diff --git a/.editorconfig b/.editorconfig index 6ddef3d3c1..a18e8d5829 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,22 +1,29 @@ # http://editorconfig.org -root = true +#root = true [*] indent_style = space indent_size = 4 -continuation_indent_size = 8 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true +[*.yml] +indent_size = 2 + [*.json] -indent_style = space indent_size = 2 [*.java] indent_style = tab -ij_continuation_indent_size = 8 -ij_java_class_count_to_use_import_on_demand = 99 -ij_java_names_count_to_use_import_on_demand = 99 -ij_java_imports_layout = $*,|,java.**,|,javax.**,|,org.**,|,com.**,|,* +ij_continuation_indent_size = 4 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 0 +ij_java_blank_lines_before_method_body = 0 +ij_java_else_on_new_line = false +ij_java_class_count_to_use_import_on_demand = 999 +ij_java_names_count_to_use_import_on_demand = 999 +ij_java_imports_layout = $*,|,java.**,|,javax.**,|,org.**,|,com.**,|,*,|,net.minecraftforge.** +ij_java_insert_inner_class_imports = true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 2bca6f5e29..9ba28460a0 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -2,40 +2,37 @@ name: I found a bug! description: "Report some other kind of issue. You should ask in the Discord first to make sure it's actually a bug with Create." labels: [ "type: bug" ] body: - - type: textarea - attributes: - label: Description - description: " - Please describe the issue with as much detail as possible. - Explain what happened, and what should have happened instead. - Add images, screenshots, or videos if they could be useful." - validations: - required: true + - type: textarea + attributes: + label: Description + description: > + Please describe the issue with as much detail as possible. + Explain what happened, and what should have happened instead. + Add images, screenshots, or videos if they could be useful. + validations: + required: true - - type: input - attributes: - label: Game Log - description: " - We need the game log for additional information about the bug. - This file can be found in the \"logs\" folder of your Minecraft folder as \"latest.log\". - Please upload the file to https://mclo.gs/ and put the link here. - Do **not** paste the *contents* of the file here, because that will make this issue very hard to read. - " - validations: - required: true + - type: input + attributes: + label: Game Log + description: > + We need the game log for additional information about the bug. + This file can be found in the \"logs\" folder of your Minecraft folder as \"latest.log\". + Please upload the file to https://mclo.gs/ and put the link here. + Do **not** paste the *contents* of the file here, because that will make this issue very hard to read. + validations: + required: true - - type: textarea - attributes: - label: Debug Information - description: " - Please run the \"/create debuginfo\" command in-game. - This will copy useful information to your clipboard that will greatly help with debugging. - Please paste this information here. - If this command does not exist, you can skip this part. - " - validations: - required: false + - type: textarea + attributes: + label: Debug Information + description: > + Please run the \"/create debuginfo\" command in-game. + This will copy useful information to your clipboard that will greatly help with debugging. + Please paste this information here. + validations: + required: true - - type: markdown - attributes: - value: "Thank you for taking the time to make a report and help improve Create!" + - type: markdown + attributes: + value: "Thank you for taking the time to make a report and help improve Create!" diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c9c7595f4f..92a8228405 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,11 @@ blank_issues_enabled: true contact_links: - - name: I have a question! - url: https://discord.gg/hmaD7Se - about: Join us on Discord and ask the community. - - name: I have a suggestion or idea! - url: https://discord.gg/hmaD7Se - about: These are best discussed with the community and submitted on Discord. - - name: Talk to us on Discord. - url: https://discord.gg/hmaD7Se - about: Ask questions and get help from the community. + - name: I have a question! + url: https://discord.gg/hmaD7Se + about: Join us on Discord and ask the community. + - name: I have a suggestion or idea! + url: https://discord.gg/hmaD7Se + about: These are best discussed with the community and submitted on Discord. + - name: Talk to us on Discord. + url: https://discord.gg/hmaD7Se + about: Ask questions and get help from the community. diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml index a5d70e2c5b..5529a532b8 100644 --- a/.github/ISSUE_TEMPLATE/crash.yml +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -2,26 +2,25 @@ name: My game crashed! description: Report an issue that crashes the game. labels: [ "type: crash" ] body: - - type: textarea - attributes: - label: Context - description: What were you doing when the game crashed? Add images, screenshots, or videos if they could be useful. - validations: - required: true + - type: textarea + attributes: + label: Context + description: What were you doing when the game crashed? Add images, screenshots, or videos if they could be useful. + validations: + required: true - - type: input - attributes: - label: Crash Report - description: " - We need the crash report to figure out why the crash happened. - This file can be found in the \"crash-reports\" folder of your Minecraft folder. - It will be the newest file there. - Please upload the file to https://mclo.gs/ and put the link here. - Do **not** paste the *contents* of the file here, because that will make this issue very hard to read. - " - validations: - required: true + - type: input + attributes: + label: Crash Report + description: > + We need the crash report to figure out why the crash happened. + This file can be found in the \"crash-reports\" folder of your Minecraft folder. + It will be the newest file there. + Please upload the file to https://mclo.gs/ and put the link here. + Do **not** paste the *contents* of the file here, because that will make this issue very hard to read. + validations: + required: true - - type: markdown - attributes: - value: "Thank you for taking the time to make a report and help improve Create!" + - type: markdown + attributes: + value: "Thank you for taking the time to make a report and help improve Create!" diff --git a/.github/config/label-actions.yml b/.github/config/label-actions.yml index f257d855d2..76d60dbc05 100644 --- a/.github/config/label-actions.yml +++ b/.github/config/label-actions.yml @@ -3,53 +3,53 @@ # ----------------------------------- ISSUES ----------------------------------- # 'env: fabric': - issues: - close: true - close-reason: 'not planned' - comment: > - **Fabric Loader**: This issue tracker is only for the Forge/NeoForge versions of Create. Since you mentioned using Fabric Loader, please reopen this issue on the [Create Fabric issue tracker](https://github.com/Fabricators-of-Create/Create/issues). Thanks! + issues: + close: true + close-reason: 'not planned' + comment: > + **Fabric Loader**: This issue tracker is only for the Forge/NeoForge versions of Create. Since you mentioned using Fabric Loader, please reopen this issue on the [Create Fabric issue tracker](https://github.com/Fabricators-of-Create/Create/issues). Thanks! 'env: hybrid server': - issues: - close: true - close-reason: 'not planned' - comment: > - **Hybrid Server Software**: Create cannot reasonably support hybrid server software, such as [MohistMC](https://mohistmc.com/), as their changes under the hood make it difficult for larger mods to function properly. If you encounter this issue on official Forge/NeoForge server software, feel free to open a new issue. Otherwise, consider reporting this issue to the hybrid server software you are using. Thanks! + issues: + close: true + close-reason: 'not planned' + comment: > + **Hybrid Server Software**: Create cannot reasonably support hybrid server software, such as [MohistMC](https://mohistmc.com/), as their changes under the hood make it difficult for larger mods to function properly. If you encounter this issue on official Forge/NeoForge server software, feel free to open a new issue. Otherwise, consider reporting this issue to the hybrid server software you are using. Thanks! 'env: outdated create version': - issues: - close: true - close-reason: 'not planned' - comment: > - **Outdated Create Version**: Since you are using an outdated Create version, please update to the latest version as it may resolve your issue. If this issue persists after updating Create, feel free to open a new issue. Thanks! + issues: + close: true + close-reason: 'not planned' + comment: > + **Outdated Create Version**: Since you are using an outdated Create version, please update to the latest version as it may resolve your issue. If this issue persists after updating Create, feel free to open a new issue. Thanks! 'env: pojav': - issues: - close: true - close-reason: 'not planned' - comment: > - **Pojav**: Create does not support Pojav or other mobile launchers due to rendering limitations. If you encounter this issue on a PC, feel free to open a new issue. Thanks! + issues: + close: true + close-reason: 'not planned' + comment: > + **Pojav**: Create does not support Pojav or other mobile launchers due to rendering limitations. If you encounter this issue on a PC, feel free to open a new issue. Thanks! 'env: unsupported minecraft version': - issues: - close: true - close-reason: 'not planned' - comment: > - **Unsupported Minecraft Version**: Unsupported Minecraft versions no longer receive Create updates. Please check the [supported Minecraft versions](https://github.com/Creators-of-Create/Create/wiki/dev.status). If you encounter this issue on a supported Minecraft version, feel free to open a new issue. Thanks! + issues: + close: true + close-reason: 'not planned' + comment: > + **Unsupported Minecraft Version**: Unsupported Minecraft versions no longer receive Create updates. Please check the [supported Minecraft versions](https://github.com/Creators-of-Create/Create/wiki/dev.status). If you encounter this issue on a supported Minecraft version, feel free to open a new issue. Thanks! # ----------------------------------- PULL REQUESTS ----------------------------------- # 'pr status: conflicts': - prs: - comment: > - @{issue-author}, this pull request has merge conflicts with the target branch. Please merge the latest changes and leave a message here so we can continue with the process of reviewing and merging this pull request. Thanks! + prs: + comment: > + @{issue-author}, this pull request has merge conflicts with the target branch. Please merge the latest changes and leave a message here so we can continue with the process of reviewing and merging this pull request. Thanks! 'pr status: waiting for author': - prs: - comment: > - @{issue-author}, a developer has left a review and requested changes. Please make the requested changes or further discuss them with the developer so this pull request can be merged. Thanks! + prs: + comment: > + @{issue-author}, a developer has left a review and requested changes. Please make the requested changes or further discuss them with the developer so this pull request can be merged. Thanks! 'pr status: wrong target': - prs: - comment: > - @{issue-author}, this pull request is targeting the wrong branch. Pull requests should target the branch corresponding to the earliest supported Minecraft version unless the changes are specific to code that only exists for a newer Minecraft version. Please change the target branch, resolve any merge conflicts, and leave a message here so we can continue with the process of reviewing and merging this pull request. Thanks! + prs: + comment: > + @{issue-author}, this pull request is targeting the wrong branch. Pull requests should target the branch corresponding to the earliest supported Minecraft version unless the changes are specific to code that only exists for a newer Minecraft version. Please change the target branch, resolve any merge conflicts, and leave a message here so we can continue with the process of reviewing and merging this pull request. Thanks! diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..41181ae923 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,38 @@ +name: Build + +on: [ workflow_dispatch, push, pull_request ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: NeoGradle Cache + uses: actions/cache@v4 + with: + path: "**/.gradle/repositories/" + key: "${{ runner.os }}-gradle-${{ hashFiles('**/libs.versions.*', '**/*.gradle*', '**/gradle-wrapper.properties') }}" + restore-keys: "${{ runner.os }}-gradle-" + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + gradle-home-cache-cleanup: true + + - name: Validate Gradle Wrapper Integrity + uses: gradle/wrapper-validation-action@v2 + + - name: Build + run: ./gradlew build + + - uses: actions/upload-artifact@v4 + with: + path: build/libs/ diff --git a/.github/workflows/gametest.yml b/.github/workflows/gametest.yml deleted file mode 100644 index 23bb055a98..0000000000 --- a/.github/workflows/gametest.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: gametest -on: [ workflow_dispatch ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - - name: checkout repository - uses: actions/checkout@v3 - - - name: setup Java - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - cache: gradle - - - name: make gradle wrapper executable - run: chmod +x ./gradlew - - - name: run gametests - run: ./gradlew prepareRunGameTestServer runGameTestServer --no-daemon diff --git a/.github/workflows/label-actions.yml b/.github/workflows/label-actions.yml index 1b59fae39c..a9fdcba0bf 100644 --- a/.github/workflows/label-actions.yml +++ b/.github/workflows/label-actions.yml @@ -1,21 +1,21 @@ -name: "Label Actions" +name: Label Actions on: - issues: - types: [labeled, unlabeled] - pull_request_target: - types: [labeled, unlabeled] + issues: + types: [ labeled, unlabeled ] + pull_request_target: + types: [ labeled, unlabeled ] permissions: - contents: read - issues: write - pull-requests: write - discussions: write + contents: read + issues: write + pull-requests: write + discussions: write jobs: - action: - runs-on: ubuntu-latest - steps: - - uses: dessant/label-actions@102faf474a544be75fbaf4df54e73d3c515a0e65 # Depend on an exact commit - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - config-path: '.github/config/label-actions.yml' + action: + runs-on: ubuntu-latest + steps: + - uses: dessant/label-actions@102faf474a544be75fbaf4df54e73d3c515a0e65 # Depend on an exact commit + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + config-path: '.github/config/label-actions.yml' diff --git a/.github/workflows/localization.yml b/.github/workflows/localization.yml index 01bed80205..6eab04cab5 100644 --- a/.github/workflows/localization.yml +++ b/.github/workflows/localization.yml @@ -1,48 +1,32 @@ # This workflow will run Crowdin Action that will upload new texts to Crowdin, download the newest translations and create a PR # For more information see: https://github.com/crowdin/github-action - name: Crowdin Action - -# Controls when the action will run. on: workflow_dispatch - # Only run when started manually - - #: - # inputs: - # uploadTranslations: - # description: "Set to true to upload (changed) translations to Crowdin" - # type: boolean - # required: true - # default: false - - #schedule: - #- cron: '0 */6 * * *' # Every 6 hours - https://crontab.guru/#0_*/6_*_*_* jobs: - synchronize-with-crowdin: - runs-on: ubuntu-latest + synchronize-with-crowdin: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: crowdin action - uses: crowdin/github-action@1.4.9 - with: - # Upload sources to Crowdin - upload_sources: true - # Upload translations to Crowdin, only use true at initial run - upload_translations: false - # Make pull request of Crowdin translations - download_translations: true - # To download translations to the specified version branch - localization_branch_name: l10n_crowdin_translations - # Create pull request after pushing to branch - create_pull_request: true - pull_request_title: 'New Crowdin translations' - pull_request_body: 'New Crowdin pull request with translations' - pull_request_base_branch_name: 'mc1.20.1/dev' - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} + - name: crowdin action + uses: crowdin/github-action@1.4.9 + with: + # Upload sources to Crowdin + upload_sources: true + # Upload translations to Crowdin, only use true at initial run + upload_translations: false + # Make pull request of Crowdin translations + download_translations: true + # To download translations to the specified version branch + localization_branch_name: l10n_crowdin_translations + # Create pull request after pushing to branch + create_pull_request: true + pull_request_title: 'New Crowdin translations' + pull_request_body: 'New Crowdin pull request with translations' + pull_request_base_branch_name: 'mc1.20.1/dev' + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..66ee2d29ec --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,30 @@ +name: Publish Release + +on: workflow_dispatch + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-disabled: true + + - name: Validate Gradle Wrapper Integrity + uses: gradle/wrapper-validation-action@v2 + + - name: Build & Publish + env: + MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} + CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }} + run: ./gradlew build publish publishMods diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..29d85b7dbd --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,52 @@ +#!/usr/bin/env groovy + +pipeline { + + agent any + + tools { + jdk "jdk-17.0.1" + } + + stages { + + stage('Setup') { + + steps { + + echo 'Setup Project' + sh 'chmod +x gradlew' + sh './gradlew clean' + } + } + + stage('Build') { + + steps { + + withCredentials([ + file(credentialsId: 'build_secrets', variable: 'ORG_GRADLE_PROJECT_secretFile') + ]) { + + echo 'Building project.' + sh './gradlew build publish --stacktrace --warn' + } + } + } + } + + post { + + always { + + archiveArtifacts artifacts: '**/build/libs/*.jar', fingerprint: true + + withCredentials([ + string(credentialsId: 'discord_webhook_url', variable: 'DISCORD_URL') + ]) { + echo 'Notifying Discord..' + discordSend description: "Build: #${currentBuild.number}", link: env.BUILD_URL, result: currentBuild.currentResult, title: env.JOB_NAME, webhookURL: env.DISCORD_URL, showChangeset: true, enableArtifactsList: false + } + } + } +} diff --git a/build.gradle b/build.gradle index 546f885679..d973ce7901 100644 --- a/build.gradle +++ b/build.gradle @@ -1,39 +1,46 @@ +import dev.ithundxr.silk.ChangelogText + plugins { - id 'eclipse' - id 'idea' - id 'maven-publish' - id 'net.minecraftforge.gradle' version "${forgegradle_version}" - id 'org.parchmentmc.librarian.forgegradle' version "${librarian_version}" - id 'org.spongepowered.mixin' version "${mixingradle_version}" - id 'com.matthewprenger.cursegradle' version "${cursegradle_version}" + id "idea" + id "eclipse" + id "maven-publish" + id "net.neoforged.moddev.legacyforge" version "2.0.74" + id "me.modmuss50.mod-publish-plugin" version "0.8.3" + id "dev.ithundxr.silk" version "0.11.15" + id "net.kyori.blossom" version "2.1.0" // https://github.com/KyoriPowered/blossom + id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.8" // https://github.com/JetBrains/gradle-idea-ext-plugin } -jarJar.enable() - -boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equals('false'); +apply from: "./gradle/java.gradle" +apply from: "gradle/property_loader.gradle" +boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equals('false') ext.buildNumber = System.getenv('BUILD_NUMBER') +String gitHash = "\"${calculateGitHash() + (hasUnstaged() ? "-modified" : "")}\"" -group = 'com.simibubi.create' -archivesBaseName = "create-${artifact_minecraft_version}" -version = mod_version + (dev && buildNumber != null ? "-${buildNumber}" : '') +base { + archivesName = "create-${artifact_minecraft_version}" + group = 'com.simibubi.create' + version = mod_version + (dev && buildNumber != null ? "-${buildNumber}" : '') +} -java.toolchain.languageVersion = JavaLanguageVersion.of(17) +boolean inMultiModWorkspace = rootProject.hasProperty('multiModWorkspace.enabled') +boolean ponderInWorkspace = rootProject.hasProperty('multiModWorkspace.ponder') -println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + ' (' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) +if (ponderInWorkspace) { + evaluationDependsOn(":ponder:Forge") +} + +project.logger.lifecycle("MultiModWorkspace ${inMultiModWorkspace ? 'enabled' : 'disabled'} for project ${project.name}.") +project.logger.lifecycle("Dependencies included in Workspace: [Ponder: ${ponderInWorkspace}]") mixin { add sourceSets.main, 'create.refmap.json' - - config 'flywheel.backend.mixins.json' - config 'flywheel.impl.mixins.json' - config 'flywheel.impl.sodium.mixins.json' config 'create.mixins.json' - - debug.verbose = true - debug.export = true } +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" + idea { module { downloadJavadoc = true @@ -41,175 +48,174 @@ idea { } } -minecraft { - if (Boolean.parseBoolean(use_parchment)) { - mappings channel: 'parchment', version: "${parchment_version}-${minecraft_version}" - } else { - mappings channel: 'official', version: "${minecraft_version}" +legacyForge { + version = "$minecraft_version-$forge_version" + + // TODO - Try turning this on later + validateAccessTransformers = false + + if (file('src/main/resources/META-INF/accesstransformer.cfg').exists()) { + accessTransformers.from "src/main/resources/META-INF/accesstransformer.cfg" } - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + parchment { + minecraftVersion = minecraft_version + mappingsVersion = parchment_version + } + + mods { + create { + sourceSet sourceSets.main + } + + if (ponderInWorkspace) { + ponder { + sourceSet project(":ponder:Common").sourceSets.main + sourceSet project(":ponder:Forge").sourceSets.main + } + } + } runs { + // applies to all the run configs below configureEach { - property 'forge.logging.markers', '' - property 'forge.logging.console.level', 'info' + systemProperty 'forge.logging.markers', '' + systemProperty 'forge.logging.console.level', 'info' + jvmArguments = ["-XX:+IgnoreUnrecognizedVMOptions", "-XX:+AllowEnhancedClassRedefinition"] + //jvmArgs("-XX:-OmitStackTraceInFastThrow") // uncomment when you get exceptions with null messages etc + //jvmArgs '-XX:+UnlockCommercialFeatures' // uncomment for profiling - property 'mixin.env.remapRefMap', 'true' - property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg" + systemProperty 'mixin.debug.export', 'true' + systemProperty 'mixin.debug.verbose', 'true' - //jvmArgs '-XX:+IgnoreUnrecognizedVMOptions', '-XX:+AllowEnhancedClassRedefinition' // uncomment with jbr - - mods { - create { - source sourceSets.main - } - } + programArgument '-mixin.config=create.mixins.json' + programArgument '-mixin.config=ponder.mixins.json' } client { - workingDirectory project.file('run') + client() + + gameDirectory = project.file('run') } server { - workingDirectory project.file('run/server') + server() + + gameDirectory = project.file('run/server') } data { - workingDirectory project.file('run') - property 'forge.logging.markers', 'REGISTRIES,REGISTRYDUMP' - property 'forge.logging.console.level', 'debug' - args '--mod', 'create', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources') + data() + + gameDirectory = project.file('run') + systemProperty 'forge.logging.markers', 'REGISTRIES,REGISTRYDUMP' + systemProperty 'forge.logging.console.level', 'debug' + programArguments.addAll("--mod", mod_id as String, "--all", "--output", file("src/generated/resources/").getAbsolutePath(), "--existing", file("src/main/resources").getAbsolutePath()) } gameTestServer { - workingDirectory project.file('run/gametest') + type = "gameTestServer" + + gameDirectory = project.file('run/gametest') // setForceExit false <- FIXME 1.20 } } } repositories { + maven { url = "https://maven.createmod.net" } // Ponder, Flywheel + maven { url = "https://maven.tterrag.com" } // Registrate + maven { url = "https://maven.blamejared.com" } // JEI, Vazkii's Mods + maven { url = "https://harleyoconnor.com/maven" } // Dynamic Trees + maven { url = "https://maven.theillusivec4.top/" } // Curios API + maven { url = "https://maven.squiddev.cc" } // CC: Tweaked + maven { url = "https://www.cursemaven.com" } + maven { url = "https://api.modrinth.com/maven" } + maven { url = "https://maven.saps.dev/releases" } // FTB Mods + maven { url = "https://maven.architectury.dev" } // Arch API maven { - // location of the maven for Registrate and Flywheel - name = 'tterrag maven' - url = 'https://maven.tterrag.com' - } - maven { - // location of the maven that hosts JEI files since January 2023 - // location of the maven for Vazkii's mods - name = "Jared's maven" - url = "https://maven.blamejared.com/" - } - /*maven { - // location of a maven mirror for JEI files, as a fallback - name = "ModMaven" - url = "https://modmaven.dev" - }*/ - maven { - // location of the maven for Dynamic Trees - url = 'https://harleyoconnor.com/maven' - } - maven { - // location of the maven for Curios API - url = "https://maven.theillusivec4.top/" - } - maven { - // location of maven for CC: Tweaked - name = "squiddev" - url = "https://squiddev.cc/maven/" - } - maven { - name = "ftb" - url = "https://maven.saps.dev/releases" - } - maven { - name = "architectury" - url = "https://maven.architectury.dev/" - } - maven { - url = "https://jm.gserv.me/repository/maven-public/" + url = "https://jm.gserv.me/repository/maven-public" // JourneyMap content { includeGroup "info.journeymap" includeGroup "mysticdrew" } } - - maven { - url = 'https://www.cursemaven.com' - content { - includeGroup "curse.maven" - } - } - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - content { - includeGroup "maven.modrinth" - } - } - maven { - name = "IThundxr's Maven" - url = "https://maven.ithundxr.dev/releases" - } - mavenCentral() mavenLocal() flatDir { - dirs 'libs' + dirs "libs" } } dependencies { - minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" - jarJar("com.tterrag.registrate:Registrate:${registrate_version}") { - jarJar.ranged(it, '[MC1.19.3-1.1.10,)') + version { + strictly "[MC1.20-1.3.3,)" + } } - jarJar("dev.engine_room.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") { - jarJar.ranged(it, '[1.0,2.0)') + jarJar("dev.engine-room.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") { + version { + strictly "[1.0,2.0)" + } } - compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")) - implementation(jarJar("io.github.llamalad7:mixinextras-forge:0.4.1")) { - jarJar.ranged(it, "[0.4.1,)") + jarJar("net.createmod.ponder:Ponder-Forge-${minecraft_version}:${ponder_version}") { + version { + strictly "[${ponder_version},)" + } } - implementation fg.deobf("com.tterrag.registrate:Registrate:${registrate_version}") + implementation(jarJar("io.github.llamalad7:mixinextras-forge:${mixin_extras_version}")) { + version { + strictly "[${mixin_extras_version},)" + } + } - compileOnly fg.deobf("dev.engine_room.flywheel:flywheel-forge-api-${flywheel_minecraft_version}:${flywheel_version}") - runtimeOnly fg.deobf("dev.engine_room.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") + modImplementation("com.tterrag.registrate:Registrate:${registrate_version}") - compileOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}-common-api:${jei_version}") - compileOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}-forge-api:${jei_version}") - runtimeOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}-forge:${jei_version}") + modCompileOnly("dev.engine-room.flywheel:flywheel-forge-api-${flywheel_minecraft_version}:${flywheel_version}") + modRuntimeOnly("dev.engine-room.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") + modRuntimeOnly("dev.engine-room.vanillin:vanillin-forge-${flywheel_minecraft_version}:${flywheel_version}") - compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${curios_minecraft_version}:api") - runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${curios_minecraft_version}") + if (ponderInWorkspace) { + implementation project(":ponder:Common") + implementation project(":ponder:Forge") + } else { + modImplementation("net.createmod.ponder:Ponder-Forge-${minecraft_version}:${ponder_version}") + } - if (cc_tweaked_enable.toBoolean()) { - compileOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-core-api:${cc_tweaked_version}") - compileOnly fg.deobf("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge-api:${cc_tweaked_version}") - runtimeOnly fg.deobf("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge:${cc_tweaked_version}") - } + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:${mixin_extras_version}")) + + // modCompileOnly("mezz.jei:jei-${jei_minecraft_version}-common-api:${jei_version}") + // modCompileOnly("mezz.jei:jei-${jei_minecraft_version}-forge-api:${jei_version}") + modImplementation("mezz.jei:jei-${jei_minecraft_version}-forge:${jei_version}") + + modCompileOnly("top.theillusivec4.curios:curios-forge:${curios_version}+${curios_minecraft_version}:api") + modRuntimeOnly("top.theillusivec4.curios:curios-forge:${curios_version}+${curios_minecraft_version}") + + if (cc_tweaked_enable.toBoolean()) { + compileOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-core-api:${cc_tweaked_version}") + modCompileOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge-api:${cc_tweaked_version}") + modRuntimeOnly("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge:${cc_tweaked_version}") + } if (dynamic_trees_enable.toBoolean()) { - compileOnly fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-${dynamic_trees_minecraft_version}:${dynamic_trees_version}") + modCompileOnly("com.ferreusveritas.dynamictrees:DynamicTrees-${dynamic_trees_minecraft_version}:${dynamic_trees_version}") } - // implementation fg.deobf("curse.maven:ic2-classic-242942:5555152") not updated to 1.20 - // implementation fg.deobf("curse.maven:druidcraft-340991:3101903") not updated to 1.20 - // implementation fg.deobf("com.railwayteam.railways:railways-1.19.2-1.6.4:all") { transitive = false } + // modImplementation("curse.maven:ic2-classic-242942:5555152") + // modImplementation("curse.maven:druidcraft-340991:3101903") + // modImplementation("com.railwayteam.railways:railways-1.19.2-1.6.4:all") { transitive = false } - // implementation fg.deobf("dev.architectury:architectury-forge:9.1.12") - // implementation fg.deobf("dev.ftb.mods:ftb-chunks-forge:2001.3.1") - // implementation fg.deobf("dev.ftb.mods:ftb-teams-forge:2001.3.0") - // implementation fg.deobf("dev.ftb.mods:ftb-library-forge:2001.2.4") + modRuntimeOnly("dev.architectury:architectury-forge:9.1.12") + modImplementation("dev.ftb.mods:ftb-chunks-forge:2001.3.1") + modImplementation("dev.ftb.mods:ftb-teams-forge:2001.3.0") + modImplementation("dev.ftb.mods:ftb-library-forge:2001.2.4") + + implementation fg.deobf("curse.maven:journeymap-32274:5457831") + // implementation fg.deobf("ignored:journeymap-1.20.1-5.10.1-forge") - // implementation fg.deobf("curse.maven:journeymap-32274:5457831") - // implementation fg.deobf("ignored:journeymap-1.20.1-5.10.1-forge") - // runtimeOnly fg.deobf("curse.maven:framedblocks-441647:5629578") // runtimeOnly fg.deobf("curse.maven:galosphere-631098:4983871") // runtimeOnly fg.deobf("curse.maven:elementary-ores-332609:4622524") @@ -255,29 +261,37 @@ dependencies { // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings // This allows 'Settings > Build, Execution, and Deployment > Build Tools > Gradle > Build and run using' set to IntelliJ to work correctly if (!Boolean.getBoolean('idea.sync.active')) { - annotationProcessor "org.spongepowered:mixin:${mixin_version}:processor" + annotationProcessor "org.spongepowered:mixin:0.8.5:processor" } } -sourceSets.main.java { - if (!cc_tweaked_enable.toBoolean()) { - exclude 'com/simibubi/create/compat/computercraft/implementation/**' - } +sourceSets.main { + java { + if (!cc_tweaked_enable.toBoolean()) { + exclude 'com/simibubi/create/compat/computercraft/implementation/**' + } + } + + resources { + srcDir 'src/generated/resources' + exclude '.cache/' + } + + blossom.javaSources { + property("version", build_info_mod_version) + property("gitCommit", gitHash.toString()) + } } -sourceSets.main.resources { - srcDir 'src/generated/resources' - exclude '.cache/' -} +processResources { + def buildProps = project.properties.clone() -// Workaround for SpongePowered/MixinGradle#38 -afterEvaluate { - tasks.configureReobfTaskForReobfJar.mustRunAfter(tasks.compileJava) - tasks.configureReobfTaskForReobfJarJar.mustRunAfter(tasks.compileJava) -} + // Replaces FML's magic file.jarVersion string with the correct version at build time. + buildProps.put('file', [jarVersion: project.version]) -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand buildProps + } } compileJava { @@ -285,115 +299,91 @@ compileJava { } jar { - archiveClassifier = 'slim' - manifest { - attributes([ - 'Specification-Title': 'create', - 'Specification-Vendor': 'simibubi', - 'Specification-Version': '1', - 'Implementation-Title': project.jar.archiveBaseName, - 'Implementation-Version': project.jar.archiveVersion, - 'Implementation-Vendor': 'simibubi', - 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), - 'MixinConfigs': 'create.mixins.json' - ]) + from('LICENSE') { + rename { "${it}_${archivesBaseName}" } } + + manifest.attributes([ + "MixinConfigs": "create.mixins.json", + "Git-Hash" : gitHash + ]) } -task jarJarRelease { - group = 'jarjar' - doLast { - tasks.jarJar { - archiveClassifier = '' - } - } - finalizedBy tasks.jarJar +tasks.named("sourcesJar") { + manifest.attributes([ + "Git-Hash": gitHash + ]) } -java { - withSourcesJar() - withJavadocJar() -} - -void addLicense(jarTask) { - jarTask.from('LICENSE') { - rename { "${it}_${project.archivesBaseName}" } - } -} - -jar.finalizedBy('reobfJar') -tasks.jarJar.finalizedBy('reobfJarJar') - -addLicense(jar) -addLicense(tasks.jarJar) - -publishing { +project.publishing { publications { mavenJava(MavenPublication) { - artifactId = archivesBaseName - + artifactId base.archivesName.get() from components.java - fg.component(it) - jarJar.component(it) } } repositories { + if (project.hasProperty("mavenUsername") && project.hasProperty("mavenPassword") && project.hasProperty("mavenURL")) { + project.logger.lifecycle("Adding maven from secrets") + + maven { + credentials { + username = project.property("mavenUsername") as String + password = project.property("mavenPassword") as String + } + url = URI.create(project.property("mavenURL") as String) + } + } + if (project.hasProperty('mavendir')) { maven { url mavendir } } } } -String getChangelogText() { - def changelogFile = file('changelog.txt') - String str = '' - int lineCount = 0 - boolean done = false - changelogFile.eachLine { - if (done || it == null) { - return - } - if (it.size() > 1) { - def temp = it - if (lineCount == 0) { - temp = "Create ${version}" - temp = "Create v${mod_version}  for Minecraft ${minecraft_version}
" - } else if (it.startsWith('-')) { - temp = "   $temp
" - temp = temp.replaceAll("(\\S+\\/\\S+)#([0-9]+)\\b", "\$0"); - temp = temp.replaceAll("#([0-9]+)\\b(?!<\\/a>)", "\$0"); - } else { - temp = "

$temp

" - } - str += temp - lineCount++ - } else { - str += "

Please submit any Issues you come across on the Issue Tracker.

" - done = true - } +publishMods { + file = jar.archiveFile + changelog = ChangelogText.getChangelogText(project).toString() + type = STABLE + displayName = "$mod_name $minecraft_version $mod_version" + modLoaders.add("forge") + modLoaders.add("neoforge") + +// curseforge { +// accessToken = providers.environmentVariable("CURSEFORGE_TOKEN") +// projectId = "328085" +// minecraftVersions.add(minecraft_version) +// } + + modrinth { + accessToken = providers.environmentVariable("MODRINTH_TOKEN") + projectId = "LNytGWDc" + minecraftVersions.add(minecraft_version) } - return str } -// changelog debugging -// new File("changelog.html").write getChangelogText() -// tasks.curseforge.enabled = !dev && project.hasProperty('simi_curseforge_key') -// curseforge { -// if (project.hasProperty('simi_curseforge_key')) { -// apiKey = project.simi_curseforge_key -// } -// -// project { -// id = project.projectId -// changelog = System.getenv('CHANGELOG') == null || System.getenv('CHANGELOG').equals('none') ? getChangelogText() : System.getenv('CHANGELOG') -// changelogType = 'html' -// releaseType = project.curse_type -// mainArtifact(shadowJar) { -// displayName = "Create - ${version}" -// } -// relations { -// optionalDependency 'jei' -// } -// } -// } +String calculateGitHash() { + try { + def output = providers.exec { + commandLine("git", "rev-parse", "HEAD") + } + return output.standardOutput.asText.get().trim() + } catch (Throwable ignored) { + return "unknown" + } +} + +boolean hasUnstaged() { + try { + def output = providers.exec { + commandLine("git", "status", "--porcelain") + } + String result = output.standardOutput.asText.get().replace("/M gradlew(\\.bat)?/", "").trim() + if (!result.isEmpty()) + println("Found stageable results:\n ${result}\n") + return !result.isEmpty() + } catch (Throwable ignored) { + return false + } +} diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000000..bab0e30c5c --- /dev/null +++ b/changelog.md @@ -0,0 +1,172 @@ +------------------------------------------------------ +Create 6.0.0 +------------------------------------------------------ + +_Now using Flywheel 1.0_ + +#### Additions + +- Chain conveyor +- Item hatch +- Packager and Re-packager +- Cardboard packages +- Package frogport +- Package postbox +- Stock link +- Stock ticker +- Redstone requester +- Factory gauge +- Table cloths and covers +- Pulse timer +- Desk bell +- Pulp and the cardboard ingredient +- Cardboard armor set +- Cardboard sword +- Package filter +- Cardboard block +- Cherry and bamboo windows +- Industrial iron window +- Weathered iron block and windows + +#### Art Changes + +- Palette and model updates to all copper-based components +- Rope and hose pulley motion now uses a scrolling texture +- Increased vertical size of train and contraption controls to a full block +- Updates to display and redstone links +- Updates to metal sheet items +- Copper roof blocks now use connected textures +- Added missing shaft detail to the backtank armor +- Updates to various UI screens and components +- Bars and window item models are now consistent with vanilla + +#### Gameplay Changes + +- Redstone links are now andesite tier +- All links now use a new ingredient item, the transmitter +- New advancement chain for high logistics components +- New ponder scenes and category for high logistics components +- Tracks and Trains now have special integration with FTBChunks and Journeymap +- Depots can now be used as storage blocks on contraptions +- Brass tunnels now try to distribute an item more quickly when it first arrives +- Brass tunnels now always prefer filtered sides over non-filtered sides +- Added train schedule instructions for delivering or retrieving packages +- Basins no longer limit to 16 items per slot +- Mechanical crafters waste less time on empty animation frames +- In common cobblegen scenarios, stationary drills now skip breaking blocks and just insert the result items into open + inventories directly below +- Held clipboards can now copy entries from other in-world clipboards +- Filters, Clipboards and Schedules can now be copyied in the crafting table +- Metal ladders no longer require a wall if another ladder block is above them +- Bells assembled to elevator contraptions now activate when arriving at a floor +- Sliding doors placed in front of contraption-mounted sliding doors now open and close automatically +- Fully outlined text on filter slots for better readability +- Added recipes where cardboard substitutes leather +- Play at most four steam engine sounds at once per side of a boiler +- Increased default max rope length to 384 +- Implemented a system for generating certain recipes at runtime to improve mod compat +- Boiler gauge now disappears when blocks are clipping into it +- Added a keybind that opens a radial menu for rotating blocks with the wrench +- Wood cutting recipes in mechanical saws +- Added pressing recipes for coarse dirt and rooted dirt which both produce dirt paths (#7186) +- Updated JEI integration and added potion fluids to the JEI sidebar (#6934) +- Chain Drives can now be crafted from zinc nuggets +- Redstone lamps can now be picked up with the wrench +- New compatibility recipes for Immersive Engineering +- Added missing deploying recipes for copper oxidisation +- Framed and tiled glass panes can now be obtained via stonecutting +- Schematicannon on 'replace blocks with empty' now send block updates at the edges after printing +- The player hitbox used in contraption collision is now slightly shorter + +#### Bug Fixes + +- Deployers can no longer take a seat +- Fixed contraptions keeping pressure plates and tripwires activated (#7255) +- Steam engine placement assist now shows a normal shaft +- Fixed schedule screen not showing tooltips in the entry editor +- Fixed tracks creating signal block intersections despite being in different dimensions +- Fixed non-effect fans resetting processed belt items (#7298) +- Fixed mechanical saw considering scaffolding as leaves +- Fixed entity name display source not working for players on signs +- Fixed certain blocks messing up the order scheduled ticks (#7141) +- Fixed unbreakable superglue not being usable (#6253) +- Fixed update suppression (#7176) +- Fixed comparator output of depots ignoring the items' max stack size (#7179) +- Fixed deployers retaining the damage attribute of their last held weapon (#4870) +- Fixed an exploit allowing people to create clipboards that execute commands (#7218) +- Fixed redstone links not updating their redstone output when they've been taken out of receiver mode (#7226) +- Fixed rare crash related to sliding doors (#6184) +- Verify that schematics are gzip-encoded before trying to read from them (#6087) +- Fixed ConditionContext nbt in trains containing a large number of empty tags +- Fixed deployers not placing fish from fish buckets (#3705) +- Fixed gasses not being visible in basins and item drains (#7236) +- Set vault capacity config limit to 2048 slots +- Fixed InventorySorter able to take items from ghost/filter inventories +- Fixed typo in better end compat recipe +- FTB buttons no longer show in create screens +- Fixed mechanical arm interactions with jukeboxes (#5902) +- Fixed toolboxes not giving a comparator output signal (#6973) +- Fixed copper slabs and stairs being missing from the respective tags (#3080) +- Fixed Fix waterlogged bracketed kinetics dropping the bracket (Fabricators-of-Create#1552) +- Switched away from using streams in ContraptionCollider fixing a rare crash (#5043) +- Fixed pumps not placing fluids into flowing fluids of the same type (#5884) +- Fixed schematicannons not consuming the right number of group items (#6983) +- Fixed backtanks getting incompatible enchants via smithing tables (#6687) +- Fixed Lectern Controllers storing ItemStacks from nbt (#7143) +- Optimized spout recipe generation by avoiding filling non-empty items (#7274) +- Fixed crash when dying nixie tubes with dye depots dyes (#6694) +- Fix enchantments getting trimmed from non-filter items (#7216) +- Fixed sandpaper polishing recipes not working in sequenced assembly recipes (#7259) +- Fixed mechanical drills and saws using the friendly creatures sound source instead of the blocks sound source (#7038) +- Fixed backtank crashing on ctrl+pick block (#7284) +- Improved memory usage of drain category in JEI (#7277) +- Fixed getSize() throwing an error on newly loaded display link peripherals (#7059) +- Fixed inability to mill cactus when Quark is installed (#7215) +- Fixed rare spout crash and offset rendering (#7025) +- Fixed deploying food resulting in missing particles and not returning the correct items (#7288) +- Fixed trains not properly pathfinding to stations with an opposing signal just behind the destination +- Fixed stations voiding schedules when disassembling the train +- Fixed lighting on signal block indicators +- Fixed vaults and tanks rotated in place not updating their multiblock correctly +- Hose pulley now deletes lilypads and other surface foliage +- Fixed crushing wheels not applying looting to killed entities +- Updated contraption chunkban protections, corrected limits and made them much harder to hit + +#### API Changes + +- Versioning change: `major.minor.patch`, starting with `6.0.0` +- Ponder is now a separate library mod. It comes shipped with the create jar. +- Added `#create:chain_rideable` to mark items as valid for riding a chain with +- Added `#create:invalid_for_track_paving` for items +- Added `#create:sugar_cane_variants` to allow the mechanical saw to work with custom sugarcane variants (#7263) +- Added `#create:not_harvestable` to disallow blocks that the mechanical harvester would otherwise try to harvest +- New API for custom storage block behaviour on contraptions. + For simple cases, create provides the `#create:simple_mounted_storage` and `#create:chest_mounted_storage` block tags. +- Added `#create:non_breakable` to mark blocks that cannot be broken by block-breaking kinetics +- Removed LangMerger and related classes +- Implemented an api to allow mods to register schematic requirements, partial safe nbt and contraption transforms + without implementing interfaces (#4702) +- Add a method that developers can override to change the icon in goggle tooltips +- Refactored Item Attributes types, Fan processing types and Arm interaction points, all 3 now use registries +- Synced AllPortalTracks with Create Fabric +- Implemented DyeHelper api (#7265) +- Implemented api to add custom block train conductors (#7030) +- Convert Potato Cannon projectile types into a dynamic registry + - Everything can be done with datapacks now, and there is no need to write a mod unless you need to add new + Render Modes, Entity Hit Actions or Block Hit Actions +- Reworked the AttachedRegistry class into SimpleRegistry and added Provider functionality +- Exposed all custom registries as API +- Exposed a handful of previously internal classes to the API, and gave them some cleanup + - BlockSpoutingBehaviour + - MovementBehaviour + - MovingInteractionBehaviour + - DisplaySource + - DisplayTarget + - ContraptionMovementSetting + - BoilerHeater + - PortalTrackProvider + - BlockMovementChecks + - ContraptionType + - MountedDispenseBehavior + - BlockStressValues + - OpenPipeEffectHandler diff --git a/gradle.properties b/gradle.properties index df343accbf..a32e86b568 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,32 +2,31 @@ # This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs = -Xmx3G org.gradle.daemon = false +org.gradle.parallel = true +org.gradle.caching = true # mod version info -mod_version = 0.5.2 +# build_info_mod_version is the version that gets filled into CreateBuildInfo.java +mod_version = 6.0.0 +build_info_mod_version = 6.0.0 artifact_minecraft_version = 1.20.1 minecraft_version = 1.20.1 forge_version = 47.2.6 -# build dependency versions -forgegradle_version = [6.0.16,6.2) -mixingradle_version = 0.7.+ -mixin_version = 0.8.5 -librarian_version = 1.+ -cursegradle_version = 1.4.0 parchment_version = 2023.09.03 - use_parchment = true # dependency versions registrate_version = MC1.20-1.3.3 flywheel_minecraft_version = 1.20.1 -flywheel_version = 1.0.0-beta-145 +flywheel_version = 1.0.0-beta-212 jei_minecraft_version = 1.20.1 jei_version = 15.19.0.85 curios_minecraft_version = 1.20.1 curios_version = 5.3.1 +ponder_version = 1.0.34 +mixin_extras_version = 0.4.1 cc_tweaked_enable = true cc_tweaked_minecraft_version = 1.20.1 @@ -37,9 +36,9 @@ dynamic_trees_enable = true dynamic_trees_minecraft_version = 1.20.1 dynamic_trees_version = 1.3.0-BETA13 -# curseforge information -projectId = 328085 -curse_type = beta - -# github information -github_project = Creators-of-Create/Create +# mod options +mod_id = create +mod_name = Create +mod_author = simibubi +mod_description = Technology that empowers the player. +mod_license = MIT diff --git a/gradle/java.gradle b/gradle/java.gradle new file mode 100644 index 0000000000..86c9d96509 --- /dev/null +++ b/gradle/java.gradle @@ -0,0 +1,39 @@ +apply plugin: 'java' + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) +java.withSourcesJar() +java.withJavadocJar() + +jar { + manifest { + attributes([ + 'Specification-Title' : mod_name, + 'Specification-Vendor' : mod_author, + 'Specification-Version' : project.jar.archiveVersion, + 'Implementation-Title' : project.name, + 'Implementation-Version' : project.jar.archiveVersion, + 'Implementation-Vendor' : mod_author, + 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + 'Timestampe' : System.currentTimeMillis(), + 'Built-On-Java' : "${System.getProperty('java.vm.version')} (${System.getProperty('java.vm.vendor')})", + 'Built-On-Minecraft' : minecraft_version + ]) + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.encoding = 'UTF-8' + it.options.release = 17 +} + +// Disables Gradle's custom module metadata from being published to maven. The +// metadata includes mapped dependencies which are not reasonably consumable by +// other mod developers. +tasks.withType(GenerateModuleMetadata) { + enabled = false +} + +javadoc { + // Suppress annoying warnings when generating JavaDoc files. + options.addStringOption('Xdoclint:none', '-quiet') +} diff --git a/gradle/property_loader.gradle b/gradle/property_loader.gradle new file mode 100644 index 0000000000..0f28530156 --- /dev/null +++ b/gradle/property_loader.gradle @@ -0,0 +1,48 @@ +/* + This module can inject build properties from a JSON file. Each property in the + JSON file will be mapped to a build property using the key of that property. + Property keys ending with _comment will be skipped. + + If a secretFile property exists and points to a valid JSON file that file will + be automatically loaded. You can manually load a file using the loadProperties + method. +*/ +import groovy.json.JsonSlurper + +// Auto detects a secret file and injects it. +if (project.rootProject.hasProperty("secretFile")) { + project.logger.lifecycle("Automatically loading properties from the secretFile") + final def secretsFile = project.rootProject.file(project.rootProject.getProperty("secretFile")) + + if (secretsFile.exists() && secretsFile.name.endsWith(".json")) { + loadProperties(secretsFile) + } +} + +// Loads properties using a specified json file. +def loadProperties(propertyFile) { + if (propertyFile.exists()) { + propertyFile.withReader { + Map propMap = new JsonSlurper().parse it + + for (entry in propMap) { + + // Filter entries that use _comment in the key. + if (!entry.key.endsWith("_comment")) { + + project.ext.set(entry.key, entry.value) + } + } + + project.logger.lifecycle("Successfully loaded " + propMap.size() + " properties") + propMap.clear() + } + } else { + project.logger.warn("The property file " + propertyFile.getName() + " could not be loaded. It does not exist.") + } +} + +// Allows other scripts to use these methods. +ext { + loadProperties = this.&loadProperties +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e2..a4b76b9530 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 309b4e18db..e2847c8200 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb43..f5feea6d6b 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,9 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +134,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +205,11 @@ fi # 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. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f13..9d21a21834 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/settings.gradle b/settings.gradle index c339a6321c..fbb0422deb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,17 +2,14 @@ pluginManagement { repositories { gradlePluginPortal() mavenCentral() - maven { - name = 'MinecraftForge' - url = 'https://maven.minecraftforge.net/' - } + maven { url = 'https://maven.minecraftforge.net/' } maven { url = 'https://repo.spongepowered.org/repository/maven-public' } maven { url = 'https://maven.parchmentmc.org' } } } plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } rootProject.name = 'Create' diff --git a/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa b/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa index 8aded56d1a..2455de35af 100644 --- a/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa +++ b/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa @@ -1,4 +1,4 @@ -// 1.20.1 2024-10-09T12:24:59.2666858 Create's Sequenced Assembly Recipes +// 1.20.1 2025-02-02T11:59:39.5960908 Create's Sequenced Assembly Recipes dbaca5a5aa312f3bc7b826e51e665d32e798a5d7 data/create/recipes/sequenced_assembly/precision_mechanism.json dacafdb106304d183b00e21fb01517ac45eca800 data/create/recipes/sequenced_assembly/sturdy_sheet.json 1274315b5c570722d6f5b2ed7f5e53fe01b6288a data/create/recipes/sequenced_assembly/track.json diff --git a/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c b/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c index 65c9cefcc3..dd7d0033b0 100644 --- a/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c +++ b/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c @@ -1,4 +1,4 @@ -// 1.20.1 2025-01-04T09:59:54.9600791 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] +// 1.20.1 2025-02-25T19:53:55.428995432 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] 60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json 6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json @@ -15,24 +15,32 @@ c9aa3f6acdcadfcd6f0c48457ddafcdd9ff37104 assets/create/blockstates/andesite_enca 1299bde31535b381cc2d9b40f58097702bd12b92 assets/create/blockstates/andesite_ladder.json afff577673aec43b9a596c4663024cb35127e0c3 assets/create/blockstates/andesite_pillar.json 0d47d0816051dd63837c689de8b838dc1639d2fd assets/create/blockstates/andesite_scaffolding.json +beb5fd89e2c6701bca3c7c579b1b1f965a7ff71a assets/create/blockstates/andesite_table_cloth.json 67c4f7802f0854d24bb29019682b1d0a2f335a15 assets/create/blockstates/andesite_tunnel.json 542af96eb0c1e34df81f15fae7dbbaf4f81287f3 assets/create/blockstates/asurine.json 7f07775d89e3bea45d7161d289daf15470e7f544 assets/create/blockstates/asurine_pillar.json +a850a113b4cfd8f1c827905b79b8629c40de12b0 assets/create/blockstates/bamboo_window.json +dfaec148d3bb21efb2ef7106a2d04454c4134303 assets/create/blockstates/bamboo_window_pane.json 9c62e0ce5d85ac4081bc04c85db7676b996b0f12 assets/create/blockstates/basin.json a97910c7516e7cedec9e34eca51f1183f1e3e681 assets/create/blockstates/belt.json 0ea03133af234921a3313f52521d8cfd02bf5d81 assets/create/blockstates/birch_window.json 2003c43151b731bf19cae58290c63bcb3785848a assets/create/blockstates/birch_window_pane.json c8b65faf51122eb411f5895e718869da9b260c2e assets/create/blockstates/black_nixie_tube.json +fdc7dad3daa231e3d1906a1f0a84f254a31cf2c7 assets/create/blockstates/black_postbox.json 980ae9ba3f6d4e0faea8f3878985f9a9dadc0796 assets/create/blockstates/black_sail.json da3ad0225984a0dcbfb4ed800e307e45aff5aaa1 assets/create/blockstates/black_seat.json +1ea958c40f0cbf63c31d9b5422b6b86f9268e393 assets/create/blockstates/black_table_cloth.json 0083f6aa3fda2c7ebb2e5f2a032e740cf3ae3846 assets/create/blockstates/black_toolbox.json 28f2fb355e80171403e540afd2aed44e9c19659a assets/create/blockstates/black_valve_handle.json 06ecd28cd97f4e8200dc396858695cad57b871c8 assets/create/blockstates/blaze_burner.json 37caf031254b5171a1fbfe9906f4bc65e8dbc909 assets/create/blockstates/blue_nixie_tube.json +80cd0b998a2e21d6ca77419139c24a7ad97c2538 assets/create/blockstates/blue_postbox.json d540f0f23e0d7c03f8e147cf3eebbaf7caec9f93 assets/create/blockstates/blue_sail.json d2fdb432bb037de781260c789e905b223fab408c assets/create/blockstates/blue_seat.json +27241e0fd5a034c461f6920f94b852c6e825ce56 assets/create/blockstates/blue_table_cloth.json f91092da79b69fece9583ccc15350612f439ee1b assets/create/blockstates/blue_toolbox.json e330efa253172b315f73401ed8f2c39270ba90d3 assets/create/blockstates/blue_valve_handle.json +a02d3059619edf0bd19dbf397cb35f0f8b8fb20e assets/create/blockstates/bound_cardboard_block.json 5c7065e56a831e0957b6531d50f720e9efb64309 assets/create/blockstates/brass_bars.json d49d09f1026f816bb05a5dc13c806b860f2eb07a assets/create/blockstates/brass_belt_funnel.json 5a2551315557447abc579cf9225e3a12d9a46641 assets/create/blockstates/brass_block.json @@ -44,14 +52,21 @@ bac88b313b63acfc77c25b1463276a714f22f336 assets/create/blockstates/brass_encased a408005aae4c1caa7aaae5a0ddf9d1ad73cd0254 assets/create/blockstates/brass_funnel.json 1e8eba1ac6a0beb744f8b5feb96bbe5f3a75f214 assets/create/blockstates/brass_ladder.json 6d210298b9d80ae69aa03b09aa73b92e14b9ab1b assets/create/blockstates/brass_scaffolding.json +61f5242e85c36ecf0f7963954236c60596ec9cbe assets/create/blockstates/brass_table_cloth.json 8ee948f9e87b82bb27aaecc522127fa1297b3d9d assets/create/blockstates/brass_tunnel.json debf33346bf410216f21082e1e8d07aa6250b84c assets/create/blockstates/brown_nixie_tube.json +bc6719074acbec67e345005aeee352fd7bc54c09 assets/create/blockstates/brown_postbox.json 1334fc9e71d9f2a6117f448817263467a9c695de assets/create/blockstates/brown_sail.json 19524b2c0672632e63372f405a87dbea35f1d160 assets/create/blockstates/brown_seat.json +41a93cdd7ef066a844b750b657dce766df29d301 assets/create/blockstates/brown_table_cloth.json 1ffc38bf682e84aad4cb300c573375eb0cdcc434 assets/create/blockstates/brown_toolbox.json 440b29e1dffa4374ddc1aed444bff18a485bc1cb assets/create/blockstates/brown_valve_handle.json 2064534de4791b339fdcd4ef3a8129a2e233ec50 assets/create/blockstates/calcite_pillar.json +6a3e661d54423af7a8d642b813deb8f5331013c5 assets/create/blockstates/cardboard_block.json 060c957b28afed9f4e0954cbef7e80cbf4b99f58 assets/create/blockstates/cart_assembler.json +fab98b93ad9b78312742daca83c2575db40fce98 assets/create/blockstates/chain_conveyor.json +178c651f169ffc32556738bb5c19b4a746cfa085 assets/create/blockstates/cherry_window.json +b1796f89bd7785d00dc8618ca90d760da4f258bb assets/create/blockstates/cherry_window_pane.json c7eca70054241944171b1d4ffcba0376b071ec62 assets/create/blockstates/chocolate.json 9eb989b0a0545af9efd052d1f127b2ec28a972d1 assets/create/blockstates/chute.json b5170d754ce5f07ea2b4646eb07c099c50bae249 assets/create/blockstates/clipboard.json @@ -71,6 +86,7 @@ df3103dfc1c3ba7a9573229d009cb0de4925df16 assets/create/blockstates/copper_scaffo 1ea8fdb990f8cda1762ab69ac38ea3161a835227 assets/create/blockstates/copper_shingle_slab.json 7c35bb802099d6bb5d92eafd8cbb7ea146979a2e assets/create/blockstates/copper_shingle_stairs.json 4d3d29e8a74bf103da39e76a1466b03eb5dcf916 assets/create/blockstates/copper_shingles.json +5c5ba06bf5b0a2c57d0aa42e85880f36d9694a78 assets/create/blockstates/copper_table_cloth.json 7db7a0d81887091ca889f40bb8a508d3098c5164 assets/create/blockstates/copper_tile_slab.json c0b7eca017242913d156e4623147add0d03574f6 assets/create/blockstates/copper_tile_stairs.json 9a9f03140a57a7a8903d3e1b159bdc052566a6ec assets/create/blockstates/copper_tiles.json @@ -202,8 +218,10 @@ beb9e47f8d811c2146f68daf992fb805342a65cb assets/create/blockstates/cut_veridium. c11f09df4a23e951bdf9a345515183f4fac7cde3 assets/create/blockstates/cut_veridium_stairs.json 3aa6f5e613ff73952e3de00408051f92316e7f81 assets/create/blockstates/cut_veridium_wall.json bb627b2e78dba6833cf2d357033f253fc89aa1b8 assets/create/blockstates/cyan_nixie_tube.json +21b830af3dc477c527885d6590e0a8419ffb4fa2 assets/create/blockstates/cyan_postbox.json f1061b8f9757374d6608fda07e301a2623e79f72 assets/create/blockstates/cyan_sail.json 538c6d95da5cc460e99c91647dac61726a91479f assets/create/blockstates/cyan_seat.json +c2fc64da0466fe9daa63c18c35221736c1e091df assets/create/blockstates/cyan_table_cloth.json c4d84b719762aca46cdb8decddfeb97dcc50676c assets/create/blockstates/cyan_toolbox.json 477d32008d5aa6ed5a6825a70b9bb7d976e7d0fc assets/create/blockstates/cyan_valve_handle.json f4d7f5a38db9b92399a81f49ff1787d025c6f41f assets/create/blockstates/dark_oak_window.json @@ -212,6 +230,7 @@ c705f9cd47042867c87fab3a898a57152dec6dd5 assets/create/blockstates/deepslate_pil 1073fe9e96ea170c81b613835064034f967945b5 assets/create/blockstates/deepslate_zinc_ore.json d0ec99fdd534e1f3a84cc51fa914d3b74fb2c96a assets/create/blockstates/deployer.json 4f18fd003ca756417fd036bd8b66f323e0ca4852 assets/create/blockstates/depot.json +5b933ed479ec646f8cc2cd3739405c34737d517c assets/create/blockstates/desk_bell.json 26a5a4c176e75b1f48f3eb653a45c23e606f07b4 assets/create/blockstates/diorite_pillar.json d45d92164f81fd42cc1f8c6ba4ac25df0fca79b1 assets/create/blockstates/display_board.json a65771f280051a884725073d14a831539bc0d658 assets/create/blockstates/display_link.json @@ -228,6 +247,7 @@ d47bc65703e9582cc710e6408fb565e16d3514a6 assets/create/blockstates/encased_fan.j 6ee73ff3608d51fdad6e9810feee66ed1773b81c assets/create/blockstates/exposed_copper_tile_slab.json f93e4059876bfc6d70b9fa2bc24d8e3d6943d56f assets/create/blockstates/exposed_copper_tile_stairs.json 5299b4f7b9b3490872e8c26a6b212e14dd05fd9a assets/create/blockstates/exposed_copper_tiles.json +4b30365ed77db9c5754eeda5fee81d47b568b946 assets/create/blockstates/factory_gauge.json f1a03ede031d8c4e33a4d07c529e71936da9dc6d assets/create/blockstates/fake_track.json 21fa4a1bf4ee851e090a21c97c9a38d18cfddf0d assets/create/blockstates/fluid_pipe.json 185e6367c5c5b3632e54148c74987057cbfccaca assets/create/blockstates/fluid_tank.json @@ -244,13 +264,17 @@ ff9f56912d8ac4069df90505232820f9c45f5e06 assets/create/blockstates/gantry_carria 5a193991f33a1af8659192f3693e4d8d3ed0082b assets/create/blockstates/glass_fluid_pipe.json e3f2a093c436cb65c5a7ac049a14cc4dadb22526 assets/create/blockstates/granite_pillar.json 921cf220c44a67195c90a30c4c296e65311738da assets/create/blockstates/gray_nixie_tube.json +024b9e82cc5802e8a9ff22880f8098d07fd192e7 assets/create/blockstates/gray_postbox.json 30ba031a6b5a327d2a4caa12169676da573c2133 assets/create/blockstates/gray_sail.json f35a502c4a5e2703e7c6811b3d2ba16a9c47d4c8 assets/create/blockstates/gray_seat.json +612058f415131fb127280c24d5d089793c103a7a assets/create/blockstates/gray_table_cloth.json 87457e0eddae80225dbb3145f2d120296ea1bfcd assets/create/blockstates/gray_toolbox.json f18b87db39836eef20154b239d488eebb64b3455 assets/create/blockstates/gray_valve_handle.json 0f0fe2bf83f763e04cd2d7a979beb547feac3191 assets/create/blockstates/green_nixie_tube.json +587c4f761858d888097c83f132c0a2d66ded3c56 assets/create/blockstates/green_postbox.json 0a2a5fbf2cf084e1be0426a224c291dc22a826fd assets/create/blockstates/green_sail.json b4aede1847d204ecdb7847559066d9d2ffb66903 assets/create/blockstates/green_seat.json +98587a931a565d4196f71ac4928846a7d55b3645 assets/create/blockstates/green_table_cloth.json 6f080890b3b30c46ba9ceb382c1171940bf4966f assets/create/blockstates/green_toolbox.json a343aefdb4207d1bffa6f4b40e20283a6d42c2f9 assets/create/blockstates/green_valve_handle.json 23430b770b5257af36844dfe9b976e343a6d1180 assets/create/blockstates/hand_crank.json @@ -260,7 +284,10 @@ d0b26c085df3ee5189082bc18945e5f74ee529fa assets/create/blockstates/haunted_bell. bffc2169f5fc3a8e22f8952a90767e0bb8d726b5 assets/create/blockstates/horizontal_framed_glass_pane.json 8ae52808eba950c36b75d62113e9cea9441a1a54 assets/create/blockstates/hose_pulley.json 87fa830c5d3541d096fab32d430c54516c197583 assets/create/blockstates/industrial_iron_block.json +3727801604445df291112fd9b99f99bbdcfa0f6d assets/create/blockstates/industrial_iron_window.json +877418ed76fdc589788db119663ca3e52e26a2aa assets/create/blockstates/industrial_iron_window_pane.json 2788ad2d29996076f7f18ab8d47e40c1ad10b348 assets/create/blockstates/item_drain.json +3151ed4019d851ab2a7b07f1327bc4bfb6ed7227 assets/create/blockstates/item_hatch.json 3e99569e978c0fe17ec18b97881434a9da1a8421 assets/create/blockstates/item_vault.json 8680e9d2a94231f4bbad87b26ab2efdb714903d3 assets/create/blockstates/jungle_window.json ddcf1010e43c5d4a8c93aad37cc97a94343fd9f5 assets/create/blockstates/jungle_window_pane.json @@ -283,18 +310,24 @@ ca124508c59130d21f23d7b1ef354d78bdd24dd4 assets/create/blockstates/layered_tuff. 2ff5466f9ea3b1292c24a8ddb31666d74635c592 assets/create/blockstates/layered_veridium.json fcf02725651ab5973fab1cfc09fdd68cb4b93579 assets/create/blockstates/lectern_controller.json 5d7e1b08b1ec7c7c11b70db11df09311fcd7cf45 assets/create/blockstates/light_blue_nixie_tube.json +3a7ceaefb2f7a24eac6bb3676a8fee01290a535f assets/create/blockstates/light_blue_postbox.json f2354e8cb6086473ac97a5228b99706858dcad8a assets/create/blockstates/light_blue_sail.json 6b7045eaf9efe3a90f2d9a6785be6a5fd534b8e7 assets/create/blockstates/light_blue_seat.json +ba0ae5046b643f82338e98ae56a48c01cf2d5972 assets/create/blockstates/light_blue_table_cloth.json b7065e7871c3c7f1a0656c2f92f82544e606f2fb assets/create/blockstates/light_blue_toolbox.json 549882a0f4de60906ca870a6197330f81d4e1afe assets/create/blockstates/light_blue_valve_handle.json fa5fb2be73c7c54b70e927b66adf3f4d64c5cb6b assets/create/blockstates/light_gray_nixie_tube.json +9af388892d4ae6c4a91dc6021e4f15a504b82695 assets/create/blockstates/light_gray_postbox.json 3d95c9c4442d1bdd660bae382c72c68134db86dd assets/create/blockstates/light_gray_sail.json 8ec5144da4a49dd5b497af07b0d4b88c9c0b6cc0 assets/create/blockstates/light_gray_seat.json +f1901887cd166296e465133c3b0d7ad0d664a614 assets/create/blockstates/light_gray_table_cloth.json 35b151db396069b146d223fbe46be5b0c3dda8a9 assets/create/blockstates/light_gray_toolbox.json 894827ffd176bc733abecf18d96888e9ed5a3eb4 assets/create/blockstates/light_gray_valve_handle.json 7f20b548dd535942b2d6f41c39de7ad4fafe637e assets/create/blockstates/lime_nixie_tube.json +c6ac740bf37477ad170576983230b130ac01f355 assets/create/blockstates/lime_postbox.json ad1ec304729fd6d336c0d4d0c27c9345af636695 assets/create/blockstates/lime_sail.json b9934a558e1b495403dc2c71ffb43cce7d396013 assets/create/blockstates/lime_seat.json +7c5dc2ffd0bd44ba8785b6a788030714a009bcbc assets/create/blockstates/lime_table_cloth.json 49a02f7fc16697ba1cf16cee7e45ab6bfd8b06ce assets/create/blockstates/lime_toolbox.json ba181485f219d3ae23509a7edf28e25d9edb10f4 assets/create/blockstates/lime_valve_handle.json a6f319c803c03e34bbf841ea52d82f0f7ec7a413 assets/create/blockstates/limestone.json @@ -302,8 +335,10 @@ a6f319c803c03e34bbf841ea52d82f0f7ec7a413 assets/create/blockstates/limestone.jso 654e845cebed82b7afbcf81380921e0a475b01e9 assets/create/blockstates/linear_chassis.json e195e82e4d0c1fc20474535bc9068cbb77a5e175 assets/create/blockstates/lit_blaze_burner.json 296186b196af94e1ab3f7e8a3254f6d31ae47a5c assets/create/blockstates/magenta_nixie_tube.json +725e695b70bc6aac379fae422c86bed92612e504 assets/create/blockstates/magenta_postbox.json f150922cbed1c05fb3892d4ac91eb471234252e2 assets/create/blockstates/magenta_sail.json bb1ab5c70647933400b3a99ef9d166ba5e3d4709 assets/create/blockstates/magenta_seat.json +a09b8c51cfbb1c9c8a4f670a83cd81c376fe4ba3 assets/create/blockstates/magenta_table_cloth.json fcd226c7863262d98765c701538bf9e44d2b177e assets/create/blockstates/magenta_toolbox.json ecf670d95969a33a738f59e08393299891f78847 assets/create/blockstates/magenta_valve_handle.json 8a30c1ed277ec60963abbcb24cce6efd162d02d3 assets/create/blockstates/mangrove_window.json @@ -334,8 +369,10 @@ ba9c3ecfacbd398048440d247decffeaefc714b5 assets/create/blockstates/mysterious_cu 7f2c5728e24d60ed2f7a095e3a954d7ca4e410e9 assets/create/blockstates/oak_window_pane.json df91d0ca68934c1afd9858a8d1591dd4cb88df65 assets/create/blockstates/ochrum.json 09c9bee3d26edc4b87cb7a5042f125c439ee5956 assets/create/blockstates/ochrum_pillar.json +42f108813ed68f4492d0a168d52f31bbe2e5635b assets/create/blockstates/orange_postbox.json af4c2c4861d1410e1b7371a5bf3fe09ed3ab0077 assets/create/blockstates/orange_sail.json aab812cecf7d10d4e7587f4dead8a98238a15f41 assets/create/blockstates/orange_seat.json +27d90736a8d64fe7f742a6e5874b8d5843f5dd2d assets/create/blockstates/orange_table_cloth.json 2bc30ed9907230271b4e2d0786f106f3e1e25029 assets/create/blockstates/orange_toolbox.json 2af63a4768f84fc93c7e7d67fa9a64438433e59f assets/create/blockstates/orange_valve_handle.json 515ed7dae09b052f289419ba09998a23e0d7083d assets/create/blockstates/ornate_iron_window.json @@ -346,10 +383,14 @@ ac536ae742c12e97bfd0b2483c87ff29f3935eaf assets/create/blockstates/oxidized_copp 3f3924f0f0e368edfa04f4fdd6d6c2319276ddfe assets/create/blockstates/oxidized_copper_tile_slab.json 5e634cfb9abb06d8b29f39d751fc56b28ea5a9cd assets/create/blockstates/oxidized_copper_tile_stairs.json 110a6c19bcc9f044e5e982ac6e4b295b03ec0145 assets/create/blockstates/oxidized_copper_tiles.json +887565a0f89f089d6be888c87394dde4878afda7 assets/create/blockstates/package_frogport.json +65f3fa5a068189c1c2971af1a1052f69c0e26005 assets/create/blockstates/packager.json 36742cc6ce052ead143366d31b11e828a525c1b8 assets/create/blockstates/peculiar_bell.json 53d102e706d53cb2c0dbc0bc11da828084a43519 assets/create/blockstates/pink_nixie_tube.json +db7ef5acb1ce2d3b8f881f34b5d9f40633c3973d assets/create/blockstates/pink_postbox.json 213da5c04a33ae8ae7c0a4dec9844bbb6d670e33 assets/create/blockstates/pink_sail.json 8d5c80d5dc561240dfe8d7f212ffc33ac4e0fcd8 assets/create/blockstates/pink_seat.json +2698986d23ccd7b828af6150d04f0139255a5bf1 assets/create/blockstates/pink_table_cloth.json 90bd26c7c6933f5ebbe17b0fe58f840e2924a0f5 assets/create/blockstates/pink_toolbox.json 9f698d0fe8cfd3c9b727ec00623e6d473d516d4a assets/create/blockstates/pink_valve_handle.json 73c2a6e6e2e0dad1bdcf2d8b089b28dd4c72c825 assets/create/blockstates/piston_extension_pole.json @@ -418,22 +459,29 @@ b1f5ad596067cb4c84eb53b2c7b359be76f1cfbe assets/create/blockstates/powered_shaft df7af1e49c53ae99ac3f0b2fca5d948b8ea91938 assets/create/blockstates/pulley_magnet.json 89d763258c53aa12a1e0c0e586ab701f3de5a1b5 assets/create/blockstates/pulse_extender.json 81281435b8d1eeb4f1e318c6d14d49fa1fd86820 assets/create/blockstates/pulse_repeater.json +65bfd8283749117663f7199204691758fd286e38 assets/create/blockstates/pulse_timer.json b658654aa97e8dd2c897f432a601835a3f8aca10 assets/create/blockstates/purple_nixie_tube.json +6fa2954396474f97dab79955e4bd75346b04acc5 assets/create/blockstates/purple_postbox.json f8f9802df9c0b4e39edeefc3b1abb38255d79801 assets/create/blockstates/purple_sail.json 91b5ab66d7ec5235d278ee2bed6ddd88f39ce81d assets/create/blockstates/purple_seat.json +a4b6bd4e55cd292abf752efeda93cf8d23162657 assets/create/blockstates/purple_table_cloth.json 6aa467b3588359fdf5d7201f844193d5b70f20f7 assets/create/blockstates/purple_toolbox.json 6d02761efbb93349654514f67f5c0b7331e2823a assets/create/blockstates/purple_valve_handle.json 3aca01f2eddb22adb1b25735b98a990bfc7220d2 assets/create/blockstates/radial_chassis.json 72faac9777be540f95f8b662a833856e0e1b8f35 assets/create/blockstates/railway_casing.json 7ce346fa18702f6fe6e2a939efcfa26eda63fe38 assets/create/blockstates/raw_zinc_block.json e3fd62e466e3e6e7bd6fc8661f764ba972a466fc assets/create/blockstates/red_nixie_tube.json +d14d6437a6727da13cea5f7eeb815720c80dde6f assets/create/blockstates/red_postbox.json 4c36b562da58ef2af57009da7cf2426059249228 assets/create/blockstates/red_sail.json 145f4e9ffaeff9be180e6c4e4989f2cf44cf0686 assets/create/blockstates/red_seat.json +90bf31515faa2e7e6d73414a6c5498911910710e assets/create/blockstates/red_table_cloth.json 380f46b7cb72b13c0f16fd4a4287a1a33adeff41 assets/create/blockstates/red_toolbox.json b689d87a27ed0cb2cab190a2ad2b599818bff56c assets/create/blockstates/red_valve_handle.json ec546afd3ec8036e4393b97d535f05a86f57dbc1 assets/create/blockstates/redstone_contact.json ff205f032b36486753dddb1f2029ef8d53e9c86f assets/create/blockstates/redstone_link.json +e4c645b199a2d7e89c91065071a0a91df5ca8e3c assets/create/blockstates/redstone_requester.json 87ab7ca62ecf24d60d7e5c61bd5af97714dad0ad assets/create/blockstates/refined_radiance_casing.json +64a5b256e5af2dc8cb7ed77f0feadcf5134f7335 assets/create/blockstates/repackager.json 3807bcc6ccc3dad0dbfcc8fcf260a361aa488659 assets/create/blockstates/rope.json baa7da231c6c45d5eabaf04985d46e206a3346f8 assets/create/blockstates/rope_pulley.json a8b42f047fe9099f81334e2e1082067de67549db assets/create/blockstates/rose_quartz_block.json @@ -520,7 +568,9 @@ a60c9c8241e40c2e28f5760c0ca6e80cfe9d59f3 assets/create/blockstates/steam_whistle 636ec6c7e1ef3b737edc716200f138bc63681d78 assets/create/blockstates/steam_whistle_extension.json 8865500bcd2e4d467e74edb3509850fa92a5809f assets/create/blockstates/sticker.json bed0534e618105184bc877b104230403ca85bb58 assets/create/blockstates/sticky_mechanical_piston.json -bab242ab794e6d439645c2d5a0242ae7c81942ff assets/create/blockstates/stockpile_switch.json +d17e6ac368278bd60442e2f19eb064a31c4106d2 assets/create/blockstates/stock_link.json +9989bda294fbffc5f659d2e608e01dea424c7694 assets/create/blockstates/stock_ticker.json +c7c17ff17b98ce85d355f2f9b4509271bc283843 assets/create/blockstates/stockpile_switch.json a70c025de5d85180f371ff05bbdc531d8bdfaab1 assets/create/blockstates/stressometer.json 8086f80c532fad42b37fcdc590b890ed7e8c3fe9 assets/create/blockstates/tiled_glass.json 1143ab7223c655764a81ed72ac385ea179664072 assets/create/blockstates/tiled_glass_pane.json @@ -570,23 +620,30 @@ c11562afd9a5f85945e521dcea5f911d1b6d13c6 assets/create/blockstates/weathered_cop fee668eb9a45dca0d287fee5811219d69f9ec3e2 assets/create/blockstates/weathered_copper_tile_slab.json da110f382368257e15431c77164aef82e014e3f8 assets/create/blockstates/weathered_copper_tile_stairs.json 236e072d9056c0dbffdf5d7d973a85a56c2c8de1 assets/create/blockstates/weathered_copper_tiles.json +64fb3e569da401635b64e71e01ea0b3ff6360611 assets/create/blockstates/weathered_iron_block.json +6fd81f1eb48fbfc44df9db8eedc613690c9b8ef5 assets/create/blockstates/weathered_iron_window.json +1aed351050d73989c4553bf49ce03b3a8fdd210e assets/create/blockstates/weathered_iron_window_pane.json 25ce64b7af5d244f194da91ccf964a9bf5762327 assets/create/blockstates/weighted_ejector.json 2974b34a8cfb0d4e8e010f8bd085584ea631d541 assets/create/blockstates/white_nixie_tube.json +3de81b9e34425a9d3a25c657dabd24d74bf01456 assets/create/blockstates/white_postbox.json f079469d186087d23f0d91b384040f777b0088b1 assets/create/blockstates/white_sail.json 317a6463db64b66d215d25b65ab52fe7f26ba9f8 assets/create/blockstates/white_seat.json +9013272715c2ed3104457a50a6f0795a7c33fc43 assets/create/blockstates/white_table_cloth.json 6cb8c82a429b54d6a87d02eec5cfd1fcd5365f1e assets/create/blockstates/white_toolbox.json c0bfe8416173868f9916c4a54dd9f983887c5bac assets/create/blockstates/white_valve_handle.json ec2720e3f1bc84304d0c81cd23ff1e155b0c2f2c assets/create/blockstates/windmill_bearing.json d688e80dfbd5b17970814887c3698fc721981caa assets/create/blockstates/wooden_bracket.json 157942a838aa02909fb2238ad9ce77edc82f6142 assets/create/blockstates/yellow_nixie_tube.json +f3d0a1335e0d9cd592e177d51a36206749346676 assets/create/blockstates/yellow_postbox.json 68b6e267e93b96dbc0596ea4a1cd26636aa0e04a assets/create/blockstates/yellow_sail.json 4face2dd50a30bda0b21742319e701e666d51f8c assets/create/blockstates/yellow_seat.json +38135a1fda544b7b9624ebfa08d46351bd31ec89 assets/create/blockstates/yellow_table_cloth.json b0d8f08968763a5f74e5cd5644377a76a9f39753 assets/create/blockstates/yellow_toolbox.json fe8c497aacc641c2f01cec90bba9f19e59cc2ed2 assets/create/blockstates/yellow_valve_handle.json e819e93fdcbe9fd9c050a052d2718ff3b3539365 assets/create/blockstates/zinc_block.json 64121dcb216381c83b4fe28aa361ea07c24c9ad0 assets/create/blockstates/zinc_ore.json -5f729ba3f0557eb1c1923a091e06eee5ddf25c59 assets/create/lang/en_ud.json -bdd95ac05db0717d02e4dc34b6054e73d4eee640 assets/create/lang/en_us.json +148ea6cb1f12ff9fa4b882c75ee5509aef00cf37 assets/create/lang/en_ud.json +9f810a52200ffba1a507fe7180df392bf2ddb0f9 assets/create/lang/en_us.json a97e1060e00ae701a02e39cd4ef8054cf345fac4 assets/create/models/block/acacia_window.json 103e032c0b1a0a6a27c67da8c91179a564bd281c assets/create/models/block/acacia_window_pane_noside.json fb00b627abda76ad4fea867ca57dbfadd24fffa3 assets/create/models/block/acacia_window_pane_noside_alt.json @@ -640,12 +697,19 @@ b39661fd20e4b3f5ab2b20cbd51af4ca98e2410e assets/create/models/block/andesite_lad 32551174974fde322de14af09afb160673c4ed23 assets/create/models/block/andesite_scaffolding_horizontal.json e20105b4d1762fbfe67377e08cdb8c7ff9a62128 assets/create/models/block/andesite_side.json b58e7204eef795080abf9fffa41ba11ec2e12426 assets/create/models/block/andesite_side_alt.json +f9bc3af98dedae53161917c78a76353d1a270e7b assets/create/models/block/andesite_table_cloth.json 378df94de8cbce28cd3c2dc30fd3a30dfc451cdd assets/create/models/block/asurine_natural_0.json d6eb7105dd9b42adde48bd70e3f2fba70751c1db assets/create/models/block/asurine_natural_1.json 6d77d2591579619aa1ebb7b2f0e2c939e1648e4a assets/create/models/block/asurine_natural_2.json e80a3d387e8c40bf886735d46a119f9a93c6f5a8 assets/create/models/block/asurine_natural_3.json 1c3ddf07bdd9fc5fcf7c1f35c7a06846cc1add54 assets/create/models/block/asurine_pillar.json 403efa3dcd07e94c351594cc6c5b5becc15e6690 assets/create/models/block/asurine_pillar_horizontal.json +daac4c886b0485449eff2f87d82754d387baba93 assets/create/models/block/bamboo_window.json +75f28c83adcd81ddd7f073596b04ddc5809b421e assets/create/models/block/bamboo_window_pane_noside.json +e70e053d438ec435395c416c6fa7a06aa0527762 assets/create/models/block/bamboo_window_pane_noside_alt.json +568c8603c7606bf77958d0855a7471e6a935bb54 assets/create/models/block/bamboo_window_pane_post.json +d9c964d9e0d77249f1e5caac8fc419ae533ee828 assets/create/models/block/bamboo_window_pane_side.json +c60adf74c20091675c4c9293e69fcc8ded8fef93 assets/create/models/block/bamboo_window_pane_side_alt.json 930e154155eaba67acb96109472b6d8c502907dc assets/create/models/block/birch_window.json 3ba397e70b642bdfa458dd3046b094ccf73b42e5 assets/create/models/block/birch_window_pane_noside.json 3ff792e09a83b47640083f4da20701e47e6a46bb assets/create/models/block/birch_window_pane_noside_alt.json @@ -653,13 +717,19 @@ ee71b0992edc2496025c22806e8de3a3243882aa assets/create/models/block/birch_window 3088aa5e46cf9caa912c80a4e7791904e64e9def assets/create/models/block/birch_window_pane_side.json cb9d3a0dbac6a884d5ce0dc82085322f8c666707 assets/create/models/block/birch_window_pane_side_alt.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/black_nixie_tube.json +1fe4a9cbcae773f32c07f7cef42f52588ec1c1aa assets/create/models/block/black_postbox_closed.json +3caec00f8aa36393cac8049815b3e8bad12d8dae assets/create/models/block/black_postbox_open.json 62c92a681b5a86a5415cc7a70263ffdc794cdd59 assets/create/models/block/black_sail.json 443ed49b053fdd7356cd56f0495e18f2570d57d9 assets/create/models/block/black_seat.json +6f85d70c8fb017e80290a5832cdaf07ad3306b50 assets/create/models/block/black_table_cloth.json f48989d377de8e5067e807adf7e38da781e37ed9 assets/create/models/block/black_toolbox.json 8715787d72c3ef47c5651abcd819539bad6a96f7 assets/create/models/block/black_valve_handle.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/blue_nixie_tube.json +e9e9487a3440b3a6c1ac515f63385ee59e8fb773 assets/create/models/block/blue_postbox_closed.json +7e2df652bfc7fdc27da6a52b52fe732fa175c996 assets/create/models/block/blue_postbox_open.json ddc740084aa5f387bee062bd4141ad8fadb56355 assets/create/models/block/blue_sail.json 96431b1f3a531ce89f876c9286b81838aec9b6d3 assets/create/models/block/blue_seat.json +97aef30303b851c28d4911bf2c6ad8033df628df assets/create/models/block/blue_table_cloth.json 89932aab163b14a21fffd4fab4b8b88a94163089 assets/create/models/block/blue_toolbox.json 3e052466f0b8db75779945c0f1231af9611b723e assets/create/models/block/blue_valve_handle.json 159e2b37a0866c9dbcdd6554be8a207883098168 assets/create/models/block/bracket/cog/ground_metal.json @@ -709,13 +779,23 @@ b2a95218042586aae38dff9278f3ee3f159bc73e assets/create/models/block/brass_post_e 62d99236e09b11af9a24d3c667fb1167cf8db0b0 assets/create/models/block/brass_scaffolding_horizontal.json ec81e9c237ec98b30a3de22e12cb9720922478eb assets/create/models/block/brass_side.json c697cace1f4097468ff34254c4ff6450d9d52f91 assets/create/models/block/brass_side_alt.json +f0552bba877b84ae81051019961cf87d13f976f4 assets/create/models/block/brass_table_cloth.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/brown_nixie_tube.json +b04c80852527a07e01c27686be678cbaf568e821 assets/create/models/block/brown_postbox_closed.json +19a2045ecedd3ef12cda7d69a0d7bc6a4133b7f1 assets/create/models/block/brown_postbox_open.json 50a054d1e0660d16e86cf7a520b9bf36e38401b6 assets/create/models/block/brown_sail.json 0616de192825246e6036d1f69911170438a83b81 assets/create/models/block/brown_seat.json +eb829b796cea3387cb25ace858c795e2497b3703 assets/create/models/block/brown_table_cloth.json 4226a7c5f1bfb0a75457fb4dfd22448503110e5c assets/create/models/block/brown_toolbox.json 0e1fece0854ccea20df2f0abc865e4f44af54d1a assets/create/models/block/brown_valve_handle.json 40a224ce4ea989599f7bd66bd2437ac2b98247d8 assets/create/models/block/calcite_pillar.json 141fc72bb7296c6b5a13499622c0c7384179a7fa assets/create/models/block/calcite_pillar_horizontal.json +09cdcbe8056a81a0a825df47f5cb0e352f98907e assets/create/models/block/cherry_window.json +5275e27c80bdd43b40fa31418dfad175fc809480 assets/create/models/block/cherry_window_pane_noside.json +ae87368850bc6ef1a2e2f633b8ef6ed33ab5b2e0 assets/create/models/block/cherry_window_pane_noside_alt.json +0e5c58632e134aeae3e85e70d7c0ea1ed6e05055 assets/create/models/block/cherry_window_pane_post.json +b13184df1e1c20a7b94fa887ab64845e3b7d0fca assets/create/models/block/cherry_window_pane_side.json +d8e2f395915af41686924cb4654d43097260720c assets/create/models/block/cherry_window_pane_side_alt.json e9d61ba17fa2619af01ef604c3f65cbe9272f010 assets/create/models/block/chocolate.json d8339ab47ffa828985c7da27c37794a95aba8b42 assets/create/models/block/clockwork_bearing.json 8afe6afaff33b94c1fcee68fdaf842d525eec212 assets/create/models/block/copper_cap.json @@ -734,6 +814,7 @@ fcb9295f4f388e6d439ec9a3906ca326b6d69077 assets/create/models/block/copper_shing 32fdb85b5b62d5a0fb41732874c854788cdd2ba1 assets/create/models/block/copper_shingles.json cb218a725f82db34ffe58a5208266e1c768cfc05 assets/create/models/block/copper_side.json d9b4652ca8f1e65007f42d946ecfb38acc3f168f assets/create/models/block/copper_side_alt.json +03a6c5b8bc3041a2be001092f7abd014d6f852a2 assets/create/models/block/copper_table_cloth.json 298c6100de02ed9f813397d8ba38c46f35035c69 assets/create/models/block/copper_tile_slab.json d4422c2d96fb329087d1be70d8b983a8cf6c7f01 assets/create/models/block/copper_tile_slab_top.json fca72048f916d3a3e567b385c948cc1b59711ef4 assets/create/models/block/copper_tile_stairs.json @@ -1035,8 +1116,11 @@ d6423c0fd0af4fbd929d26d6097a1722567acc9d assets/create/models/block/cut_veridium b2e847cee8c01791c15fcdd35787af33ebe46f0a assets/create/models/block/cut_veridium_wall_side.json 5ab4db4245b852edf985fe72595f678eb7372801 assets/create/models/block/cut_veridium_wall_side_tall.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/cyan_nixie_tube.json +0cbd0c6c909effa2f71e198655d51f2e483454aa assets/create/models/block/cyan_postbox_closed.json +ccea6f3023879d84de4590a584f666598f58d6bc assets/create/models/block/cyan_postbox_open.json 27c9aff76b32e4de18d581e133fc23a8239ca412 assets/create/models/block/cyan_sail.json 01a324a92552076589e2aaaeca9d4da2d1e3b39d assets/create/models/block/cyan_seat.json +c7a147b092909c57ae197007818810fa75b9cb68 assets/create/models/block/cyan_table_cloth.json 663f431fe8a02e057980cf9bcfc566eb5adc876f assets/create/models/block/cyan_toolbox.json febd2b2f94194441fb73020b667d0398853add4a assets/create/models/block/cyan_valve_handle.json 339993f53eacf042d8caab6101eb5d4088b35746 assets/create/models/block/dark_oak_window.json @@ -1116,13 +1200,19 @@ d0fa41de17f65693188f1868ace5fc2ac518739b assets/create/models/block/gantry_shaft 3356069e112cde817da0c99ceb40cd8f207de822 assets/create/models/block/granite_pillar.json ee860a8bd95fda14a859d6632652ee2a95f06c19 assets/create/models/block/granite_pillar_horizontal.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/gray_nixie_tube.json +f2bbb067bc4e91a71303cc92939c4f4707cdc1ab assets/create/models/block/gray_postbox_closed.json +905fb4b54a39ca9bc1d6f48977bb3b158b17c2a1 assets/create/models/block/gray_postbox_open.json 97f382e9b435c81d1d8e0ed487a7fc16e6945958 assets/create/models/block/gray_sail.json 58b51da5c80e4f43582452d97453c93145a516ad assets/create/models/block/gray_seat.json +2efdba46e7e7acbbcbd36468e5d46c22989b8516 assets/create/models/block/gray_table_cloth.json cd3cff8e38d559dcb78df014556a78d5a538af43 assets/create/models/block/gray_toolbox.json 3ee19f46bdeb0ac7489dcd4d51f90ab01ad863c9 assets/create/models/block/gray_valve_handle.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/green_nixie_tube.json +21fbacdc856fb1003f58bf2842fe418124f6b01d assets/create/models/block/green_postbox_closed.json +703df2f5307d39f0f4e5b9a1f99b8c14fd819dd0 assets/create/models/block/green_postbox_open.json 26577589688ec1f39cae9f42704cb36cbc1c48ae assets/create/models/block/green_sail.json ae51eaa500dd036fa27474a7392f381afb677dfd assets/create/models/block/green_seat.json +4fbf52032b062afd32921ee925d8c13160fe2029 assets/create/models/block/green_table_cloth.json 801d277b241332d5f4b49bdb00b911dcd01a7db2 assets/create/models/block/green_toolbox.json f7762c9388198b51686541edbef9a1546041f6e4 assets/create/models/block/green_valve_handle.json f8b51eec36c2eddc08a1b60894d863bb58f55625 assets/create/models/block/haunted_bell_ceiling.json @@ -1137,6 +1227,12 @@ a1a239714f5feb45a692f5c2873c37d6614e1b8b assets/create/models/block/horizontal_f 0f7e518ef02428c55e1683bc9de0d20e2c1e6883 assets/create/models/block/horizontal_framed_glass_pane_side.json db3f9472815fb6acc1ee1d9941b8cc19518ebcbf assets/create/models/block/horizontal_framed_glass_pane_side_alt.json 6868ed1959875efec96a15ca6f32b8c7efefb2d9 assets/create/models/block/industrial_iron_block.json +02806f9c95ba6b74b61e1c92927492b3668ffdc9 assets/create/models/block/industrial_iron_window.json +a0152d54688e8c4bb0c96e0476cca7e5f92dabd7 assets/create/models/block/industrial_iron_window_pane_noside.json +bbc922f5ddce4acfe89911d149204d4663515fc2 assets/create/models/block/industrial_iron_window_pane_noside_alt.json +13c0714510f379830f42488c4f0457c4f4d6be16 assets/create/models/block/industrial_iron_window_pane_post.json +b5bbcb04dd68249b4d9c2bae2fa2c15e9bcd9870 assets/create/models/block/industrial_iron_window_pane_side.json +7763d9f974f859963a48060858b80a6b46f842c9 assets/create/models/block/industrial_iron_window_pane_side_alt.json cdc4f1c608f74824fd270521a846823ca4b6ef16 assets/create/models/block/jungle_window.json 8c5ee8e36756fcff3095c564567a35be1db23cee assets/create/models/block/jungle_window_pane_noside.json 2bb34fe17c7cfafc8658cd0b44ab636191f81348 assets/create/models/block/jungle_window_pane_noside_alt.json @@ -1158,18 +1254,27 @@ b843a6e27c4f90e31108f9f3c1573e70fb3d0927 assets/create/models/block/layered_scor 5fb53db0c6623dc16e486ac0bd094b5a90e2e080 assets/create/models/block/layered_tuff.json 336d1646294e018ea3de60b30a621a10ca7aa6d7 assets/create/models/block/layered_veridium.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/light_blue_nixie_tube.json +cf487c0be9444b7ac124d2ae33e6c545803e14b6 assets/create/models/block/light_blue_postbox_closed.json +7497701edea1599fc51e3eaa0367007ca00bbe69 assets/create/models/block/light_blue_postbox_open.json 2e83d3aaa92640d6b3da2a2644f6a160f97b08e4 assets/create/models/block/light_blue_sail.json ba917560f40a4e46ef190649f18adad9962c5c02 assets/create/models/block/light_blue_seat.json +af065b4c74b0d177075221a996d9ac78b871e8f0 assets/create/models/block/light_blue_table_cloth.json c20616aa90feab3003cecb4a5be5466c0fc83072 assets/create/models/block/light_blue_toolbox.json bcd3d28b8a062649301648ea5e2d0463f93d008d assets/create/models/block/light_blue_valve_handle.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/light_gray_nixie_tube.json +1efabd28f0dc3db1c0e6bea2be62cac883fefd66 assets/create/models/block/light_gray_postbox_closed.json +a42521eac2924269cb1f0e865bafe7dcd147d1cc assets/create/models/block/light_gray_postbox_open.json 09f284574b38ab57579e939bbb088b8d36e0b8f5 assets/create/models/block/light_gray_sail.json d1813d0f548fcddb361df7cc3b5d97582842b10f assets/create/models/block/light_gray_seat.json +debf78f20659bc3c637299a40b649cbe4aa30ebf assets/create/models/block/light_gray_table_cloth.json 4ec5d701dd8b2d8c3dc44d05f527a3d737002cd4 assets/create/models/block/light_gray_toolbox.json adb8dbed70419e0310e7a20f3656bf325b348434 assets/create/models/block/light_gray_valve_handle.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/lime_nixie_tube.json +952d292d4dc2158e6106c5079cfa1ddb81c7777e assets/create/models/block/lime_postbox_closed.json +4357f5d9102d54c7fbe5325512a2cd42d94d6d42 assets/create/models/block/lime_postbox_open.json 5a95a72444f523cfba6e8c5adf8eacbb37e2d21e assets/create/models/block/lime_sail.json 09e7bf50cf88c449dbd9e77829cdb5afffb7d88d assets/create/models/block/lime_seat.json +e4142a22c20d6e5b9a8b9f96c13d4e5f96adc59d assets/create/models/block/lime_table_cloth.json b92822a01e4fbed2463b1bdf7dcc736023988e20 assets/create/models/block/lime_toolbox.json 802b47f34b1053b7af980b08b6511f468e7dd7c1 assets/create/models/block/lime_valve_handle.json 8f53caad3899a30be5087a0ba155080834418cc0 assets/create/models/block/limestone.json @@ -1180,8 +1285,11 @@ fb18280a2a708f60b00cc7c675804c219784871a assets/create/models/block/limestone_pi a1a3804ddcb1db0a7b5c0693555f8eb326950dd0 assets/create/models/block/linear_chassis_top.json f885acc0ba705cfa9c65b62626ab4007f3b6e329 assets/create/models/block/linear_chassis_top_bottom.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/magenta_nixie_tube.json +bfea3fd456f92391afc9f948ade90b16275e63de assets/create/models/block/magenta_postbox_closed.json +fe224c9e396eb51a6cc0b38175b621a56500fda7 assets/create/models/block/magenta_postbox_open.json 81122f26a12b7ab40fed6d31c97376f4dfffa111 assets/create/models/block/magenta_sail.json b5cd13b021400b3c37499ec4ef22e560c721ac54 assets/create/models/block/magenta_seat.json +8b37821a3c6825488479d4f605bbd84734457c68 assets/create/models/block/magenta_table_cloth.json d7b2b16ba2d6a0b2441aeaf7faa76f61fbdc35e7 assets/create/models/block/magenta_toolbox.json c0d29851d48cebd376b3b6e8f0454e0369d0e265 assets/create/models/block/magenta_valve_handle.json 026384a699d592160624bb7a1606e31fb77751be assets/create/models/block/mangrove_window.json @@ -1204,8 +1312,11 @@ af50363d603d61340b336569d58c1febde253665 assets/create/models/block/ochrum_natur d69effa0a811cb93fead8257bcaad4bbf0094002 assets/create/models/block/ochrum_natural_3.json 24669a4e93925940477fcfc0aca10ab9d87368e0 assets/create/models/block/ochrum_pillar.json c8dd33a0b71dce37712788a61729de89574b117f assets/create/models/block/ochrum_pillar_horizontal.json +dbd0cbfa1c6cfaddd7ac954379b4b1f3056730f2 assets/create/models/block/orange_postbox_closed.json +88cda1f606e502cf0df9430b75a70fd3161fd6ba assets/create/models/block/orange_postbox_open.json cb4cd4e4bfb0d105a09c56454abf4795b155d12b assets/create/models/block/orange_sail.json 6c4addc75fb03911fca3083f891b22f55209b8db assets/create/models/block/orange_seat.json +f004bacf25a9675a87905ddbfa2e140a3891f4b0 assets/create/models/block/orange_table_cloth.json f68eeb8cd828a0659fe8665373daf093ea65f0fc assets/create/models/block/orange_toolbox.json 992367362e20777dd2e1245c6b26b6ffab86b21c assets/create/models/block/orange_valve_handle.json f9010894858512398bddd5d31b922e12594d2e3c assets/create/models/block/ornate_iron_window.json @@ -1231,8 +1342,11 @@ f70f83cfec770879c478eea3760ea187700f2878 assets/create/models/block/peculiar_bel b9c9d00b844ca2f217ae21cc502cd4d082fed2d5 assets/create/models/block/peculiar_bell_floor.json f7b09c243cfeda8bb38a29a917b9fbdafe47eece assets/create/models/block/peculiar_bell_single_wall.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/pink_nixie_tube.json +084266ced8975953fa158fd9e7261d8f10b94db7 assets/create/models/block/pink_postbox_closed.json +e99518b61a3c7a89570a8aa8c4cb45badfa8547a assets/create/models/block/pink_postbox_open.json 90113a1f53f0f8d9ce11ff14128eb860063f5ddc assets/create/models/block/pink_sail.json 888dba067e751a55205dbd919db8e92ef2be604d assets/create/models/block/pink_seat.json +9a7e7af8cc625a0812304c9bd3b00d13f085f040 assets/create/models/block/pink_table_cloth.json 3cb69299c7787f88fb41c6397362aa7b607c0960 assets/create/models/block/pink_toolbox.json cf2fda0a37a0e5771cf882793ca21f277219796f assets/create/models/block/pink_valve_handle.json 44b05f0e3847c526514f7a7e167d275415408b39 assets/create/models/block/polished_cut_andesite.json @@ -1385,9 +1499,15 @@ b21ec7cde56398b65f44922ddb026d9adb7b6072 assets/create/models/block/polished_cut 66374fdc4d3d55f99b03e406f3b594f8b1bab94d assets/create/models/block/pulse_repeater_powered.json 6bd0d85ca18b468bee279e7bc398bc8395e33a8b assets/create/models/block/pulse_repeater_powered_powering.json de0cc956e7ff1510d0947ca8fd2b6e642944f0ee assets/create/models/block/pulse_repeater_powering.json +addbe93af945ff7ca2680a27225db804d3ac9b46 assets/create/models/block/pulse_timer_powered.json +ab3d7e10abcb53b835d6f5c406b7a777a942d6f7 assets/create/models/block/pulse_timer_powered_powering.json +7b425d9db8d914b52b7faad2f792c020b678f84d assets/create/models/block/pulse_timer_powering.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/purple_nixie_tube.json +afdd265ee175c47ea6e4e44fb08d212e4cef5ee5 assets/create/models/block/purple_postbox_closed.json +fbd874fd63b3d6f50592703dce6bf196f2d63732 assets/create/models/block/purple_postbox_open.json 356378a5839b0b400aa5e0a67740634113c09a38 assets/create/models/block/purple_sail.json bc8e473a5662b6180b00b85e5006241a283c9baa assets/create/models/block/purple_seat.json +d040daf29c44f31c4cd8522998b66f7021b3c746 assets/create/models/block/purple_table_cloth.json 5e85ec98c165a0b5bfe25d391e96df9164372a3a assets/create/models/block/purple_toolbox.json b7e5f69044c7a1d0a31fd2f6efe81a5be060bf19 assets/create/models/block/purple_valve_handle.json e1fdd5fb88d9f5af7d0e90e65cf5ecea0667e1c7 assets/create/models/block/radial_chassis_side_x.json @@ -1399,8 +1519,11 @@ ff65b89683fbb9326f625b9a68f954def5ed000d assets/create/models/block/radial_chass 9d234d1294f927d1e70a5c9b1e6de73ef65e7014 assets/create/models/block/railway_casing.json be8042806b08990786ced1cf140c4942d7a6788b assets/create/models/block/raw_zinc_block.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/red_nixie_tube.json +844614001c30ef34d3136a350c12018c5e9ab341 assets/create/models/block/red_postbox_closed.json +d06791faedd062464a13972a3b64de86053aeac7 assets/create/models/block/red_postbox_open.json b692deeb65f338212fb1073b725a122b7b1359d5 assets/create/models/block/red_sail.json bf3f4ba33e1a61254073ecee3e753958f8debb35 assets/create/models/block/red_seat.json +687a21d7d3e00820430dc47575449dcdbdc5b59c assets/create/models/block/red_table_cloth.json 2a13766aebac1a392ae7bf934bd81d9210c87a24 assets/create/models/block/red_toolbox.json 36f525b420b040b9f78032abe84cd125766cf320 assets/create/models/block/red_valve_handle.json 2aa9e5c535979c912593f30b654ae96334f72a80 assets/create/models/block/refined_radiance_casing.json @@ -1559,6 +1682,24 @@ e13aabf77b949a4eaf33c772e8b7112b1a7f1e72 assets/create/models/block/spruce_windo 9bf5008df74b7caea128580021605a6abcae6841 assets/create/models/block/steam_whistle/block_medium_wall_powered.json 92eba6564e2c65e08bc628107fbf89a5ff7ab53e assets/create/models/block/steam_whistle/block_small_floor_powered.json d768a02c31606cc46a4bbd619906e313099cce2d assets/create/models/block/steam_whistle/block_small_wall_powered.json +63d74987f8461b4e94c00030d380d4891707d2ae assets/create/models/block/threshold_switch/block_ceiling_0.json +12496e505374e7fff2d1f800218848635d86ec71 assets/create/models/block/threshold_switch/block_ceiling_1.json +523bc69211b6e90cc381356f103b01b8d7e15771 assets/create/models/block/threshold_switch/block_ceiling_2.json +c62cbd9fe144326c46702ba4e512c832484ea4e8 assets/create/models/block/threshold_switch/block_ceiling_3.json +fe1017b4338d3027771d5eb8b4e2444ddb842b36 assets/create/models/block/threshold_switch/block_ceiling_4.json +d090a659a8df0b86d9892214ac5b06641aaabc9a assets/create/models/block/threshold_switch/block_ceiling_5.json +dffc869ccce392b1908c833631e3df374c6a3012 assets/create/models/block/threshold_switch/block_floor_0.json +ab3d51ab5dd8ef6c1cad5d65406180915340dd7e assets/create/models/block/threshold_switch/block_floor_1.json +7a69fb5a6e77b457c381495c951aa0ba9c7df7f0 assets/create/models/block/threshold_switch/block_floor_2.json +3a6bbc80eea8d824a981e257f8025997946b3260 assets/create/models/block/threshold_switch/block_floor_3.json +a76fae0415604615be0e822394e0879ca81bf166 assets/create/models/block/threshold_switch/block_floor_4.json +28ddae97613f1a06885f06faa20b1b2a5bcaa7db assets/create/models/block/threshold_switch/block_floor_5.json +ab50d142c25c95b0865dd41176cc07a0c76109ac assets/create/models/block/threshold_switch/block_wall_0.json +be730f505bf937db4b3658b2bd3763b514d295c2 assets/create/models/block/threshold_switch/block_wall_1.json +f7f6d92ab5dea5a85ec3d570cdd169329dd4225f assets/create/models/block/threshold_switch/block_wall_2.json +41009d15d22c946a2ed4c6ba98447c3c7cc26315 assets/create/models/block/threshold_switch/block_wall_3.json +ad3204842128db2c7bebdbf3c40fccc45c82de44 assets/create/models/block/threshold_switch/block_wall_4.json +197a6ed7fd9514de13daf58605c24a7156c00bd1 assets/create/models/block/threshold_switch/block_wall_5.json 9e74256a37ee71de978395fb911e6e6db9fcc41e assets/create/models/block/tiled_glass.json 49c76af85635454ba3b6278f7317bb1729c4c58a assets/create/models/block/tiled_glass_pane_noside.json 4319255a3fcb0b9b60cba96273c513329a480a6b assets/create/models/block/tiled_glass_pane_noside_alt.json @@ -1655,25 +1796,41 @@ e26dd64495ff8801593e9c22203cbf364075badd assets/create/models/block/weathered_co b658c1022587bd670b5acee267607719c1544332 assets/create/models/block/weathered_copper_tile_stairs_inner.json e7ae89577be9d26a071bf96cbd7ed80293902b63 assets/create/models/block/weathered_copper_tile_stairs_outer.json 9782a25341dd2ffb146430edbe6916932250c326 assets/create/models/block/weathered_copper_tiles.json +045b812ddb1ca8dd6cd9b49852ddbd37f86cd2a6 assets/create/models/block/weathered_iron_block.json +a569ddd725898a86f8745e46723edeff7fe7f2e9 assets/create/models/block/weathered_iron_window_1.json +133928d853037efb81022b69377669f0b16239bc assets/create/models/block/weathered_iron_window_2.json +06b0109b8dd43f433de00ff271042b416be7d86c assets/create/models/block/weathered_iron_window_3.json +f7199168a6ac364a03c52dd186bf8a3ec79954e4 assets/create/models/block/weathered_iron_window_4.json +847adaa7197d84669d4c69146595980f179f44e7 assets/create/models/block/weathered_iron_window_pane_noside.json +c0f40f2f698ebc2f2a3affd8aa7520735debb577 assets/create/models/block/weathered_iron_window_pane_noside_alt.json +48a7646b44a34d9721311bbf489214a02ca5cf83 assets/create/models/block/weathered_iron_window_pane_post.json +f6d98f8518f48feb8faf5691ce1de02e9430eefa assets/create/models/block/weathered_iron_window_pane_side.json +94a6c852930e980640a5733536bac21b1c327d18 assets/create/models/block/weathered_iron_window_pane_side_alt.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/white_nixie_tube.json +998d838964c6c5bc2a1903b5098491abf5d819bc assets/create/models/block/white_postbox_closed.json +e89fe63260b94fc70e360eceb3d04b74242c248f assets/create/models/block/white_postbox_open.json 99f0628623a36ac1700a5876cec010ee6353162f assets/create/models/block/white_seat.json +29d6f3efddd06f6c9fd876aefb3f95043fc928e6 assets/create/models/block/white_table_cloth.json f252f8c68702a0c050797a2dc2a51c586408722d assets/create/models/block/white_toolbox.json c9e344a06ee8bca1bfddd70481198135cabafbce assets/create/models/block/white_valve_handle.json 68d8eddfb724c73938862fb1a213a99c95814fdb assets/create/models/block/windmill_bearing.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/yellow_nixie_tube.json +9abbd0af47396b1cb18362b423f497ddb40eede4 assets/create/models/block/yellow_postbox_closed.json +098b675ef5071a32bce387445da09067917852c7 assets/create/models/block/yellow_postbox_open.json cf8477d6c7558ceba38416fae755567086a856a6 assets/create/models/block/yellow_sail.json 07b68f0e4c617dfe3e935a1b9e8e020ab3131c0b assets/create/models/block/yellow_seat.json +199a767acb9a27b5fead0870c00068f3f5602bc4 assets/create/models/block/yellow_table_cloth.json 21bb6e0b43984214c496e531e16dd60aeb619a42 assets/create/models/block/yellow_toolbox.json 467109ede866fb030d2cdc46c832643630d982b5 assets/create/models/block/yellow_valve_handle.json 23d6852eca1bf1480dc74ed51d15c098e26a520f assets/create/models/block/zinc_block.json 617330267f01a08062b05b8516082d7ebdab3d0b assets/create/models/block/zinc_ore.json 86b835fa8d2264feb2159262b069c6c2cf68e818 assets/create/models/item/acacia_window.json -697eda24a3a1c79401d7d073a503804cb589e2f5 assets/create/models/item/acacia_window_pane.json +ab7e40e22fedad4ae69281eb6137e699110327a2 assets/create/models/item/acacia_window_pane.json feb7bd45dc6ec0542c7af648b371e54168641d1e assets/create/models/item/adjustable_chain_gearshift.json be9e4a7937dcb87bce696e6ad234c9eff8cd299e assets/create/models/item/analog_lever.json 626cc26c8a7a2742b991b432c5104981183f1eb6 assets/create/models/item/andesite_alloy.json 158270c9fa3022d1afb56002d0ea1db3366467aa assets/create/models/item/andesite_alloy_block.json -d497fcfe54f9caddf1925cc303f9f9a62015e0ae assets/create/models/item/andesite_bars.json +0a79ae7caa46f64085e0bd7d94018a46f53920b3 assets/create/models/item/andesite_bars.json 11c747281cbe2d96324db27fec020100b50977d0 assets/create/models/item/andesite_casing.json ab09b7886916048add1fa0ea9e87c4644a781031 assets/create/models/item/andesite_door.json 944cbae9f7c4bf7d1734d25645cfa6b0d0f2c33d assets/create/models/item/andesite_encased_cogwheel.json @@ -1683,25 +1840,33 @@ af792bb7d70029e66cc8aa21ed61322f899fb134 assets/create/models/item/andesite_enca 113fb6cb131bc3cdf63f558be71b8d77f9ae64c9 assets/create/models/item/andesite_ladder.json f187d676688c728804ab3758eb4b78a431c7ec21 assets/create/models/item/andesite_pillar.json d0dd86f6c7418c27c0f930cfd20e0867936eca3d assets/create/models/item/andesite_scaffolding.json +2ef7426efa3c2609e67d2eef73f6f84a1b13d46c assets/create/models/item/andesite_table_cloth.json d5375c3de6272a00f3e3787fee6b8255f828d686 assets/create/models/item/andesite_tunnel.json d6eb7105dd9b42adde48bd70e3f2fba70751c1db assets/create/models/item/asurine.json 8b61987c61ae461e4bea0fccf5b1bb3399ac9226 assets/create/models/item/asurine_pillar.json a8e9fab6ce8dc5da29b451c827663fb553669a23 assets/create/models/item/attribute_filter.json +2a57b4e07c5a853d4875fae7916cdb71f3b3f378 assets/create/models/item/bamboo_window.json +3baee1bf202692d9e14865b7ba1e2606f761774f assets/create/models/item/bamboo_window_pane.json 6913f9acbb272de28387918ce92984fa767b4389 assets/create/models/item/bar_of_chocolate.json def88cd2c79a1f0ed40bbf5a0332187dd1d6006e assets/create/models/item/basin.json 35a1e2cb2645a8386dfee2697b47547b3f9a1dd2 assets/create/models/item/belt_connector.json f5dcb9096a52d5d2eab1e4204fbd1222e0d5094d assets/create/models/item/birch_window.json -eccafeec52e4195fbe211c602b4fc71a260d8a64 assets/create/models/item/birch_window_pane.json +9589b0f3d31028c1499a49298600eede6d84f7bb assets/create/models/item/birch_window_pane.json +641b85751f91c0b4931307548c12034fc56286bc assets/create/models/item/black_postbox.json 7ca635d45fef81e6681a492be6c7bb71fd0f4574 assets/create/models/item/black_seat.json +67256e7c62c3ed2cee1dc88c2437083966165f92 assets/create/models/item/black_table_cloth.json e2dc1a8db84d84d592bfd91a26464343b8706bc0 assets/create/models/item/black_toolbox.json 20fbeb136e85d146c0e041f7f1570b1d1fd34585 assets/create/models/item/black_valve_handle.json c31038397821b6abe296d2799aa81edf3c12d095 assets/create/models/item/blaze_burner.json 9d28754112688323a6b55ecb6742e918eabfd6a3 assets/create/models/item/blaze_cake.json 01637416bb932d861e9c9b10b256b2fdf4c96d44 assets/create/models/item/blaze_cake_base.json +ef453775edb9342dc68e0e4ed7aa2e845b819fa6 assets/create/models/item/blue_postbox.json de8beb7ef521822eb9b2826806baf1fa3344a45d assets/create/models/item/blue_seat.json +b1059dd00b8b4102e345a3d4f3e903a92c372ea1 assets/create/models/item/blue_table_cloth.json a82bc56a503cd15d2354c86a49fc6d1d4ed22767 assets/create/models/item/blue_toolbox.json 2f90f781cd9b5d144a6cfd4748ae3a87c9f12ba8 assets/create/models/item/blue_valve_handle.json -4e711f64e0ab7d16c550cc4aa8b876d604dfb2af assets/create/models/item/brass_bars.json +d16ce54ed4e2546f168d3bcf7d748ff749565316 assets/create/models/item/bound_cardboard_block.json +8facd82128e77ed41de3bb92d7714e56fc58ada6 assets/create/models/item/brass_bars.json 136f97f26217c51c932d79bf715b2a1a92e6595e assets/create/models/item/brass_block.json c876713c3b8ed6511679d1e3186e6d6031190dd5 assets/create/models/item/brass_casing.json 378a2f1820c9abdc1080c940e5a01e30c25ea5cb assets/create/models/item/brass_door.json @@ -1715,13 +1880,70 @@ a51a28424e75dbd11c845f455c778d4c578b9da4 assets/create/models/item/brass_ladder. 55208677f9135c3ca897c2432caa332bb1b858f2 assets/create/models/item/brass_nugget.json af97ba84be90381e2cc9434e31e2199c2e7e3aa6 assets/create/models/item/brass_scaffolding.json b78e9274156f5027a9a3b6fb7725c57a7aecc8bb assets/create/models/item/brass_sheet.json +7085ab446db5fa59aafe9bbba41c0e0f43bf749a assets/create/models/item/brass_table_cloth.json 28e104d5041c1f4676704c0f6b4e2e80aac43106 assets/create/models/item/brass_tunnel.json +35c8539a0b2f927e65a43c3a2c3cb82db429c2eb assets/create/models/item/brown_postbox.json fce64539b36fc8a5ffa39d7a3f73765818437cbf assets/create/models/item/brown_seat.json +a126a50454ea449e66c6f6e36eb96bff96652c92 assets/create/models/item/brown_table_cloth.json 90c1ec317beed0b5735c8731e3115a695b7060f7 assets/create/models/item/brown_toolbox.json 9477ab491586f1314bebf4d58387425ae56d0bad assets/create/models/item/brown_valve_handle.json 1db479848369140bb913ba09f3f1d994e4ac864c assets/create/models/item/builders_tea.json f5ff4e2ed2ea2e43b6d02f6a95ba02b2e4b611dc assets/create/models/item/calcite_pillar.json +cc2692f7964f4266ecf00fcab176b1ef0b78673f assets/create/models/item/cardboard.json +607272f2b906fdffd46677d47a4e6ecb94184eff assets/create/models/item/cardboard_block.json +70ab4eb53188efef1a157823ce90e5fd09e35d3c assets/create/models/item/cardboard_boots.json +5c67ce75ffe3f5c9a32877ffdb4005b2a44d6483 assets/create/models/item/cardboard_boots_amethyst_trim.json +2027e70e42e1c931537e591c51b1f2d1aed6833c assets/create/models/item/cardboard_boots_copper_trim.json +881e17e4d8b2be53403833ee262a7a17040695bd assets/create/models/item/cardboard_boots_diamond_trim.json +ae9617e768f8a711d932a5137bd7946c7bb1fbe3 assets/create/models/item/cardboard_boots_emerald_trim.json +62dbafe3a1493be7d46270168e57ff1f866bc669 assets/create/models/item/cardboard_boots_gold_trim.json +dcdc125780505d55bf76302fe982b23083c08845 assets/create/models/item/cardboard_boots_iron_trim.json +86a5435fcf899530bd1caa3fdf83e1dee337f22d assets/create/models/item/cardboard_boots_lapis_trim.json +527602bacf19e6ddb40023e1ad9fd532d96699ed assets/create/models/item/cardboard_boots_netherite_trim.json +bf4ec4f542e5d96ca9b6b90e298526acaa8cb8b9 assets/create/models/item/cardboard_boots_quartz_trim.json +d0a89aae893a45b14173f2f104dc0bb72d14516e assets/create/models/item/cardboard_boots_redstone_trim.json +169470769f90bb6fa0e503c78d8dde4bf63c0e7f assets/create/models/item/cardboard_chestplate.json +37ba0d5584aabd317e984d46e2e56622c10c74d0 assets/create/models/item/cardboard_chestplate_amethyst_trim.json +e50df07949d1a0a7e54e5b1635827adf8c250583 assets/create/models/item/cardboard_chestplate_copper_trim.json +1b82a900bb783a55a32d308fbec4c103981ca0ea assets/create/models/item/cardboard_chestplate_diamond_trim.json +90f5afe6a3e8292a37814ae6b8d1ca78bf1279b7 assets/create/models/item/cardboard_chestplate_emerald_trim.json +84ac8525c149e6f630fa02ca53d1e0a0b5f55b3e assets/create/models/item/cardboard_chestplate_gold_trim.json +6327a6514a3c19e9faf31c5388103e1e8cc7d01c assets/create/models/item/cardboard_chestplate_iron_trim.json +0df84176624b1cb081f8bff881156fbe530fda43 assets/create/models/item/cardboard_chestplate_lapis_trim.json +f27591c2befb21f6aa944bd2f54e7c4f58833917 assets/create/models/item/cardboard_chestplate_netherite_trim.json +3ace2f1c1a773d5d9d2b4f3d6c93f742d9bd971d assets/create/models/item/cardboard_chestplate_quartz_trim.json +9e74713fbdc8d90697f264562316f991de51d49e assets/create/models/item/cardboard_chestplate_redstone_trim.json +0b46dc6ac222fcf998100f1656047058fb8ef1ee assets/create/models/item/cardboard_helmet.json +61fad07fcc7da51ed9806938c7c1d930481015d2 assets/create/models/item/cardboard_helmet_amethyst_trim.json +c185e1b969ffb78df3d956a5907486a5abe81d55 assets/create/models/item/cardboard_helmet_copper_trim.json +b5ecea23091e2fa7d0b004a73a210ec4cf970035 assets/create/models/item/cardboard_helmet_diamond_trim.json +1b908f938a492f1faddf7f47e44f99dd0e0cc700 assets/create/models/item/cardboard_helmet_emerald_trim.json +f7096241733b0623eade076fcc536c0a3dd9f252 assets/create/models/item/cardboard_helmet_gold_trim.json +079c0ea69a5c8a7d1bb2e1bdd23ccc9c92e036d5 assets/create/models/item/cardboard_helmet_iron_trim.json +4db478f4669c26edef502b87be277be314933cab assets/create/models/item/cardboard_helmet_lapis_trim.json +ab46809613299865e33dcca39df597a239174df8 assets/create/models/item/cardboard_helmet_netherite_trim.json +03d4eb863c7b4cfc60a81b270a569440f0c62c85 assets/create/models/item/cardboard_helmet_quartz_trim.json +2703a1c5c65fe5c74c03bfe8ab6acfc4e5849cf9 assets/create/models/item/cardboard_helmet_redstone_trim.json +9987b29466b2a83ef25c66f51086b26ccd2c5a5b assets/create/models/item/cardboard_leggings.json +6a98f395678073c3ec0c09556b38cc9ac9e63492 assets/create/models/item/cardboard_leggings_amethyst_trim.json +5e932da44be1022af8c97061caca61a97c99b6d6 assets/create/models/item/cardboard_leggings_copper_trim.json +e010c6af3e4c3c5cba26491c84c2c73c3c9386c7 assets/create/models/item/cardboard_leggings_diamond_trim.json +6f7a3ed21abf915f5803922db3a15fb6210162c6 assets/create/models/item/cardboard_leggings_emerald_trim.json +8176633be5a2ea548fa39df1d875a29851a7b091 assets/create/models/item/cardboard_leggings_gold_trim.json +56254db2e5432386b4de1ab00603f72255a8aa61 assets/create/models/item/cardboard_leggings_iron_trim.json +ca37276063d58483994ab51e3f72ef20521902c2 assets/create/models/item/cardboard_leggings_lapis_trim.json +55dfc8af30c392b0a70390d90c4239aba011d0ac assets/create/models/item/cardboard_leggings_netherite_trim.json +3f7d0d84790570dd92bb83071d6ecfddadce047d assets/create/models/item/cardboard_leggings_quartz_trim.json +47963712e6a470c5d14d7ea1bc8fff2a0553267b assets/create/models/item/cardboard_leggings_redstone_trim.json +123f7b8f5129e07beead05846744ff06161ec7a1 assets/create/models/item/cardboard_package_10x12.json +4f22bc19ebf19be0efc32b5d2fe449349e6f5b2f assets/create/models/item/cardboard_package_10x8.json +599d305569d025d8771993d0b56a377f910e2a95 assets/create/models/item/cardboard_package_12x10.json +563720f20bee58dfc5b2c628cd037f7b6daf6a34 assets/create/models/item/cardboard_package_12x12.json +9dccb21720687bbd516c8598c5449028077f8467 assets/create/models/item/cardboard_sword.json 1cdb2b8801551c1540bb9b2a9cc3d725a2b433e7 assets/create/models/item/cart_assembler.json +390a06d81c8c2a0ff83196bd0154dd292206e3b6 assets/create/models/item/chain_conveyor.json +74c265b6ea2df76ae1b2e8e920eaa91749f74c1a assets/create/models/item/cherry_window.json +7aecdbca8bc44bdf9a6926889bdbf4e74c4407a7 assets/create/models/item/cherry_window_pane.json a197d08618f4035182c91a6b16031eb681ab8a7c assets/create/models/item/chest_minecart_contraption.json 293cfa8b1073f8641a2c623b73a90907576c36ed assets/create/models/item/chocolate_bucket.json 77654cbd16cdfa95181ea3f85fcfa3cd352b69fd assets/create/models/item/chocolate_glazed_berries.json @@ -1740,7 +1962,7 @@ de48f4b6fa26928ebc7d5d60e6a0767093430d65 assets/create/models/item/contraption_c 6a4e8aa37120fa8238be72fb2c732f9ab5670d53 assets/create/models/item/controls.json 68d0bd260e5062448ca9008f7cf44e963d941653 assets/create/models/item/copper_backtank.json 6c53b1a6ed28929b7a0a090edf6101e610f842fc assets/create/models/item/copper_backtank_placeable.json -2a0b31d76ab8a74c458475640d17de15ad314fcd assets/create/models/item/copper_bars.json +aaac7663d062731433c920d94a24b9b3a521dd8c assets/create/models/item/copper_bars.json 688e4dee99126b7507761de618d6788c18f17153 assets/create/models/item/copper_casing.json 68890c027cd6a094b484a237d3ff5daeb09622af assets/create/models/item/copper_diving_boots.json 23499699c6ea6a30673835056f5d0039519413fa assets/create/models/item/copper_diving_helmet.json @@ -1752,6 +1974,7 @@ a4fd2f4f00e03b2ac5d863e93827d39a984cc2ff assets/create/models/item/copper_sheet. 79d9f8667965072f12e51e6601b5c36f8acc125f assets/create/models/item/copper_shingle_slab.json 9fe6f0bdea4595b403ed2d2cbc2023a9abeb79f0 assets/create/models/item/copper_shingle_stairs.json 13b18ba2938e283d507fbca70518cf52198cdc71 assets/create/models/item/copper_shingles.json +9a33eeb0f7c682ee2f8c0abbfa174f8828acc2b5 assets/create/models/item/copper_table_cloth.json a7147444fc28a4cce21b6cf38e9528537e27c352 assets/create/models/item/copper_tile_slab.json 7330324d6c64f0340d676ecef83a930515d9130e assets/create/models/item/copper_tile_stairs.json 19642e4ea5deecaf57059827c4c13a19d2e73822 assets/create/models/item/copper_tiles.json @@ -1767,7 +1990,7 @@ ad620bd5eb32a41b0a8a130f49ab3dbb398907e5 assets/create/models/item/creative_moto 612778c4a390c3fc9de7ef40713375dc7be85270 assets/create/models/item/crimsite.json e432e359b77e7129e18c1d4daf68d11c4a661110 assets/create/models/item/crimsite_pillar.json 9c77e6d7d56310b34468a6d52080e477e893494d assets/create/models/item/crimson_window.json -43625514f941a61cfbae339419d0de4b22db9662 assets/create/models/item/crimson_window_pane.json +cfad32c8024f9f1479aed6916735a4d75b16dc4e assets/create/models/item/crimson_window_pane.json 189ddf2f3c83608ddfe9e8d2fe88d8b4610ade13 assets/create/models/item/crushed_raw_aluminum.json 4e74e066349d0311064e21fd72aa40e249e2e830 assets/create/models/item/crushed_raw_copper.json 513ccb83879e523f8df66a4ad8aee0ecab1ba003 assets/create/models/item/crushed_raw_gold.json @@ -1895,15 +2118,18 @@ f633006045ccfcdf486d7a240217229d6eed717e assets/create/models/item/cut_veridium_ 410b949304faa5856028f7c42ab762b7498ffd95 assets/create/models/item/cut_veridium_slab.json 62697c0922b11537914d2f4f84faa0b909ee518d assets/create/models/item/cut_veridium_stairs.json 3921d61a26d48d999cbb2f6645611e53ea71978b assets/create/models/item/cut_veridium_wall.json +73c2eed9b6a906a519e27361211ae05bc6ed2d87 assets/create/models/item/cyan_postbox.json eef3be2fa3b6424436a553e3c1bfee3979015962 assets/create/models/item/cyan_seat.json +fb3660aa1b33ef63361d91598c2b46dd5b1c30d7 assets/create/models/item/cyan_table_cloth.json 265d5d6de4238442bb9b161dba0a2fc2f063df0b assets/create/models/item/cyan_toolbox.json 8beb6459822efe59d0f60749143d73c5390e39f2 assets/create/models/item/cyan_valve_handle.json 2e0a1bb3f3498454eb23dab5d4eb6fad98fe586c assets/create/models/item/dark_oak_window.json -34088ac6ee20cd56c309ad687e2b721fc6070b0b assets/create/models/item/dark_oak_window_pane.json +e30c50f79332cb2cd2815554af84747c58545a39 assets/create/models/item/dark_oak_window_pane.json 5b90f8778ae1c2dbd99da89407f12bfb4775b123 assets/create/models/item/deepslate_pillar.json 9b5b804fe75a3e748a0d9a6761ab46178e5f3850 assets/create/models/item/deepslate_zinc_ore.json 7ff5075e907b57d6b0f6fd0a31d0e46464afe634 assets/create/models/item/deployer.json aa44d681c3ccffe08aedbda093062b1a5ab3302e assets/create/models/item/depot.json +63e24083922af9d5300aea771bb63bb9962ba3e6 assets/create/models/item/desk_bell.json 85a5830ca034be9a0ed534186210aa975278b20b assets/create/models/item/diorite_pillar.json 2a992f0961b8bab5628e075da413c91e903e424c assets/create/models/item/display_board.json 0dd4d33644c9ec7dbf920d7fd7b713e4b413b330 assets/create/models/item/display_link.json @@ -1925,6 +2151,7 @@ a443633d90ef9ac2a866b69b2ecdfad1841dc3e1 assets/create/models/item/exposed_coppe 9bb425a14635fc8b36a9a95f3d0c54e0b129b7b4 assets/create/models/item/exposed_copper_tile_stairs.json fa7ffb172a43774cc07a2bb201e7010a2549001d assets/create/models/item/exposed_copper_tiles.json 8b64a93d9b6e33e3caa66adb7a0cc8c5cd473023 assets/create/models/item/extendo_grip.json +9114fa2e92ea4b7bf949b2e5a26290b0bade1af3 assets/create/models/item/factory_gauge.json dad31483f65baaf187e6553e3cd301c5d69e9db4 assets/create/models/item/filter.json 575047531b8e324df9e58abba79cfe9ee3db8b16 assets/create/models/item/fluid_pipe.json 51d34caaa63685e901b8bfe6ced13ff2e8914ce7 assets/create/models/item/fluid_tank.json @@ -1932,7 +2159,7 @@ dad31483f65baaf187e6553e3cd301c5d69e9db4 assets/create/models/item/filter.json 37dcb8911cd29d883849b655e3e388dbba5df6c0 assets/create/models/item/flywheel.json ddeba2ef1d185629be5c88aeb2105fe0aaae3951 assets/create/models/item/framed_glass.json 02a88f5c9aab6fc2f6cbbdaa871fd67476c9a9c2 assets/create/models/item/framed_glass_door.json -c27e10488bd56237af75b1fd8742a5e633d7ec4a assets/create/models/item/framed_glass_pane.json +3ed4300d2fb60b4e2761fd7a2d1f116fecea150a assets/create/models/item/framed_glass_pane.json 127386f4dee6c305023e45ad6b2f04fd6d4e5009 assets/create/models/item/framed_glass_trapdoor.json b17d9fd1a92db0965f2e5da6215956b0451af29e assets/create/models/item/furnace_minecart_contraption.json 7b3a197eed9dec75f95aaed8e438d49d46948f1d assets/create/models/item/gantry_carriage.json @@ -1942,10 +2169,14 @@ b17d9fd1a92db0965f2e5da6215956b0451af29e assets/create/models/item/furnace_minec 7c850a41a754e46bb9c9f257ed621e37a1b9506a assets/create/models/item/goggles.json b1ae37998326c8ca054e57b0cbff0b51cad98625 assets/create/models/item/golden_sheet.json 85c301898775d5720d4d11c1c555b331a5c2e93b assets/create/models/item/granite_pillar.json +44173ca711aa497d08ca3b8a9613290378072870 assets/create/models/item/gray_postbox.json b8d6d2d163e2ab5f654bbc4eda9ad63f8064d27c assets/create/models/item/gray_seat.json +4a9aa604745afcb19c3495a879013e263415f214 assets/create/models/item/gray_table_cloth.json 6492f86b693f924d0222d0ca1d16fbe33d797b1a assets/create/models/item/gray_toolbox.json 2a9500f9630b1da44615c7c9ca145b56324c46bb assets/create/models/item/gray_valve_handle.json +1a97f63df2977ac2f2e3363c61a7e36bf60d3ce3 assets/create/models/item/green_postbox.json 2843370b0e693e1ba1777c26416914edbd87c4f9 assets/create/models/item/green_seat.json +334fd81d5e6574220ee5815f1452b4f4aa7ad223 assets/create/models/item/green_table_cloth.json 561e0579101bf602b252c0b9a5eec468c89d0e40 assets/create/models/item/green_toolbox.json 7d3ddad087b4d2c6a32f97092533cbfb5de0cb3b assets/create/models/item/green_valve_handle.json dac0331061c464e6d3e2070b232781c632840191 assets/create/models/item/hand_crank.json @@ -1954,16 +2185,19 @@ dac0331061c464e6d3e2070b232781c632840191 assets/create/models/item/hand_crank.js 2e97629313eab1a4ac4b38785dbe7ed45346e625 assets/create/models/item/honey_bucket.json 81d67fb0e59f25762a412990884813c72d399d55 assets/create/models/item/honeyed_apple.json 70185e640169d6253f06fb98f31b240f4807a53e assets/create/models/item/horizontal_framed_glass.json -e623c9541adc0fa877c5615e3211f47886383f2d assets/create/models/item/horizontal_framed_glass_pane.json +d47884b13fadf545bd585cd9ae347368924b04b0 assets/create/models/item/horizontal_framed_glass_pane.json 58b6f4ec2af3a69ae7145fb25d73451b6e8a2834 assets/create/models/item/hose_pulley.json 14ae1ba5e842715fc4526b19e20c74d10102eb4a assets/create/models/item/incomplete_precision_mechanism.json ae5c5925ecf775a4f5c3dc3c79d9766d7dd34ab6 assets/create/models/item/incomplete_track.json 43173d18384817288a9ba687da77a4fab31b1957 assets/create/models/item/industrial_iron_block.json +4596b83d7da43a670f2274c8389cca9897ae379d assets/create/models/item/industrial_iron_window.json +199e1b60315fc2d016b69d2d60fcb790a6e075fc assets/create/models/item/industrial_iron_window_pane.json c6e3e4ca8b3dfdaaa943faa3dc89c0b2e6f2b5c4 assets/create/models/item/iron_sheet.json d1fbf1be53208c3ab5384dfd6be4d980c858941c assets/create/models/item/item_drain.json +5adda29ca25d00eb41884d0b7ad4a471e250ae10 assets/create/models/item/item_hatch.json 908dd0a4eafd868d280e25cfb7721f20b649560f assets/create/models/item/item_vault.json 5fba1fa33e360c2744ec74d7ccb63f9baa295546 assets/create/models/item/jungle_window.json -b3a0c9664465f49a2f53e4ded6c29710a357e6ca assets/create/models/item/jungle_window_pane.json +1a76bf2c7cf1036c458651536a7be8511a39d551 assets/create/models/item/jungle_window_pane.json 26c3f75074779ec0286e19219bd277147bfb9e96 assets/create/models/item/large_cogwheel.json 23f9028ae83a1723071c67cb6a1742731969e21e assets/create/models/item/large_water_wheel.json 33978f928e1f548a2b53081d6a7517e41d875ec3 assets/create/models/item/layered_andesite.json @@ -1980,24 +2214,32 @@ a22638fd361a8185175e107a8ee092a9ac030b7b assets/create/models/item/layered_grani 14494272713544a1595d654fd397a986b2da0951 assets/create/models/item/layered_scoria.json b1174d783c62dda84aafd4259c622197f4664421 assets/create/models/item/layered_tuff.json 952b07dbf9ecc1883deabaa1344667f13936f7f2 assets/create/models/item/layered_veridium.json +623c937db944651cf1075b3875afe002db527ed6 assets/create/models/item/light_blue_postbox.json b44a9f1bd9079f3533d7f708d76eb19a864e5ebb assets/create/models/item/light_blue_seat.json +df2a3c76b7dbe1f5f6556436e7db3b72288b2232 assets/create/models/item/light_blue_table_cloth.json dae914625ff1bc3ebe1463485cad4526a7d7e9f5 assets/create/models/item/light_blue_toolbox.json 1d94314f185151eb9dcabcef950abf6f86c3c836 assets/create/models/item/light_blue_valve_handle.json +b56a28924b0b1b2530ebac7834e011700b09b966 assets/create/models/item/light_gray_postbox.json 1747bcdea3b1d3f5dfb786102069e07198d36dfe assets/create/models/item/light_gray_seat.json +cc8834024208662cb100f7cd38a04637da3b6852 assets/create/models/item/light_gray_table_cloth.json c8513eb1c89652783e26d7dcfcf64afa97619bc8 assets/create/models/item/light_gray_toolbox.json 3774d23e76b5712e7004e333e0a770f2230c2998 assets/create/models/item/light_gray_valve_handle.json +26b8e1daf9cc4b206fb5f62904c7f1701ba93e67 assets/create/models/item/lime_postbox.json 32cd55a1c97a31a13ad106a457ec9925aa91f6d3 assets/create/models/item/lime_seat.json +a0843c3731fa3c4d23bc2b91fd68410fcf1df149 assets/create/models/item/lime_table_cloth.json 931d187c11cb95a0eeae8f256187ef551b42007e assets/create/models/item/lime_toolbox.json d0f4148bdb0a905e68f54b5dfd829fd47e528fea assets/create/models/item/lime_valve_handle.json 8f53caad3899a30be5087a0ba155080834418cc0 assets/create/models/item/limestone.json fba1e7d1cad39c89976b427db62544d80f47ad5d assets/create/models/item/limestone_pillar.json 1d30f9b525e8e9736b34a92f848e235c71fd6bd8 assets/create/models/item/linear_chassis.json 8f622f5f79446f6060d9e8815205fce919c8c829 assets/create/models/item/linked_controller.json +538e28af9013a43c258a659cbe67671991f3eee7 assets/create/models/item/magenta_postbox.json ad6fd371ee989c9c3c21e762273e8a4e903f0af8 assets/create/models/item/magenta_seat.json +c50cb6b0285ee3a2b7d7f592ee48672d66e02af3 assets/create/models/item/magenta_table_cloth.json 7c0e3f91e5ab029473736deffb2b2aab9d4763c7 assets/create/models/item/magenta_toolbox.json 6d82582e5afea919927606b20a74cbda5223956f assets/create/models/item/magenta_valve_handle.json a4ecba2ee36699401de661b89065bf0738487a87 assets/create/models/item/mangrove_window.json -474c896c4ca4e6547fac225cc204bbc0b287c5ea assets/create/models/item/mangrove_window_pane.json +a8d3d6f1329c75d4d5a1db3e7fad40eaeca53716 assets/create/models/item/mangrove_window_pane.json d5b1665cdcf03baef41a8d3fbbdcc747cd6867f8 assets/create/models/item/mechanical_arm.json 95d437fffd455e5a22d288bb7683fbdce211fa8a assets/create/models/item/mechanical_bearing.json 08dcab9d0cdb7fb6426b8dee508eecc3f5d71fb1 assets/create/models/item/mechanical_crafter.json @@ -2023,22 +2265,29 @@ c11656a940ef54a023634376c742b3fb17201f92 assets/create/models/item/netherite_bac f80358eba19bc8d1741e4e25753866799631a118 assets/create/models/item/nixie_tube.json 33c5dfa7ef718fb29cf59bb0c04ebd88cf20eb1c assets/create/models/item/nozzle.json 39626402ba637abced828902d9d657ab09edcadb assets/create/models/item/oak_window.json -061587faf0e53e4fac0c8f2f3bd6b22020b2a3ee assets/create/models/item/oak_window_pane.json +7d9eef77eb18dd5c768e48b5871ca2dcdd1a136c assets/create/models/item/oak_window_pane.json af50363d603d61340b336569d58c1febde253665 assets/create/models/item/ochrum.json 62ec1afee14f9de3f5b02ee930d002a240a3c337 assets/create/models/item/ochrum_pillar.json +226f99c241b1d8b03d8fc57db32c1bee0721b64f assets/create/models/item/orange_postbox.json 56e7d28824d3fc566b5f551babbe423a550ef08c assets/create/models/item/orange_seat.json +9f122183a1b04ac6346631db4f505e53ed333acf assets/create/models/item/orange_table_cloth.json 96cc543d5afed90a022ece7b8671cd47a9b6fb68 assets/create/models/item/orange_toolbox.json 7e767ca9e0ddb769b38fabd9289648ac63f5413d assets/create/models/item/orange_valve_handle.json 82152bca4310111d91584a2a78f05e158bb4bd90 assets/create/models/item/ornate_iron_window.json -f9064c1f199bcd8db321078e2363ed91cb2acc09 assets/create/models/item/ornate_iron_window_pane.json +ca749a88faeef441c55c0527d81257187938b6b0 assets/create/models/item/ornate_iron_window_pane.json c9c7ccdb68de2e77cd9f7053fab19493dd30a985 assets/create/models/item/oxidized_copper_shingle_slab.json 89c5f7a0a28f238ebed2641e243a47e4be2ad5ab assets/create/models/item/oxidized_copper_shingle_stairs.json 09b3cd8ff7b29a6dd59f739a95bb708646d23537 assets/create/models/item/oxidized_copper_shingles.json f1af7c5f3840efc3ae07940ee6719eb3417a0e1a assets/create/models/item/oxidized_copper_tile_slab.json ef2fe68d407a03bf1ed8f2d2f3e7323777d061bb assets/create/models/item/oxidized_copper_tile_stairs.json 1c3428e2aed32a013631db012642a34d4eaf0785 assets/create/models/item/oxidized_copper_tiles.json +5b974e55caffdbfc2156eb8b59dd99db12243bd3 assets/create/models/item/package_filter.json +7fd76e7d2e6c6d94352f1fa08d096b63616ad01e assets/create/models/item/package_frogport.json +b21a1f3ee7de3e17f69d27fd13ae6b23b62aa22c assets/create/models/item/packager.json 76aeceb41bb7df873dbafe1bd5e26deb24abf93f assets/create/models/item/peculiar_bell.json +ab6c05a0468f3f4295a07adb362fa2d36cf6e3e8 assets/create/models/item/pink_postbox.json df13d4281dc45041ecd93504d45daef61d070581 assets/create/models/item/pink_seat.json +d142627de73dc821281d64ab54fe9956936253b4 assets/create/models/item/pink_table_cloth.json 842afb2a345dbaba857e90f7dffa724841ef7b2d assets/create/models/item/pink_toolbox.json 6b85a0da81b2d18fb54eb05e187a2ce8cd7b09eb assets/create/models/item/pink_valve_handle.json 9e8b4c1a0bbcb0ea9b15aec174d8f98b572133d1 assets/create/models/item/piston_extension_pole.json @@ -2108,23 +2357,41 @@ a06275da5e5cec7c17edaae8b5a693a3eeff2fe2 assets/create/models/item/powered_latch a1c6fd9b035eed7de732f4080cedaa118a2bc559 assets/create/models/item/powered_toggle_latch.json bd70b798ca9f73f4e5aabc30e286487f5363122e assets/create/models/item/precision_mechanism.json d9a736e7a6fc70e0848de3e318c739d58b1e563f assets/create/models/item/propeller.json +34c09fb1eb46ed362aa384958c2ad2cc96688abb assets/create/models/item/pulp.json 9b41eec5759887be9bae3d27654bf478a7eff676 assets/create/models/item/pulse_extender.json ea76bd3bd9e5bea4d64d91347d473b538e926b02 assets/create/models/item/pulse_repeater.json +6ff9ce0cc633ea39b779b2e873a1d0fd7cfe7119 assets/create/models/item/pulse_timer.json +8496f6c5449a70eef12e9c68ba46eee2f365fb77 assets/create/models/item/purple_postbox.json 7e165f83266edf34bb03fa3e8d2a83d44829c10a assets/create/models/item/purple_seat.json +0d688a25e03c9f0e7059998a44a5be31e570a04d assets/create/models/item/purple_table_cloth.json d75c4969334f2ee1ae4a3d8ac28b001735c76b97 assets/create/models/item/purple_toolbox.json ebffb05119f499fcec051a4337aadc47654baed2 assets/create/models/item/purple_valve_handle.json f91405b9aec1e0142c1b90582e03a1973251da05 assets/create/models/item/radial_chassis.json 1c984ea9dbaec02e88dba1b81906c9acca7ed672 assets/create/models/item/railway_casing.json +87c4c0e13441cf0238103ca065c0c16f80f60f26 assets/create/models/item/rare_creeper_package.json +f15145349b717dbd58b696019d38c7c8c506dee2 assets/create/models/item/rare_darcy_package.json +8bb602b530ac2c1301776b83673ef062b7b0ace6 assets/create/models/item/rare_evan_package.json +f982794c2e01a70fcc2bb009bcb8cd06a2ea5510 assets/create/models/item/rare_jinx_package.json +9f4de06da4d9c2b54b758b2b01e0595811338b94 assets/create/models/item/rare_kryppers_package.json +7830b48ef4292922f0ef13f9a7c2ee7d47366169 assets/create/models/item/rare_simi_package.json +fd2345d4e4012ba238501985962cf9d34ab2cd34 assets/create/models/item/rare_starlotte_package.json +d3274003067a943d749ba5d23b5abc0fee8727a2 assets/create/models/item/rare_thunder_package.json +95aae4907a2435e31f079411dd1b3625ab2689c4 assets/create/models/item/rare_up_package.json +48ceaaead35ae1422542a615c9db55bd88f464e6 assets/create/models/item/rare_vector_package.json 5f8e5283fbebb452f1a1141b33ee73f08879c75d assets/create/models/item/raw_zinc.json 4631d67976cef148c346a7016baaa6703e4f243e assets/create/models/item/raw_zinc_block.json +4b73ee9cc2651a3d1a97476d100f9c4d7e2b2efe assets/create/models/item/red_postbox.json 8d00eb1a10055a802556eab10e13f522d12acd1c assets/create/models/item/red_sand_paper.json b64a054c92cbd2e055502d470f3921d1077e63a1 assets/create/models/item/red_seat.json +359d9bdb2496140e297a1e5a98c9563bc09d56b9 assets/create/models/item/red_table_cloth.json ac4695cc465d094b4adba1a4e9efec42c916f37d assets/create/models/item/red_toolbox.json 02473f42ef4b53dc809c7c58ae657c014bfaf652 assets/create/models/item/red_valve_handle.json 9dc6c52e258b00cac6ed23147983045c43218b5d assets/create/models/item/redstone_contact.json f8f733364bdd32b2ad597e81103bc02344ce63bd assets/create/models/item/redstone_link.json +ae0ba4827a81bd51c5c01178c2ccdae3a722628a assets/create/models/item/redstone_requester.json 9926bbe6dad7c4c1a146492116d232e941c80d2b assets/create/models/item/refined_radiance.json bf827486dc7a1b3aeae577844d2dab2a97051db9 assets/create/models/item/refined_radiance_casing.json +a982c29763d90556cca03074c168462a52cb9526 assets/create/models/item/repackager.json 69dc8139280bce3a7e08532afbbc5c41e7942be1 assets/create/models/item/rope_pulley.json 7a93e1b9557422f6b5dfc17e44524805ec4575c6 assets/create/models/item/rose_quartz.json bfbe599cada68962c66cbc6a3e88019fbd9cffd5 assets/create/models/item/rose_quartz_block.json @@ -2147,6 +2414,7 @@ ff36a19e124caf2ee8a03767e39601df6866075b assets/create/models/item/secondary_lin abaa6da82babc26717ffff44fc41327bd015c9a6 assets/create/models/item/shadow_steel.json ffaec38d11b91add4e150e33d0e0e49394f5beca assets/create/models/item/shadow_steel_casing.json b6fcd9722e5a09a9207964cba68752512e3b945a assets/create/models/item/shaft.json +617c6e2f759b2a95da7ee7192a2661afc6f6e8f8 assets/create/models/item/shopping_list.json fa92996fada8545fc340fb401bd0568f56809bf0 assets/create/models/item/small_andesite_brick_slab.json 08474bf814a55795c1f94203ceb8a969be2a2132 assets/create/models/item/small_andesite_brick_stairs.json 0e00bc6aa5be242217ed6fe8cbe1ccdf180742fb assets/create/models/item/small_andesite_brick_wall.json @@ -2209,24 +2477,27 @@ ab4e7695e99548f83a89f3d5ad7690a576bafcc0 assets/create/models/item/small_veridiu 67804bdd890f167010f6101a700e85a3245f4cc3 assets/create/models/item/speedometer.json 4bc463849e2309aa7bb996c403bfb565e950aa49 assets/create/models/item/spout.json 09784bf20529fdc5bb76892c10cea14187748a82 assets/create/models/item/spruce_window.json -368bc939a79864c4bce0fa05d91760bd75c9e5cd assets/create/models/item/spruce_window_pane.json +693cdacb67b28b5d69c8541fd1e0c246b26260ae assets/create/models/item/spruce_window_pane.json b82ab0c69df330f6f938ed1beee7b4add67d2e50 assets/create/models/item/steam_engine.json 24acc593a5e910b6301afcb3f23cba526d23a0ab assets/create/models/item/steam_whistle.json 54f200be903e056e5cf9e2186f0a0a51f8f0f84e assets/create/models/item/sticker.json 0f88de164439640cc175ceef2017f7416b5a7018 assets/create/models/item/sticky_mechanical_piston.json +97222d9eb36944a89b8047423eafa6af3da82b0b assets/create/models/item/stock_link.json +67c98c6c7f2122850acfbee34688572934fdd226 assets/create/models/item/stock_ticker.json 4b640b66765b206f8c2884b7c1a1ef860b81d841 assets/create/models/item/stockpile_switch.json 6ee792277b9fd980c40e18e841afa63fc500ed0b assets/create/models/item/stressometer.json 8d4ce1ccf180016506292f63188c10d0dabe0ee3 assets/create/models/item/sturdy_sheet.json a10bb4d6d1a4483a806e3aaa086d48c0e20aaefe assets/create/models/item/super_glue.json dddac09bb9dd962d99502ab10929ae6886fbd831 assets/create/models/item/sweet_roll.json 6264be89eb998566b171beb073594393041780ca assets/create/models/item/tiled_glass.json -0ef4d2df2a4096b87b86506efc5c9404944fe982 assets/create/models/item/tiled_glass_pane.json +20fde7ab92e521fe861374148b240378990e9e12 assets/create/models/item/tiled_glass_pane.json 4683ab824d93cd96a82143eb9c62c9777f278f18 assets/create/models/item/track.json c4bd1224b988ca10708fe9538a0baa8b88272eb5 assets/create/models/item/track_observer.json 236d89ebd8ae45344b374264d39947d82a2d1914 assets/create/models/item/track_signal.json c08a82b94666ca81a6d9134c740cc9c28ddae892 assets/create/models/item/track_station.json be3b40aee1c62680ddcf9129fd9f926bab790590 assets/create/models/item/train_door.json 1d45bba128629e6c962a9260d49f2df83958ed16 assets/create/models/item/train_trapdoor.json +b3a5de0cddc4d9d2d1858535220cb527735e86bc assets/create/models/item/transmitter.json ba7a9f542e9f65bdce3d3330a95f1166a0be0673 assets/create/models/item/tree_fertilizer.json 55aafc103c38057faa3295ccc76da99f4a91de52 assets/create/models/item/tuff_pillar.json 0e199ab3e450156aae2d54c227383af9bb3f7082 assets/create/models/item/turntable.json @@ -2234,11 +2505,11 @@ ba7a9f542e9f65bdce3d3330a95f1166a0be0673 assets/create/models/item/tree_fertiliz 63a159b54de6a31ee265750e4af4b1990820eda6 assets/create/models/item/veridium.json 38970acde350735e00b53e6836ccee428c630fcc assets/create/models/item/veridium_pillar.json 9b2e4da1ab7e20cd744adb469dd3690e33cc905f assets/create/models/item/vertical_framed_glass.json -63d94954704691fccde1b13b320ec62a4e12a13a assets/create/models/item/vertical_framed_glass_pane.json +1eda3a4bc309eb9f125c583c1d398a1cb9e3a4e7 assets/create/models/item/vertical_framed_glass_pane.json b0f6d37aa695395e28a23d36775092f63ab3f5a5 assets/create/models/item/vertical_gearbox.json 011ef16e912638b4095d34c8c711ebd67cb85fba assets/create/models/item/wand_of_symmetry.json 9c5087114e35052c5e56bb752252de5d092408c5 assets/create/models/item/warped_window.json -83502f4b8d0134e793611b36a56cca59af097ed5 assets/create/models/item/warped_window_pane.json +cdc1226f8a098adbc420fe50c98466507c3a3157 assets/create/models/item/warped_window_pane.json e5939b47bf7440dc101c667e68ef6bf750a3290f assets/create/models/item/water_wheel.json adc188e4e48bea80607c6e0c7076c9bdd7236cb0 assets/create/models/item/waxed_copper_shingle_slab.json 7e224aceaa94361256e95e4c44d8814aebaf297c assets/create/models/item/waxed_copper_shingle_stairs.json @@ -2270,51 +2541,44 @@ dadc7b65a4527e288c21a20df978796a8c444fd2 assets/create/models/item/waxed_weather 0b1b299d6dfab65b6060305a8b3e51f6e2df09f4 assets/create/models/item/weathered_copper_tile_slab.json 0c3989b44fde934ba8b88b071887e5ede522c417 assets/create/models/item/weathered_copper_tile_stairs.json 99f17b16b68201aefb78298b3e6c657e3c2235e0 assets/create/models/item/weathered_copper_tiles.json +b5d591fbb40e062efe301b3b3b49580e5ad64566 assets/create/models/item/weathered_iron_block.json +a569ddd725898a86f8745e46723edeff7fe7f2e9 assets/create/models/item/weathered_iron_window.json +68ca3316942b2df1623893cda722402238ab7724 assets/create/models/item/weathered_iron_window_pane.json 79431edb868e6560f4f6d5b3441c0176c7699f5e assets/create/models/item/weighted_ejector.json 0fd2214cdff8a92e05d9d5ee888329b3235143c0 assets/create/models/item/wheat_flour.json aacced59d21212090d508a9684bb46c9472a8a2f assets/create/models/item/whisk.json +bcf3104e463ec212dc239281033e4e80d78e1d74 assets/create/models/item/white_postbox.json 4e112e82185e2c1a5c57f5a94fa11c59c92cef0d assets/create/models/item/white_sail.json 17ed8ac7d745117f622190a46c5e1b42892afc29 assets/create/models/item/white_seat.json +0fa9208df662c018499902e3aeddf1bbec16c3db assets/create/models/item/white_table_cloth.json 432040f39177ab3df6003df24e818c73e28cf754 assets/create/models/item/white_toolbox.json 8ba8a6d4baf98f0f037f83b4b704f75a8d46a26e assets/create/models/item/white_valve_handle.json bccccbdfa5d376936e123defa44f2907dc317617 assets/create/models/item/windmill_bearing.json 47c6ad1c146366156a0ec4bc1cbf74282784698f assets/create/models/item/wooden_bracket.json 6c08d2fa59e56e4848063ab6f3e45894b89f1744 assets/create/models/item/wrench.json +3a899db3044ee39ac5d6385c16630733e00f77ca assets/create/models/item/yellow_postbox.json ac59f141cd3c3f7e57a794e542d6e22bf8ebb8f9 assets/create/models/item/yellow_seat.json +1f9f7c6102a0c5e1a6e50a6ac67858009a13153f assets/create/models/item/yellow_table_cloth.json 532a429d58a177f61b4d67180db7676fa7536052 assets/create/models/item/yellow_toolbox.json 2c87ef8a26a01a17b2f3799d62cb27cf1107d061 assets/create/models/item/yellow_valve_handle.json bcf63b7198d31d3a94b2566171b7e3e84464601c assets/create/models/item/zinc_block.json d4a3290393c1c659f3d4dd4e267a87d287bd49a6 assets/create/models/item/zinc_ingot.json 1e9656f81ec01a89796b175cf029d1de45b758fe assets/create/models/item/zinc_nugget.json f3719d4d3a8d1e0d9f36db5d1317894ecacf3bf3 assets/create/models/item/zinc_ore.json -63d74987f8461b4e94c00030d380d4891707d2ae assets/create/models/threshold_switch/block_ceiling_0.json -12496e505374e7fff2d1f800218848635d86ec71 assets/create/models/threshold_switch/block_ceiling_1.json -523bc69211b6e90cc381356f103b01b8d7e15771 assets/create/models/threshold_switch/block_ceiling_2.json -c62cbd9fe144326c46702ba4e512c832484ea4e8 assets/create/models/threshold_switch/block_ceiling_3.json -fe1017b4338d3027771d5eb8b4e2444ddb842b36 assets/create/models/threshold_switch/block_ceiling_4.json -d090a659a8df0b86d9892214ac5b06641aaabc9a assets/create/models/threshold_switch/block_ceiling_5.json -dffc869ccce392b1908c833631e3df374c6a3012 assets/create/models/threshold_switch/block_floor_0.json -ab3d51ab5dd8ef6c1cad5d65406180915340dd7e assets/create/models/threshold_switch/block_floor_1.json -7a69fb5a6e77b457c381495c951aa0ba9c7df7f0 assets/create/models/threshold_switch/block_floor_2.json -3a6bbc80eea8d824a981e257f8025997946b3260 assets/create/models/threshold_switch/block_floor_3.json -a76fae0415604615be0e822394e0879ca81bf166 assets/create/models/threshold_switch/block_floor_4.json -28ddae97613f1a06885f06faa20b1b2a5bcaa7db assets/create/models/threshold_switch/block_floor_5.json -ab50d142c25c95b0865dd41176cc07a0c76109ac assets/create/models/threshold_switch/block_wall_0.json -be730f505bf937db4b3658b2bd3763b514d295c2 assets/create/models/threshold_switch/block_wall_1.json -f7f6d92ab5dea5a85ec3d570cdd169329dd4225f assets/create/models/threshold_switch/block_wall_2.json -41009d15d22c946a2ed4c6ba98447c3c7cc26315 assets/create/models/threshold_switch/block_wall_3.json -ad3204842128db2c7bebdbf3c40fccc45c82de44 assets/create/models/threshold_switch/block_wall_4.json -197a6ed7fd9514de13daf58605c24a7156c00bd1 assets/create/models/threshold_switch/block_wall_5.json 7dbef6df108c395c2481c8183517c9ea568a7d88 data/create/advancements/recipes/building_blocks/acacia_window.json 8005cd18b80bcee4f5a2111ee78f87d117d6fcdf data/create/advancements/recipes/building_blocks/acacia_window_pane.json a2b7fe4d1b1c8d173da0e6dfcf41379648a92a80 data/create/advancements/recipes/building_blocks/andesite_from_stone_types_andesite_stonecutting.json ab03b83587129f06998ec86e9c417e622baff713 data/create/advancements/recipes/building_blocks/andesite_pillar_from_stone_types_andesite_stonecutting.json 676eca0ab460b460ae76c66926ac91da4612a201 data/create/advancements/recipes/building_blocks/asurine_from_stone_types_asurine_stonecutting.json fb36a2f400347c3291978a49e59374f3ac459f14 data/create/advancements/recipes/building_blocks/asurine_pillar_from_stone_types_asurine_stonecutting.json +a41990f2ea73c54ce3af41a3a61c4fdd4134d3b9 data/create/advancements/recipes/building_blocks/bamboo_window.json +b25b8c230fde8d6d77e8d516bed52236652b5ca6 data/create/advancements/recipes/building_blocks/bamboo_window_pane.json 7a7eb78c70e1591d339115b367cd3114fb7c1799 data/create/advancements/recipes/building_blocks/birch_window.json 6df6a6885c3ebf92f98f105be16d8e0c80da19f0 data/create/advancements/recipes/building_blocks/birch_window_pane.json 0d724aefa51b969dbadb59b1193172a44ecf5644 data/create/advancements/recipes/building_blocks/calcite_from_stone_types_calcite_stonecutting.json 537fe5dffa659e5838379587fbd84f2f641551ea data/create/advancements/recipes/building_blocks/calcite_pillar_from_stone_types_calcite_stonecutting.json +2636ac059b6412a46402cccbe5abe4fb49143662 data/create/advancements/recipes/building_blocks/cherry_window.json +3e08f575543f1e0abea979dbaee643572734788b data/create/advancements/recipes/building_blocks/cherry_window_pane.json 55214a0fd27318b17163cace66c7525785127ef8 data/create/advancements/recipes/building_blocks/copper_shingle_slab.json fb4210dbbfb74459e10da94a540f3bfdf91c4a8d data/create/advancements/recipes/building_blocks/copper_shingle_slab_from_copper_shingles_stonecutting.json 31b04ac1b117fb65f5129c5bbb48e42c1c4c1003 data/create/advancements/recipes/building_blocks/copper_shingle_stairs.json @@ -2383,6 +2647,70 @@ fc6babcc211f6ed7f231ed8da12f42f0ab858f4f data/create/advancements/recipes/buildi 8ef5d43ae4344f548efb55793ecc889cc011c0a1 data/create/advancements/recipes/building_blocks/crafting/kinetics/white_seat_from_other_seat.json 415435d450d42d97335416c6faa12538dc8e0fb6 data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat.json e71219bcfe8c712fc7e7368c2933533b3c5ef121 data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat_from_other_seat.json +2171371d683e03c5d6b5b7e89be6c674804adab7 data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox.json +f62a87aaa90fd82730c7bc0b2f6fcecfbdaa8042 data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox_from_other_postbox.json +f598f4689e6e02c7e4325085ee3bb9f43a96377e data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth.json +123399acf7acf989d92735600d74c14ef5849ffc data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth_from_other_table_cloth.json +f2dda3b77262a1d14ab3bc39fbe0bc10a519b947 data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox.json +8997db26c93945f3ef6deb87b51c12e2f28789b9 data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox_from_other_postbox.json +06207bb81c2ee103d79dc8b8f9d38119b6b6bf55 data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth.json +5383fc14b57fb591ebfee9962a774c354f5e99f4 data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth_from_other_table_cloth.json +29f34e0859d0ff8476dcd23d3076d0ed27656a06 data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox.json +6fafc9beff44de0c4f0636dd2f24580b5a357621 data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox_from_other_postbox.json +5237f007a87e119f9083234f825ac757b9fd7883 data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth.json +366e5c9fdcd9cf9d1189eed5074b3e7cb1759970 data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth_from_other_table_cloth.json +35afab0036df98cc60d4e728492694a416c75309 data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox.json +661c1356fe0c8a13c11c6026cc2526e10dcd039f data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox_from_other_postbox.json +607e923aeb6ce8b346f4da35ed67a17c69df570f data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth.json +ec07ec408fb4beb8189f827d8c5b53007944c693 data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json +958fab294f6a55a9ae18b21196600d7764de095a data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox.json +93d63182b51e66a76dbea7f2f27ac0ada953cfa8 data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox_from_other_postbox.json +da207311c49105b9bb3cb7cf53ebdb8d0121f1a1 data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth.json +6102c4f5d72c16b2b2e6aedd53c91c9a00585620 data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth_from_other_table_cloth.json +e23b3d1e71a5b81093f6e71ad3ae1fa60923ad86 data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox.json +0be2943dfe2c6a98092dd44cbe2437b9c142f81a data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox_from_other_postbox.json +7c091e9a30e29cdb934c0bdb9c04b57f0a9a369a data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth.json +7c5cbfaccf7d14241c97c04fe5baf7f6031cc620 data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth_from_other_table_cloth.json +8f4bc79097e67045ec7b7394d47f845809f9851f data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox.json +1a4b12a60b3b971fd7222a90425908b33fa7985d data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox_from_other_postbox.json +166ee7c019768be4b9494608d13a7265e1e97a80 data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth.json +64189712c7c89ddb53860e4ecbbb1cfe84173e90 data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json +12b80ed2b31d3b65a831463538fc8d7788d9a77a data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox.json +bd0ebfb2379f37aeb3c03d39a6d8aa005ef3d4cf data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox_from_other_postbox.json +e1ce7076edd98e38e8d749c046ed6d289dae204e data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth.json +70e7e4df0f8b00490ac85cc7c38e501baf799d88 data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json +39182b8805ecd20842cd9d94825f5504d0bd8a0a data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox.json +d7ddb4841e306859b471be6c32f91d4bd471eae6 data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox_from_other_postbox.json +96f70bf632c5ec0dcead6ea9b03967a92321c767 data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth.json +e0192fb9ef0422d25deaa1801228357f135097cc data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth_from_other_table_cloth.json +e6b6ba626266d2ea84cce1a389df27cd44eeb15b data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox.json +7da22d10a137d0e1a953c2cb6b0c15f64cf4f453 data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox_from_other_postbox.json +416ef49b1c7cd1738c7329901dacad1688febae6 data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth.json +fc94c20112d6a0a8c85dd63dc6b036d7a8d6c9d4 data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json +13b2e283564460e095069fb9723a6d4cdcee6931 data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox.json +1f38371e0896d74abeb6616dde615345d57e3f1d data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox_from_other_postbox.json +1c49627c32669b053945c1dc6b99868e03224a05 data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth.json +0b302e3ab914de973e1a836b7babb0bfb89b8e79 data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth_from_other_table_cloth.json +f7ec699ff45bba54777c0b824a30b5e9a72e093a data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox.json +8e1188506d566763fddf96d5452aae6c409504e9 data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox_from_other_postbox.json +fa809c6e9eb3f7ff752976516ad57fa06cc2df6f data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth.json +dde27c90e1a922b75ac35939d44ce4a3c2557371 data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth_from_other_table_cloth.json +b99839abaeec938e903068ade927913e752df6ae data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox.json +5ff2cf3a429f02f067ee0cfe5317937e69b816fd data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox_from_other_postbox.json +9ba73de4e8069ecaf76b87b1746751264e8924b4 data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth.json +8d27b828d4a39ccae7fb77ffd5774458850cb7ef data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth_from_other_table_cloth.json +a9f13b04c89f2511b4ad83a14d6a1c64c16da745 data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox.json +6cb3089269221dc534c514bbcc1377a5199a273f data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox_from_other_postbox.json +675b04c5050796702e0fa970bc5f4a4153d12be2 data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth.json +489e033281e72dd1dee6a16bdee524f58a7b6679 data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth_from_other_table_cloth.json +ab72539b2ebe8cc2874a62dc32463421c9c685d1 data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox.json +b4bd005477650d6f6b5bbc244e5b25f8ad9f5f14 data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox_from_other_postbox.json +84040091909e565b1390576e3ed58cdc9735f24e data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth.json +113d0c96d61d27e419ef414550667379e37c5bf6 data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth_from_other_table_cloth.json +7d2c65210628be4a3d0c09dbf1e6fbbe868a9e56 data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox.json +9c2e00b2ac4f81f0cac0d9be6b06a0d077a23310 data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox_from_other_postbox.json +f116a1d549313a99135282a2a13262aada1a1dee data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth.json +2d0f3dc8fb9620ef3085ebbb932c7f0705ed893d data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json f3188b24f8108be4219016689a4768f826b4fef3 data/create/advancements/recipes/building_blocks/crimsite_from_stone_types_crimsite_stonecutting.json e88373b83226d860b0c2131213f5d3b09f31ab96 data/create/advancements/recipes/building_blocks/crimsite_pillar_from_stone_types_crimsite_stonecutting.json 09f7122cf360fd56bde2b1659bbed526f9a119c4 data/create/advancements/recipes/building_blocks/crimson_window.json @@ -2629,11 +2957,15 @@ cd77e32d1f6d546be68bbab084fc1864af0529a8 data/create/advancements/recipes/buildi ab4ad143375e65a867b3ca8a7b14df79e9b0b03a data/create/advancements/recipes/building_blocks/exposed_copper_tile_stairs_from_exposed_copper_tiles_stonecutting.json 59b1eb7e50c23127e63a320b70e788afaea48d70 data/create/advancements/recipes/building_blocks/framed_glass_from_glass_colorless_stonecutting.json 3e0772de79f2ddaf277394e989f88cfe066bc64d data/create/advancements/recipes/building_blocks/framed_glass_pane.json +1ca579c0734326348f6d87621b554eeb6e13fa3f data/create/advancements/recipes/building_blocks/framed_glass_pane_from_glass_panes_colorless_stonecutting.json ec5cd5091b3b8c633c02b7751ffacda743c2aeda data/create/advancements/recipes/building_blocks/granite_from_stone_types_granite_stonecutting.json e3c5bd9bf6f73620ccb61e0a9cb3beb18b04b527 data/create/advancements/recipes/building_blocks/granite_pillar_from_stone_types_granite_stonecutting.json 85fb8fdb3cebaaacf24794aec90e7894f66a8402 data/create/advancements/recipes/building_blocks/horizontal_framed_glass_from_glass_colorless_stonecutting.json c609b408d6467ec71513ecca19a6040ad7011a79 data/create/advancements/recipes/building_blocks/horizontal_framed_glass_pane.json +d5846d9cf30dc1312e74d040741e3430dbc46764 data/create/advancements/recipes/building_blocks/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json a587d84e187d6552473f646461539dc56d4e748f data/create/advancements/recipes/building_blocks/industrial_iron_block_from_ingots_iron_stonecutting.json +d6c892f6f3ae052b2f65d5e5a0cdcc7c60da13db data/create/advancements/recipes/building_blocks/industrial_iron_window.json +a26261da3faa6b49a3d2c6b4f7ccc504681f73f8 data/create/advancements/recipes/building_blocks/industrial_iron_window_pane.json 546af6a639e4799fb83d61b131ab0cc38ef6b33a data/create/advancements/recipes/building_blocks/jungle_window.json e8c728c46cc69cc0e9d755551bb9a52f2b61a6c0 data/create/advancements/recipes/building_blocks/jungle_window_pane.json b9d04c53fdf3ba977216021ca71aa5e4f2d9a0b0 data/create/advancements/recipes/building_blocks/layered_andesite_from_stone_types_andesite_stonecutting.json @@ -2903,12 +3235,14 @@ ee4012cc014539be113ace8f80e51c85d2daead9 data/create/advancements/recipes/buildi dfea65f25ebcbe0caf2694dec3d3ea616e2e9291 data/create/advancements/recipes/building_blocks/spruce_window_pane.json 763b3b49296a284f41cbccdc7f1ffb13c89d42db data/create/advancements/recipes/building_blocks/tiled_glass_from_glass_colorless_stonecutting.json 6bf6ced432a4aae040b872d19850cd8d3bd1ec35 data/create/advancements/recipes/building_blocks/tiled_glass_pane.json +d412f1ced43c0bd3eca68a43c738f5bab1b98d9e data/create/advancements/recipes/building_blocks/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json 488ca8e983ed16a45d68ec40b90f656e137da203 data/create/advancements/recipes/building_blocks/tuff_from_stone_types_tuff_stonecutting.json 7569d0b68b77da383fccf0f6fd2d060b8cc3e0be data/create/advancements/recipes/building_blocks/tuff_pillar_from_stone_types_tuff_stonecutting.json f570839b1b1d7a2798e51e9139636eafcf28562d data/create/advancements/recipes/building_blocks/veridium_from_stone_types_veridium_stonecutting.json f4afa2d48fa4688a6ce2b5db92fc98ee68c14907 data/create/advancements/recipes/building_blocks/veridium_pillar_from_stone_types_veridium_stonecutting.json 1762e6aa720d05bf08025a05f437e61debca7b25 data/create/advancements/recipes/building_blocks/vertical_framed_glass_from_glass_colorless_stonecutting.json 47cf1a182885e51a5ce5289150c5883142d4ad3f data/create/advancements/recipes/building_blocks/vertical_framed_glass_pane.json +b17225d2a6b1c54166c573c21b952ffd6946f115 data/create/advancements/recipes/building_blocks/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json 6910b181d623de7b208d0c162fb14d0e21d71105 data/create/advancements/recipes/building_blocks/warped_window.json 658379f08f166bca27c8b2332c71bc36386e49ee data/create/advancements/recipes/building_blocks/warped_window_pane.json 8fc55eaf2b17cf47e302de9c72e494d0c37f6ab7 data/create/advancements/recipes/building_blocks/weathered_copper_shingle_slab.json @@ -2919,15 +3253,21 @@ a9e35aaf621cdb2648f4b9e9beacc91092e8d3b3 data/create/advancements/recipes/buildi 7eeaf1b7cf0a788d4b9a61274cf4752ba1fe57cb data/create/advancements/recipes/building_blocks/weathered_copper_tile_slab_from_weathered_copper_tiles_stonecutting.json 86e0a3eb797ecdfd1626ce84f26e25c503a68587 data/create/advancements/recipes/building_blocks/weathered_copper_tile_stairs.json f093326ca1f341bede9f7cbefecadf7d73d3f9d7 data/create/advancements/recipes/building_blocks/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json +c1b0ce558aad75210d8b95c982dbe063982fe567 data/create/advancements/recipes/building_blocks/weathered_iron_block_from_ingots_iron_stonecutting.json +587dd224181b7008f65ebf3b198bb23475cdec47 data/create/advancements/recipes/building_blocks/weathered_iron_window.json +0847f40c57682514297b0dbf520fd88728507bd1 data/create/advancements/recipes/building_blocks/weathered_iron_window_pane.json 39c93330e07e58d79db13d132d7f1a8f33670e9b data/create/advancements/recipes/decorations/andesite_bars_from_andesite_alloy_stonecutting.json 769926b9bb00dea3bf0534c8d828873b13def961 data/create/advancements/recipes/decorations/andesite_ladder_from_andesite_alloy_stonecutting.json 266700212dece6cba8c338a1e0a8507bb41f92e6 data/create/advancements/recipes/decorations/andesite_scaffolding_from_andesite_alloy_stonecutting.json +f6513fa4fdf26848b2f9ce9bd015377a2583c439 data/create/advancements/recipes/decorations/andesite_table_cloth_from_andesite_alloy_stonecutting.json 07ad89608ed200f4c8051a398f5da9d29769c39f data/create/advancements/recipes/decorations/brass_bars_from_ingots_brass_stonecutting.json d11ca4dc890089326eede1bd5b7a32a97cc91886 data/create/advancements/recipes/decorations/brass_ladder_from_ingots_brass_stonecutting.json cbeb1685b639f0b0b2a637374ff548251c0a932e data/create/advancements/recipes/decorations/brass_scaffolding_from_ingots_brass_stonecutting.json +b3c785f2f494ab60bbe295eafecf9292379a5ff2 data/create/advancements/recipes/decorations/brass_table_cloth_from_ingots_brass_stonecutting.json 2ed97c748d8fe0c9fd060b53a4095a37a10ce67f data/create/advancements/recipes/decorations/copper_bars_from_ingots_copper_stonecutting.json e55c465683e664a0205b62d2e132afeb89ee4dce data/create/advancements/recipes/decorations/copper_ladder_from_ingots_copper_stonecutting.json d3a0524f9fce7293f8c3adbd757c5d5afe74af27 data/create/advancements/recipes/decorations/copper_scaffolding_from_ingots_copper_stonecutting.json +1762dee3f3c416d8867d90e3ce9b68c3c5fe650f data/create/advancements/recipes/decorations/copper_table_cloth_from_ingots_copper_stonecutting.json 34ae39bca445f80d431b3e329de3c1bf847a8eef data/create/advancements/recipes/misc/crafting/kinetics/black_valve_handle_from_other_valve_handle.json e222002ee051e7b72b3658655bb53b5adb825272 data/create/advancements/recipes/misc/crafting/kinetics/blue_valve_handle_from_other_valve_handle.json 472c9e1d515f5f34d97efc334cefe3eb62d860e4 data/create/advancements/recipes/misc/crafting/kinetics/brown_valve_handle_from_other_valve_handle.json @@ -2944,6 +3284,25 @@ c96b1b147139c9d560e9d1e1dd9a726ebb771329 data/create/advancements/recipes/misc/c 004b31d1be78dbc4be60f4fd0879065f1a685518 data/create/advancements/recipes/misc/crafting/kinetics/red_valve_handle_from_other_valve_handle.json cf2920d4d27c40fe71dd8954225e7f2a38ba2a4f data/create/advancements/recipes/misc/crafting/kinetics/white_valve_handle_from_other_valve_handle.json 54bf51dcbdd86635e68d366cb4130f65b9c0fe4a data/create/advancements/recipes/misc/crafting/kinetics/yellow_valve_handle_from_other_valve_handle.json +b60b14d473fc8a841be668e98303f07779916637 data/create/advancements/recipes/misc/crafting/logistics/andesite_table_cloth_clear.json +5e50ee44a3316eb23bbd8f0164c17d5719ab707c data/create/advancements/recipes/misc/crafting/logistics/black_table_cloth_clear.json +b6ce89f748f35694cf2fd4c79693b3a8f3dba864 data/create/advancements/recipes/misc/crafting/logistics/blue_table_cloth_clear.json +2aeabffefd6e7a963e61288b632961783ce9ab69 data/create/advancements/recipes/misc/crafting/logistics/brass_table_cloth_clear.json +a8a4ef79d02e1903464fff524bcbb63b424681ea data/create/advancements/recipes/misc/crafting/logistics/brown_table_cloth_clear.json +a613cb47dd2a7cf5cf2f7b6bd8031f59e6bc554a data/create/advancements/recipes/misc/crafting/logistics/copper_table_cloth_clear.json +e44912e563d11cb42bf45ab668e81c66845725d1 data/create/advancements/recipes/misc/crafting/logistics/cyan_table_cloth_clear.json +13b4e81dcaa87e9862180f10b239de43bf1d1dc8 data/create/advancements/recipes/misc/crafting/logistics/gray_table_cloth_clear.json +df90265b1aba8f4c49564dce7e04609cf65ddba5 data/create/advancements/recipes/misc/crafting/logistics/green_table_cloth_clear.json +05c7735e280b2be640084fecc3724c41544805fd data/create/advancements/recipes/misc/crafting/logistics/light_blue_table_cloth_clear.json +5ee045df398bb091467f5b18df7d8b322ed43c23 data/create/advancements/recipes/misc/crafting/logistics/light_gray_table_cloth_clear.json +ad99b5d2213c5a9d00f4719e4aaaca4215e8191b data/create/advancements/recipes/misc/crafting/logistics/lime_table_cloth_clear.json +97ca5d009fb727f770d3c3d74756eeb571f084b7 data/create/advancements/recipes/misc/crafting/logistics/magenta_table_cloth_clear.json +33cbf02d26d008cd7b261d729aed1e5fcce0cb6e data/create/advancements/recipes/misc/crafting/logistics/orange_table_cloth_clear.json +e23d1bf1143d08074df53d9a07ea0c5304f63271 data/create/advancements/recipes/misc/crafting/logistics/pink_table_cloth_clear.json +b9be0a58a604965048084487294b4c1b9ce0f745 data/create/advancements/recipes/misc/crafting/logistics/purple_table_cloth_clear.json +0d8c16e085d8f869237fdfb428d29ece096a3291 data/create/advancements/recipes/misc/crafting/logistics/red_table_cloth_clear.json +c1768fde21268bb1b035c63b5e9fba81526de83c data/create/advancements/recipes/misc/crafting/logistics/white_table_cloth_clear.json +ccb8f3871eb044360b597ff02ea78896050c3760 data/create/advancements/recipes/misc/crafting/logistics/yellow_table_cloth_clear.json 706a4da01ddbd9c3db4d3183ffdcd602a558a5cd data/create/loot_tables/blocks/acacia_window.json a7b37cec417ec9f9095e2ae11c990e4906d6af0e data/create/loot_tables/blocks/acacia_window_pane.json 5eee4b2702e432e03b1f46c6f1573ceee67b131f data/create/loot_tables/blocks/adjustable_chain_gearshift.json @@ -2960,24 +3319,32 @@ ac6b9e99a900f203f69c5127cc44c0de48b0d946 data/create/loot_tables/blocks/andesite 1d9b959e0a6b965fef70136c2988e37c94f58b9e data/create/loot_tables/blocks/andesite_ladder.json 93e40b5e41c32af364a4636989a72ef7901e6bd6 data/create/loot_tables/blocks/andesite_pillar.json 191c341be37299e8ab0d692eb3a185188157ebdf data/create/loot_tables/blocks/andesite_scaffolding.json +d3a343785cc9e9ac0e9d2309ef4203121c9ab385 data/create/loot_tables/blocks/andesite_table_cloth.json 1c6f1dd9ec49b7db86e43706e940208b51e0f6d5 data/create/loot_tables/blocks/andesite_tunnel.json d408536459078c1d72770b7431137d7d8d8ff3bb data/create/loot_tables/blocks/asurine.json 3129cb3d97d657bf16ea5973b3bde1e31ff054c7 data/create/loot_tables/blocks/asurine_pillar.json +858038cff810f9b47e37e5c80064370573d73255 data/create/loot_tables/blocks/bamboo_window.json +76843e927185385fbdfe403577eb4a85a60e25bd data/create/loot_tables/blocks/bamboo_window_pane.json 8ac6f7a29c32e636b0639ac2caaa60882617f675 data/create/loot_tables/blocks/basin.json d964b7a8f6a4ce28ce640d31a01e77eafcc181e5 data/create/loot_tables/blocks/belt.json a268eb02c10015a901a6543595b2b815a8026d78 data/create/loot_tables/blocks/birch_window.json 43d16eae230de501c528f4e9af666f72a081ed29 data/create/loot_tables/blocks/birch_window_pane.json 4aec2374e76dfa5535fe22b1fc02b4b2d453217d data/create/loot_tables/blocks/black_nixie_tube.json +6ed685605e24af5c6ff5d797dde8492069427b76 data/create/loot_tables/blocks/black_postbox.json 7ce6dd2c0d02eb1b56ec441044dfc608ea6bcb41 data/create/loot_tables/blocks/black_sail.json 2449b8c173fbbc2a96e0b8d1996d72fb60527e64 data/create/loot_tables/blocks/black_seat.json +2ac4a51540f596ddb81f9fa1b72bcc02c3a6b1fd data/create/loot_tables/blocks/black_table_cloth.json 2d33e25b2741f634bbd6cd77b31c17dd94511d94 data/create/loot_tables/blocks/black_toolbox.json f911ac185cd48afa2393d24f28a688936a9fa147 data/create/loot_tables/blocks/black_valve_handle.json eee41c02c8cfcdb56f31e74fc266783b785bea9d data/create/loot_tables/blocks/blaze_burner.json 247d12823eed3b9248003aca8e3ead87972ac61e data/create/loot_tables/blocks/blue_nixie_tube.json +76217732c9bddf77b7de735b4380d9f92adca9b3 data/create/loot_tables/blocks/blue_postbox.json bb9d906a97810ed1461ed321ef8e4bee1dd104fb data/create/loot_tables/blocks/blue_sail.json 833fe6bc3020055dd0d6f46b324cbe27b248708d data/create/loot_tables/blocks/blue_seat.json +2b7aa6506e02be7a7b76228bc16bf05d0920195e data/create/loot_tables/blocks/blue_table_cloth.json 9d22716d9d846dc9587e327dfcdf18dd5955f826 data/create/loot_tables/blocks/blue_toolbox.json 6d7ecb10e21b1e12c83c71736f14cbba3ccd7aaf data/create/loot_tables/blocks/blue_valve_handle.json +53e01f63aa47aa00575240ccdf867b4d6c392385 data/create/loot_tables/blocks/bound_cardboard_block.json 7d8b199f381003e5a74a8144976b65c93a09dbcb data/create/loot_tables/blocks/brass_bars.json 64a5869c6b3edeca06771f8ef64ef9521d83302a data/create/loot_tables/blocks/brass_belt_funnel.json 78ecee2c9baf6b0c78f6c7aa692e102a3f4dda74 data/create/loot_tables/blocks/brass_block.json @@ -2989,14 +3356,21 @@ e466a397f84957616f7e83954db2050355f052c9 data/create/loot_tables/blocks/brass_en 7b79b14f64108cd8a734f95dd8c721830b48ac82 data/create/loot_tables/blocks/brass_funnel.json 8d58d4c771843950a14fd7b800a05736c1fc88d9 data/create/loot_tables/blocks/brass_ladder.json 429d524c9848b44d19028126f0efd678e0c4b680 data/create/loot_tables/blocks/brass_scaffolding.json +ce1aa8d4b40ba0d0898c552811f1a6f7e94879a5 data/create/loot_tables/blocks/brass_table_cloth.json af90102bfe0e3a14bf1330cddec553f27b8fba89 data/create/loot_tables/blocks/brass_tunnel.json d391cff5b741fd6ddf5b6fa64e05526eb3a9f0d9 data/create/loot_tables/blocks/brown_nixie_tube.json +bfa0365507a888134c20b36af4bd7944263687f0 data/create/loot_tables/blocks/brown_postbox.json 862bd3ceed05ea45c03911bb8403817b73c4bc38 data/create/loot_tables/blocks/brown_sail.json 6ddbdd489120be56f50272c86ecdb886afa3a8e4 data/create/loot_tables/blocks/brown_seat.json +0aa66846a1b29feda9c63b9364860c4c75eaf2e4 data/create/loot_tables/blocks/brown_table_cloth.json 588ae3d0da73eed3bc30cb28c583e7f8312d15bd data/create/loot_tables/blocks/brown_toolbox.json 7c7cf4c30786f6e0a699e2b3f9120343e53107f4 data/create/loot_tables/blocks/brown_valve_handle.json 06d1c478e4236210aa12b5911691868fef33bb5f data/create/loot_tables/blocks/calcite_pillar.json +3d65461b1fc2667f446aefa2853621c06068bb38 data/create/loot_tables/blocks/cardboard_block.json 515c839deea520b07b03f7ba65c4a7b22fdf5ba3 data/create/loot_tables/blocks/cart_assembler.json +aadd8aa7f8433896bd4fea56f43e496cbc5be25a data/create/loot_tables/blocks/chain_conveyor.json +5c79f6384b77fc0d817a17f65f3cdfef34a7a039 data/create/loot_tables/blocks/cherry_window.json +d2e962b8cfc208d0c8af5f4b79311b9df14b1738 data/create/loot_tables/blocks/cherry_window_pane.json fb4877d45df15be1a74378ab28f23fbf9d0657ef data/create/loot_tables/blocks/chute.json ace9255cbdd1af5e5068916d2a6bed2f861f81f1 data/create/loot_tables/blocks/clipboard.json bfd871acdde6c239098ead188a5aad7636d11bc0 data/create/loot_tables/blocks/clockwork_bearing.json @@ -3015,6 +3389,7 @@ ac621731ca23e6fbb1003be59edacdf837dbc37e data/create/loot_tables/blocks/copper_s be31f0c68bfe80dff88959bd30ef9a9080dd3b3b data/create/loot_tables/blocks/copper_shingle_slab.json 83ae2652a2df217730d6fb34a65c3962e82a961d data/create/loot_tables/blocks/copper_shingle_stairs.json 9be387731859ccc3aec7701c1804ddc3c5dde216 data/create/loot_tables/blocks/copper_shingles.json +f6a29868a011d9ad73bc29be94ec2a07a2626323 data/create/loot_tables/blocks/copper_table_cloth.json adbe83d6bf88dd7d2b0b8788bb619cedd37f59d9 data/create/loot_tables/blocks/copper_tile_slab.json 1e06f16b1fa8e78af5cbfc90ba8ff1136de83d2d data/create/loot_tables/blocks/copper_tile_stairs.json 9cb359c96543d7421250c4ef4e83a5e170974efb data/create/loot_tables/blocks/copper_tiles.json @@ -3145,8 +3520,10 @@ d9552e3e9f4de0e09df8ca9446066e94c6e2c681 data/create/loot_tables/blocks/cut_veri 4845f7127921c7dd93a59118e63c37107d6c2061 data/create/loot_tables/blocks/cut_veridium_stairs.json b56caea031d637321eddfd5d122fc357d2c2e49c data/create/loot_tables/blocks/cut_veridium_wall.json ffb440a03f5e513b8d20c2725a95dc5c9b84c73b data/create/loot_tables/blocks/cyan_nixie_tube.json +914146303ae7e73c4f9283ea61cd5443f49f5cde data/create/loot_tables/blocks/cyan_postbox.json 8858b4e1b4e51889b2006005585a17e4978ed8e9 data/create/loot_tables/blocks/cyan_sail.json 8dccecb2c87d7421efdfb3fb97ae62b79f0b4411 data/create/loot_tables/blocks/cyan_seat.json +30bfeac6b7766ff1985ce9953f0dd6824f177aef data/create/loot_tables/blocks/cyan_table_cloth.json 66ea2f2cc32d49bb434f83cbd07736d6fbacacf3 data/create/loot_tables/blocks/cyan_toolbox.json 8c7fd26e7bd03916014274e005d69ab8f14df973 data/create/loot_tables/blocks/cyan_valve_handle.json 704a10ef59d052e92b7035406422231b9bb2372f data/create/loot_tables/blocks/dark_oak_window.json @@ -3155,6 +3532,7 @@ ccb3ab3c0d9c8fad236ccc790c2f7a1524202e9a data/create/loot_tables/blocks/dark_oak 3c3d83fc964462e2401ec6dac5200709d5ce1957 data/create/loot_tables/blocks/deepslate_zinc_ore.json 8c1d8d9680834419b9049bc11137316b75f59f46 data/create/loot_tables/blocks/deployer.json 9ded269b860ed96c964f6f8960a680a5c87fa033 data/create/loot_tables/blocks/depot.json +eec1b262b34fc05a95bbb3762cf96a050030d010 data/create/loot_tables/blocks/desk_bell.json 98987901bdb35efe2922b420def9cdb116ec5416 data/create/loot_tables/blocks/diorite_pillar.json 6dda1fa6622ce351af2e0aeec2b5c2e4183fb593 data/create/loot_tables/blocks/display_board.json 5320ddec6855d99e5685bb424d02165eca480805 data/create/loot_tables/blocks/display_link.json @@ -3171,6 +3549,7 @@ d2c9abd9260eb82ea1c2eeae5e2d6abd0b4d3ce8 data/create/loot_tables/blocks/exposed_ 6841c02935838f00011d33fc392965326c4dbc5b data/create/loot_tables/blocks/exposed_copper_tile_slab.json 432a047156b93a09b7e027fc34f5680a8f68dc92 data/create/loot_tables/blocks/exposed_copper_tile_stairs.json f0905ae4c9bdff8fe9e1ab4682a7b1efe2d27d9d data/create/loot_tables/blocks/exposed_copper_tiles.json +4dd285b35d9b94d48f7aa783e93bdd04d58c4a26 data/create/loot_tables/blocks/factory_gauge.json 3fae2a7a3f133a1d7c76ce91f6c48eab787d6ff6 data/create/loot_tables/blocks/fake_track.json 1d4734d6d9ba039c0dfa2271f08cdb55e35b721f data/create/loot_tables/blocks/fluid_pipe.json 9c112883a3763b2d286d9a5a0980dcea82bcc9e6 data/create/loot_tables/blocks/fluid_tank.json @@ -3187,13 +3566,17 @@ a4c86e5456bbbcc417d736151ac6a15c944d555b data/create/loot_tables/blocks/gearshif ffa2776989447e44fa10673986961ab395ebd592 data/create/loot_tables/blocks/glass_fluid_pipe.json 07d8265c285ebb69b9160d516905ae1f17acc87d data/create/loot_tables/blocks/granite_pillar.json 41feb0f235495384ebca5b6f70d01b6f0c0c8878 data/create/loot_tables/blocks/gray_nixie_tube.json +6f123d5e6612274223ddb695e582abd952d3521c data/create/loot_tables/blocks/gray_postbox.json bd526fc4f0acea571c37b2ecbb7267fee6be29f0 data/create/loot_tables/blocks/gray_sail.json 5e23e2032f92737eaa6e6cfb4c62232566f06e77 data/create/loot_tables/blocks/gray_seat.json +d60c2dfc073632b8488e13190b15436173c9caa4 data/create/loot_tables/blocks/gray_table_cloth.json 6ff8b3e59ea98697b87e71eb64d1e6f7e4631f36 data/create/loot_tables/blocks/gray_toolbox.json aa0d47422e0adc3fb18e5c0eefd25c417ddbf9ae data/create/loot_tables/blocks/gray_valve_handle.json 4cfbe1bdc89916f78f891b9dbaed461cd838584b data/create/loot_tables/blocks/green_nixie_tube.json +e99e3895a19faa928e40fa17fbfbda6d3566b1ed data/create/loot_tables/blocks/green_postbox.json 6c22cf8de05828af7979dc32d9e151297d551fe5 data/create/loot_tables/blocks/green_sail.json fbd61c331d4fda692f0e7174aed5aed3652d3553 data/create/loot_tables/blocks/green_seat.json +b918c78d0c8dabd9a6962e4c441096a12f4f47d1 data/create/loot_tables/blocks/green_table_cloth.json 703a285a5d47fcc13e6775040d45620db2ef5480 data/create/loot_tables/blocks/green_toolbox.json 17cbfa7c5627a2ac92826e349d09509f4722fdef data/create/loot_tables/blocks/green_valve_handle.json 8dfbcb358f008317a0515ca35f3976470ca7c4e9 data/create/loot_tables/blocks/hand_crank.json @@ -3202,7 +3585,10 @@ f917ddc34b196750efbab88ee5565ecd0e38e0e6 data/create/loot_tables/blocks/haunted_ a206598562bcbc9e3bc10dbe12fb22974ee58fcc data/create/loot_tables/blocks/horizontal_framed_glass_pane.json e65fae1b9b72cf2208696463fa20a82a4d64fb62 data/create/loot_tables/blocks/hose_pulley.json 34c239150baa92e03ca89430148560e1b7a1f02d data/create/loot_tables/blocks/industrial_iron_block.json +9c831bbcae1bf3dbddce1126a1279f4f22902a25 data/create/loot_tables/blocks/industrial_iron_window.json +de30f216e9326c27103702ea296c460d927aa3ef data/create/loot_tables/blocks/industrial_iron_window_pane.json c22dea1941471be65c811cdc2ce7b77d2247e9e1 data/create/loot_tables/blocks/item_drain.json +528078b0cf042236d2cb0701fb55f41f54aa932b data/create/loot_tables/blocks/item_hatch.json 72b5a7288f7f54694df5f456e4ab4433bd38dfff data/create/loot_tables/blocks/item_vault.json 13bd1033991eb65354a9b9406fe638c357fea409 data/create/loot_tables/blocks/jungle_window.json fe9c2629eb30393d2ae5a1f252b9732506ef9bef data/create/loot_tables/blocks/jungle_window_pane.json @@ -3225,18 +3611,24 @@ b4882fe056a8d03bddf7a8c4fa70ee06548e1743 data/create/loot_tables/blocks/layered_ 7f9ea6bfcf8344018866013e12d23edf21f034e9 data/create/loot_tables/blocks/layered_veridium.json 54a876a52655d5c9c33325a7d07c7978d33adca6 data/create/loot_tables/blocks/lectern_controller.json 8a6153a0b5857c77cdac0cffcb22e30ae6181f3a data/create/loot_tables/blocks/light_blue_nixie_tube.json +27bbda185ab99cff4974e6bfc40b72265896ef42 data/create/loot_tables/blocks/light_blue_postbox.json 304072298d4078eca7e0fb8c58ea3144afe246a8 data/create/loot_tables/blocks/light_blue_sail.json a1396be526ef27c6d0f97cdd0f0e61f810e7353b data/create/loot_tables/blocks/light_blue_seat.json +b281c6ff8b383f27bba02e11819ddab13c80a473 data/create/loot_tables/blocks/light_blue_table_cloth.json 0cd56baf9f3c9edb97e4ce892d374e21a099374f data/create/loot_tables/blocks/light_blue_toolbox.json bf4e6c308d82f15689406b5b3e88fe95d49a9a44 data/create/loot_tables/blocks/light_blue_valve_handle.json 6928acbfcafdfead9750be6760da163b86532054 data/create/loot_tables/blocks/light_gray_nixie_tube.json +eb95d1e0abb93d5efecb0809e3901f37021c4dfc data/create/loot_tables/blocks/light_gray_postbox.json 886ef98e4bd60d8860b56441da6928e24f262d70 data/create/loot_tables/blocks/light_gray_sail.json 1ae0ff25ac9468e67ab1847b87a37829328d4c84 data/create/loot_tables/blocks/light_gray_seat.json +e61e9b3e116037c4ad44a7e222e5127e5767ddad data/create/loot_tables/blocks/light_gray_table_cloth.json e22dfadefcea50090efe87136a4b92e6ef20d379 data/create/loot_tables/blocks/light_gray_toolbox.json 3e586bc1281f15e25e75475dd726578ff032c6ae data/create/loot_tables/blocks/light_gray_valve_handle.json 582bb26f6df37d0c2dbe12983ad05fc74f5fb5c0 data/create/loot_tables/blocks/lime_nixie_tube.json +ec9d973d218b26d51b82f265603feab31170c619 data/create/loot_tables/blocks/lime_postbox.json 623ac65211a9920325308b55285f78e3b7275751 data/create/loot_tables/blocks/lime_sail.json 7efe69664a781b292f491d5ff89e27dd5991f3cf data/create/loot_tables/blocks/lime_seat.json +10ecd65ecba6b66652dd04a385fc47a44c1f8110 data/create/loot_tables/blocks/lime_table_cloth.json 0f6a465501a445925e9aff7a4c84b3c8e2caa93e data/create/loot_tables/blocks/lime_toolbox.json 1a3ed7cd5660d7ea014956ea642e0b07d89bc297 data/create/loot_tables/blocks/lime_valve_handle.json c6bb0877c537dda15469934383dc45c608bfd1a4 data/create/loot_tables/blocks/limestone.json @@ -3244,8 +3636,10 @@ c6bb0877c537dda15469934383dc45c608bfd1a4 data/create/loot_tables/blocks/limeston baf70f9eb579f20b232a2af4e6b00a54f84844e6 data/create/loot_tables/blocks/linear_chassis.json e4c0f8ca822cf7555bd011825b430c3c735160d4 data/create/loot_tables/blocks/lit_blaze_burner.json 6bd8b044cc9c69a5268372e5436f556da2c1bf21 data/create/loot_tables/blocks/magenta_nixie_tube.json +601bc43286b9f6b978ae8681281bf8e195f8211d data/create/loot_tables/blocks/magenta_postbox.json b4d06c9ce7fbec0f23bb6dbc446b77d070f06775 data/create/loot_tables/blocks/magenta_sail.json 300e480d8e43e3a4ca19a92ae1360c02f7c5accd data/create/loot_tables/blocks/magenta_seat.json +64bbc8f91a7b60d86c76e237cb87863f7f7539c9 data/create/loot_tables/blocks/magenta_table_cloth.json 40d2ba0a52eaa2c61900731f0cee2657c5e77c20 data/create/loot_tables/blocks/magenta_toolbox.json 347115d1507997a6f838d222092092ab994db7e5 data/create/loot_tables/blocks/magenta_valve_handle.json 49c68e263386549cc30438d3b3878ec5bbd909cc data/create/loot_tables/blocks/mangrove_window.json @@ -3276,8 +3670,10 @@ fe79cb4cbea87efc84d61d3d31f073bf3c64c73d data/create/loot_tables/blocks/netherit 5dcb11160a51ce17fb06f5fecc14e87d92b1a641 data/create/loot_tables/blocks/oak_window_pane.json 461e9818f41aab34905757a423455cdcee780e67 data/create/loot_tables/blocks/ochrum.json 1259a439286385d5b7c48bff89d0839f1f2e02c2 data/create/loot_tables/blocks/ochrum_pillar.json +3f6940f13ca705bad7cdb9a9b80a3ae84f70f80c data/create/loot_tables/blocks/orange_postbox.json d6323d4b30faa87cd4b5b8b815cb16f78296f203 data/create/loot_tables/blocks/orange_sail.json 119fc4c3055c09c7958ac405925a6b7be2081c6b data/create/loot_tables/blocks/orange_seat.json +24b82ccacdc00d98a660c20384c76927cd8c2948 data/create/loot_tables/blocks/orange_table_cloth.json 54ac8c8166c23f24a8a0870c981ef8ffa64c0b89 data/create/loot_tables/blocks/orange_toolbox.json 30aef2df782b6b35cd16b4c205bb15de85bc0664 data/create/loot_tables/blocks/orange_valve_handle.json f4004c6d16754fc8867ed6618dace8e8f6dcc412 data/create/loot_tables/blocks/ornate_iron_window.json @@ -3288,10 +3684,14 @@ f47a01824093455030fca66e7b8a39bcfc61d219 data/create/loot_tables/blocks/oxidized 4d815b361af81bd0c0e14c853ca54ad3cde66a57 data/create/loot_tables/blocks/oxidized_copper_tile_slab.json d599ef03d1b69e4367ec0dea78f52c1964c99f9b data/create/loot_tables/blocks/oxidized_copper_tile_stairs.json 4d2a2863697664b3b71f02aa703c3504cd5cc826 data/create/loot_tables/blocks/oxidized_copper_tiles.json +54aa9700df601640b705d912abe773d5b6ee2b1f data/create/loot_tables/blocks/package_frogport.json +ab8cee7abd7dd92428bf7d8f0f5edd35082401a4 data/create/loot_tables/blocks/packager.json 58bd9fe9d6706998bfbda3b077cfd0a740972091 data/create/loot_tables/blocks/peculiar_bell.json 4d7724df6fefee4512c4f7886d0e103d1dc39510 data/create/loot_tables/blocks/pink_nixie_tube.json +df7b12349c64d035eb563535b03cb70d780c5a71 data/create/loot_tables/blocks/pink_postbox.json 85811771fbc36f645fdb9f510639715399503c99 data/create/loot_tables/blocks/pink_sail.json 9a5652002131d14c585a6e434a4457ef36d2f60d data/create/loot_tables/blocks/pink_seat.json +23e3176e0511b3910b9dcefa1821af9c9acfa34b data/create/loot_tables/blocks/pink_table_cloth.json 23e28971460b2a3b8b39412a4778672d7ced4af7 data/create/loot_tables/blocks/pink_toolbox.json e234842b7d2334b77d02e383908795f0714b21a2 data/create/loot_tables/blocks/pink_valve_handle.json 175735e4a055945df59fb6206ef1a6ebf8ca3e8f data/create/loot_tables/blocks/piston_extension_pole.json @@ -3360,22 +3760,29 @@ afe84b9468fba532acc447236a9a0cbdd02c4560 data/create/loot_tables/blocks/powered_ fbc433a7e8518860bc828a52b56dba92e4dff66c data/create/loot_tables/blocks/pulley_magnet.json e654e6cedc0373e97caea947e7e605bc4095da88 data/create/loot_tables/blocks/pulse_extender.json 422385f062dd63edaf246c42fb0e617e92e6cc44 data/create/loot_tables/blocks/pulse_repeater.json +93f0c41aedaa2b9baceda78b93a4b3198962e3f9 data/create/loot_tables/blocks/pulse_timer.json 6f453ea136098a5872aeb4e2ad1e5b78d2fd571f data/create/loot_tables/blocks/purple_nixie_tube.json +53e964048baa1b98877a559e8fda6c8f367d5cd6 data/create/loot_tables/blocks/purple_postbox.json c6b7a02db55cf0824a48156adf469c478dfd6a8d data/create/loot_tables/blocks/purple_sail.json 73cd7cc36fafb491666d2bccf1b4f24624b3c8f2 data/create/loot_tables/blocks/purple_seat.json +b4746e296f4bf63778e40a751b4c7fa8be45d21d data/create/loot_tables/blocks/purple_table_cloth.json 147086b9db173aed1b25d9460d0135708dcebcf9 data/create/loot_tables/blocks/purple_toolbox.json 0354f88c3e1d0b6580b9a23d23752dcd9b86fc31 data/create/loot_tables/blocks/purple_valve_handle.json 9e5e841d9f9a00d560ed17a7e197dc56bae334b7 data/create/loot_tables/blocks/radial_chassis.json 73a03fa31e299cec2c8a3dc0f31a8aa354b49bcd data/create/loot_tables/blocks/railway_casing.json f76e5a157d2aeab5708f464b1f3c8e47b3855f18 data/create/loot_tables/blocks/raw_zinc_block.json a50e1c28af16e9f1b4f48aa974461167139768a7 data/create/loot_tables/blocks/red_nixie_tube.json +f36f1e69e4fb8723238f81aadbac892f54b5ac62 data/create/loot_tables/blocks/red_postbox.json 977d724cddf8eba053a3310ad0d30af15199bbed data/create/loot_tables/blocks/red_sail.json 9aedede893e2127a1cdd17695699397d8d5c6ce5 data/create/loot_tables/blocks/red_seat.json +09796bc3be977e17927d0a9e32bff2982618e844 data/create/loot_tables/blocks/red_table_cloth.json 9713071cab536e8c1550a6309dc4563fecc2c4e0 data/create/loot_tables/blocks/red_toolbox.json 17d75711f4ef5d76aa931175364642732fb0c60d data/create/loot_tables/blocks/red_valve_handle.json bbc2d61eeea335f8f011d799ef6a5484ca027640 data/create/loot_tables/blocks/redstone_contact.json 4fa70deeac7e56121e42fb602dfa27ee1727f749 data/create/loot_tables/blocks/redstone_link.json +efc3a5595e4daf67fa43f84c9869dfc76fd6fca4 data/create/loot_tables/blocks/redstone_requester.json 632067fe6309e31e78637eb0272209b630750242 data/create/loot_tables/blocks/refined_radiance_casing.json +ee2c4d66d1264ec613e9e84fcac814d2f5806258 data/create/loot_tables/blocks/repackager.json 354a3b6c73379b7100b0dd12b3f3b008830c4d2d data/create/loot_tables/blocks/rope.json f74fdd78961619d712891c36e0a0778c25e145dc data/create/loot_tables/blocks/rope_pulley.json 77d2da2217689608095866de4af4b41104348354 data/create/loot_tables/blocks/rose_quartz_block.json @@ -3462,6 +3869,8 @@ bcd632c1180efbc990b077314cfce8514a25da7c data/create/loot_tables/blocks/spruce_w cae1bd9100b62841e260880faa80e2442f44a141 data/create/loot_tables/blocks/steam_whistle_extension.json 0bc3fdde351129e3a261a2420aff9d3f063c235e data/create/loot_tables/blocks/sticker.json 074f526902cb5fcff2129614428aba1ea05a6649 data/create/loot_tables/blocks/sticky_mechanical_piston.json +af312881ec9bfb0902438f53c5cac020244bdba2 data/create/loot_tables/blocks/stock_link.json +f4fa9bb255348dc79dcc0468b3beb9ad075eb036 data/create/loot_tables/blocks/stock_ticker.json a7332324e63f7d28621ddfbd54eb3d091461d890 data/create/loot_tables/blocks/stockpile_switch.json b13496b1b4bc0be30605832e23894fb374dd796e data/create/loot_tables/blocks/stressometer.json 6a7df4d2730d57ae6e404b4bc8e01367e5ddbf07 data/create/loot_tables/blocks/tiled_glass.json @@ -3512,17 +3921,24 @@ f309ffd94dfb3591efd2fab337a871a0ceff1084 data/create/loot_tables/blocks/waxed_we d6862dc9f7d291df618fbce71eebf613711a5517 data/create/loot_tables/blocks/weathered_copper_tile_slab.json 57d5065d53016e4b1ef0fbad9b84605b1546bcc4 data/create/loot_tables/blocks/weathered_copper_tile_stairs.json 771d98a6627d707228719e843bc80636b02dc985 data/create/loot_tables/blocks/weathered_copper_tiles.json +013deea9b687ce96e5042de13ab0cba9dadce364 data/create/loot_tables/blocks/weathered_iron_block.json +f0c51ad0a713aab00dff913361b8e5e8448b912a data/create/loot_tables/blocks/weathered_iron_window.json +1d3ea471ec3f2bbf10c7a11f040f8bbf0d1576a8 data/create/loot_tables/blocks/weathered_iron_window_pane.json f6ba0623b4bcea2f3796df4c65c494fc072d2c21 data/create/loot_tables/blocks/weighted_ejector.json 978263272f632ed79a61d52a0080de0b7b8102d6 data/create/loot_tables/blocks/white_nixie_tube.json +3d8a4d4a9634d49b20f65ebcdddaef2d0f21b36b data/create/loot_tables/blocks/white_postbox.json 129c6772c1c12271f9b0d41c77f41ce34fc437b1 data/create/loot_tables/blocks/white_sail.json 84c79bc47b4a74021e91745356bb24fe02402209 data/create/loot_tables/blocks/white_seat.json +cda45c1338e6c9078a107e99c70690fe3e0aa7c2 data/create/loot_tables/blocks/white_table_cloth.json 3c63263c9fb642e34a0a67af4cab2d4348d661c0 data/create/loot_tables/blocks/white_toolbox.json 2fae4331c0ab590aef542cf4e23deea579d734f8 data/create/loot_tables/blocks/white_valve_handle.json bf0ea5c6957a43b6c4b1914df70e0b8f6585e638 data/create/loot_tables/blocks/windmill_bearing.json ed989d41a4b640dc1ffb15c9c0712ee3172d408f data/create/loot_tables/blocks/wooden_bracket.json d9f853e662b004b6ffdbb82af99ad7e774698178 data/create/loot_tables/blocks/yellow_nixie_tube.json +a536699cab16540eb906e0b63a2c5064244c7b6c data/create/loot_tables/blocks/yellow_postbox.json 0ead61521fec15522633d6cfdeb77150bb30d075 data/create/loot_tables/blocks/yellow_sail.json 3ae6d4e380237face57b9187ab8570967226b3b1 data/create/loot_tables/blocks/yellow_seat.json +573457c5bb1a8693f4b877620468703c86051a3a data/create/loot_tables/blocks/yellow_table_cloth.json 11b10beba7a6842ce3d01ea4210bff7d3aa6ab94 data/create/loot_tables/blocks/yellow_toolbox.json b9648ec56e55fe2b9d54adf172405519a46bfa66 data/create/loot_tables/blocks/yellow_valve_handle.json 8be474a69469561dfe759159a40fb135a6ad5de6 data/create/loot_tables/blocks/zinc_block.json @@ -3534,15 +3950,21 @@ b9648ec56e55fe2b9d54adf172405519a46bfa66 data/create/loot_tables/blocks/yellow_v 20bd65d72f1762edf473b2fafc71fcf7d55c01f9 data/create/recipes/andesite_ladder_from_andesite_alloy_stonecutting.json 0b3896151533d220c2d1f3768c6f8e428516ff5b data/create/recipes/andesite_pillar_from_stone_types_andesite_stonecutting.json 367e57a760156a19fc6805a0f23c3f8194cd4255 data/create/recipes/andesite_scaffolding_from_andesite_alloy_stonecutting.json +24e5ad71ab310105a5cb3cf3d0a1fe46b162bd41 data/create/recipes/andesite_table_cloth_from_andesite_alloy_stonecutting.json 5272c61c8c17eb7a528cade93bbc80fd9ef51521 data/create/recipes/asurine_from_stone_types_asurine_stonecutting.json 5bf4b9baf782a461efc36d463b99b9acb0ab4607 data/create/recipes/asurine_pillar_from_stone_types_asurine_stonecutting.json +6e54f07090c60a8163038672bcbf47464219bb9b data/create/recipes/bamboo_window.json +9a243cb03b882d90760ffba791ab78ffe9daade3 data/create/recipes/bamboo_window_pane.json 41f53dd9817c3cc9613c8e97ff8f9ffb895e2b0e data/create/recipes/birch_window.json 998dbc2cc27888a28f009b8e408b7091baac9255 data/create/recipes/birch_window_pane.json 5965f3abe435ac0b3a39d8ec31af71808592642b data/create/recipes/brass_bars_from_ingots_brass_stonecutting.json 4b29884cd866dcda1b93899d81fcd3a2ae4c541b data/create/recipes/brass_ladder_from_ingots_brass_stonecutting.json 9c685014019a7a4f1ef47f235cd1e9b3f9093295 data/create/recipes/brass_scaffolding_from_ingots_brass_stonecutting.json +6f6c35d06c926e7d11e4b3d4e63d867c5546da46 data/create/recipes/brass_table_cloth_from_ingots_brass_stonecutting.json 8f21b67e168a14d354b6c00b5ec795355fdd4209 data/create/recipes/calcite_from_stone_types_calcite_stonecutting.json da3692808565988e21ec5b1d5e976338ccc4a037 data/create/recipes/calcite_pillar_from_stone_types_calcite_stonecutting.json +79bd6c532172149ede8e161f2809362d90f87e7d data/create/recipes/cherry_window.json +22557ebdbe69634968c97e7f348307fdea34d97f data/create/recipes/cherry_window_pane.json 1157b2eab2ada187ea80feae298b77ed7ece4bfd data/create/recipes/copper_bars_from_ingots_copper_stonecutting.json b9d4f55128aa03ee6f6ab1831e709629a42c147e data/create/recipes/copper_ladder_from_ingots_copper_stonecutting.json 922c5ac48c8eb8b3a39f5626a381c2252fbac107 data/create/recipes/copper_scaffolding_from_ingots_copper_stonecutting.json @@ -3551,6 +3973,7 @@ bb083ae1d057dc0106946e4c68f9469b81724396 data/create/recipes/copper_shingle_slab bd4cd7119f8371164b278afc679795a3c2a53406 data/create/recipes/copper_shingle_stairs.json 59f672e8e88d5f4655467e2696616b552debaf46 data/create/recipes/copper_shingle_stairs_from_copper_shingles_stonecutting.json bab9fa969ba95850dc6e3bd0723387a61cbb05cd data/create/recipes/copper_shingles_from_ingots_copper_stonecutting.json +0225fc8d7b7a5027b8a61e6a043c3a8e505d876a data/create/recipes/copper_table_cloth_from_ingots_copper_stonecutting.json f64ba3f3c607b43ea77e5bccb7ec2048e5c6e424 data/create/recipes/copper_tile_slab.json 91b0390e0c772d43eb46b94a0113323f0f6a4387 data/create/recipes/copper_tile_slab_from_copper_tiles_stonecutting.json d31a41f6f7ef0bd20abab06cc31a9d2c56187117 data/create/recipes/copper_tile_stairs.json @@ -3630,6 +4053,89 @@ b04c1cebcfbcf44c4ced04252f54dbfeb8f9ff12 data/create/recipes/crafting/kinetics/w 48c9e3b9f5a8a0f598ab0f57cd8936724337bf1f data/create/recipes/crafting/kinetics/yellow_seat.json 75633a46c374230fab4096a45628b42d6012627d data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json 2be097bb4f1e47a6b3a4a6f0ef222dffe31a1e22 data/create/recipes/crafting/kinetics/yellow_valve_handle_from_other_valve_handle.json +113186f64e29efebd628fe3d88ae69f1ef0537f0 data/create/recipes/crafting/logistics/andesite_table_cloth_clear.json +f4eec2dbb24d5fdd6971f8be965d4c908d8d39ea data/create/recipes/crafting/logistics/black_postbox.json +bf48cc90d8269c3c443007ce224c13fa5a2e741b data/create/recipes/crafting/logistics/black_postbox_from_other_postbox.json +a5dd78419a491f70c12e036769ec8244b561806e data/create/recipes/crafting/logistics/black_table_cloth.json +ab88f259eb1ea6767c97969e205241e91c0fe048 data/create/recipes/crafting/logistics/black_table_cloth_clear.json +b1a32a62d0e90fe01fdad31151dc269a2ed38e3f data/create/recipes/crafting/logistics/black_table_cloth_from_other_table_cloth.json +7e010aa7f5d22ac505bf04ad00ab3c56e0a78f3b data/create/recipes/crafting/logistics/blue_postbox.json +888a8202521f186fb7af27770e708f0fd4bb9659 data/create/recipes/crafting/logistics/blue_postbox_from_other_postbox.json +e48d20a774d0004eda8fc94b4589df42dfbb90ef data/create/recipes/crafting/logistics/blue_table_cloth.json +4002ef4244d7556fc132075d38ceb36e50cf1ed1 data/create/recipes/crafting/logistics/blue_table_cloth_clear.json +f34c1edaf347bb7dc863a00cf18650c0b0ee8dc5 data/create/recipes/crafting/logistics/blue_table_cloth_from_other_table_cloth.json +45a400f1b48d12af82615eba8bec4cdefb738333 data/create/recipes/crafting/logistics/brass_table_cloth_clear.json +c12ad278627aeba957aae502bb1762335918aa20 data/create/recipes/crafting/logistics/brown_postbox.json +9b481ac9d99aeb7d8bf334803628f0f200ca0ade data/create/recipes/crafting/logistics/brown_postbox_from_other_postbox.json +ce3245d64c34c3ca8374275a945004228b8cdaaf data/create/recipes/crafting/logistics/brown_table_cloth.json +850593663b67399a027d5126593e98109e626fea data/create/recipes/crafting/logistics/brown_table_cloth_clear.json +faf9a84bb5227353006f2406461a5a04e15e4111 data/create/recipes/crafting/logistics/brown_table_cloth_from_other_table_cloth.json +7c1fa243e64073d435ff2c4117dc04e002abc465 data/create/recipes/crafting/logistics/copper_table_cloth_clear.json +e899b7e0fd04525a362b62e4ee76aaaa43a33c2e data/create/recipes/crafting/logistics/cyan_postbox.json +062ea448224fea069f6455f430e01198a73aa386 data/create/recipes/crafting/logistics/cyan_postbox_from_other_postbox.json +65a946a8eecf693c8ec701d5ddbf1900c60e0744 data/create/recipes/crafting/logistics/cyan_table_cloth.json +5486c2bc2f263dd901e201bc3bad7015cf9e8d49 data/create/recipes/crafting/logistics/cyan_table_cloth_clear.json +4847ea28034779bcd922b1346afbe083ab06031f data/create/recipes/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json +1bb34be88d5d690ed00e708fbe85d119f97f7abe data/create/recipes/crafting/logistics/gray_postbox.json +19cd2ea89699860c7870f1f38ac4fad3a5efd274 data/create/recipes/crafting/logistics/gray_postbox_from_other_postbox.json +e11f331c5bf91a1865efb5486c0314b0b5812be6 data/create/recipes/crafting/logistics/gray_table_cloth.json +8e04ba7eed8faff3c16e1a841c72d3a778c970f3 data/create/recipes/crafting/logistics/gray_table_cloth_clear.json +d21603c4548c977d043a2ff5a2fa4099343424d4 data/create/recipes/crafting/logistics/gray_table_cloth_from_other_table_cloth.json +25842442f3123e92702e502757de6558c710741a data/create/recipes/crafting/logistics/green_postbox.json +98f88f8462004a734db6928b20b1cb11b8efe03c data/create/recipes/crafting/logistics/green_postbox_from_other_postbox.json +85867127ec54aeca64b316b969d0f6b3cab559e5 data/create/recipes/crafting/logistics/green_table_cloth.json +2c630a129fe21227412803d42dc3211ec95b1a38 data/create/recipes/crafting/logistics/green_table_cloth_clear.json +e3056c024840fe30dd5fec142334cf8fbae4306e data/create/recipes/crafting/logistics/green_table_cloth_from_other_table_cloth.json +d84a6c6a145dc74fbbda8b4762c207c4f28674bd data/create/recipes/crafting/logistics/light_blue_postbox.json +1d5e8eb1be029acdb79a02224530d97e52aa791e data/create/recipes/crafting/logistics/light_blue_postbox_from_other_postbox.json +1cfb864aed59cd9b9f6512aff13eda74995f6f4b data/create/recipes/crafting/logistics/light_blue_table_cloth.json +1763f06ba76551bf5c4950d50561dd491a3fb86f data/create/recipes/crafting/logistics/light_blue_table_cloth_clear.json +ed9bffdeb2e60e9a5f219c5a7d3e999db7f3651f data/create/recipes/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json +49f73e661cdf8974be04cfe46d8aba6de63ed14a data/create/recipes/crafting/logistics/light_gray_postbox.json +b8b16c25f0336449e9a2d165bf40474fed381353 data/create/recipes/crafting/logistics/light_gray_postbox_from_other_postbox.json +976da2180c5da522d07e98284439e9ec89ec21af data/create/recipes/crafting/logistics/light_gray_table_cloth.json +ea87dec016be2987fdc77c82c8ea792f93af3a7b data/create/recipes/crafting/logistics/light_gray_table_cloth_clear.json +7c1e33c5354150e028924a854e8f4dea1232e967 data/create/recipes/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json +e72d0c641ad9a12c3c388601948cf274c9a8c62a data/create/recipes/crafting/logistics/lime_postbox.json +8f6f03db69e3f96d9dc178236a205971ca920b15 data/create/recipes/crafting/logistics/lime_postbox_from_other_postbox.json +1057fe838babd5a390df5445d5266a87326c0bb6 data/create/recipes/crafting/logistics/lime_table_cloth.json +468f4c27ac1134484ea81bafbc81055aab86ed21 data/create/recipes/crafting/logistics/lime_table_cloth_clear.json +13377a12a40705c8ab25137db21f184e4612600a data/create/recipes/crafting/logistics/lime_table_cloth_from_other_table_cloth.json +b46d3a58d318c38df93327789712c1b41681ea7d data/create/recipes/crafting/logistics/magenta_postbox.json +05886ad239c84fd019e1d378450da89137631317 data/create/recipes/crafting/logistics/magenta_postbox_from_other_postbox.json +49be11385f2164fb55bc49445297a41bf8682d0b data/create/recipes/crafting/logistics/magenta_table_cloth.json +9dd457949a6f5ff746c974f8fbf5ebbfa151e31e data/create/recipes/crafting/logistics/magenta_table_cloth_clear.json +a2e1b7080484cc5114196d01d8472aeebaa0df40 data/create/recipes/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json +5dd83b47f9b5406534060662ed37fcea308f3b5b data/create/recipes/crafting/logistics/orange_postbox.json +72596b49737bf7a5fbbf01b2aec20565d2e1a01b data/create/recipes/crafting/logistics/orange_postbox_from_other_postbox.json +2f61600a28d6aaa3d7b0e7a54ed38ad9650b161e data/create/recipes/crafting/logistics/orange_table_cloth.json +ed88c2ba5ea1a41e97e80aa97979587945919233 data/create/recipes/crafting/logistics/orange_table_cloth_clear.json +6c488a8c66ff3aab59b08ef1d1cb98fce5b2976e data/create/recipes/crafting/logistics/orange_table_cloth_from_other_table_cloth.json +9c53c8e6d8e7bcac36f611995c320ebee4a0778a data/create/recipes/crafting/logistics/pink_postbox.json +75622ad3e1fe195399404ae26efeeb6be310fd92 data/create/recipes/crafting/logistics/pink_postbox_from_other_postbox.json +2ef97ee1ade0ea40e275939870dc34ca941e443c data/create/recipes/crafting/logistics/pink_table_cloth.json +b19c6ae1d968c0966815a78f2c112ea872dc1550 data/create/recipes/crafting/logistics/pink_table_cloth_clear.json +ff9044505caf27fb51922a26aa45edca75c8335c data/create/recipes/crafting/logistics/pink_table_cloth_from_other_table_cloth.json +c75f7138e92a54b6841950c5108ee03ede6af4f2 data/create/recipes/crafting/logistics/purple_postbox.json +b4f58bfe14f0b8b0070b71832150b983192ac52f data/create/recipes/crafting/logistics/purple_postbox_from_other_postbox.json +2fe939437431b6a26e0d9d6ce9453fb66fe45d9a data/create/recipes/crafting/logistics/purple_table_cloth.json +36cefcb804b1806428a6ff33bf4e5408d8f7a07f data/create/recipes/crafting/logistics/purple_table_cloth_clear.json +cb44dfbbcccd626f698d3aae8ff65ce3c9620dd2 data/create/recipes/crafting/logistics/purple_table_cloth_from_other_table_cloth.json +6deeeb05693bc98ecfd33cc11e4c098ecd76563b data/create/recipes/crafting/logistics/red_postbox.json +15310750906f41364522e0a27e8f5c2e5fd6c225 data/create/recipes/crafting/logistics/red_postbox_from_other_postbox.json +50876ccdd85879a29ae6181f2c330799a28f1365 data/create/recipes/crafting/logistics/red_table_cloth.json +bddd8bfab2124ea63df317f74d37a6e4b65a583c data/create/recipes/crafting/logistics/red_table_cloth_clear.json +7c6e582effa01018b6f4048378079150c8cb5e8b data/create/recipes/crafting/logistics/red_table_cloth_from_other_table_cloth.json +3b062eeac9c5b9917f3eed67e7525912fb32dfca data/create/recipes/crafting/logistics/white_postbox.json +ace9f83cc4cba51a8564526044ccf6e51abbdf3e data/create/recipes/crafting/logistics/white_postbox_from_other_postbox.json +fc356d74038607c44c6f7d6e7ec56b84a557ebf1 data/create/recipes/crafting/logistics/white_table_cloth.json +8d292e87ac51ea1f1683d67c53a26601d8b89495 data/create/recipes/crafting/logistics/white_table_cloth_clear.json +a9f10b38ae6a44afee64e4ed590a7fd5bb505420 data/create/recipes/crafting/logistics/white_table_cloth_from_other_table_cloth.json +a005bbb2217a7e2c985d88a1255c4285c11dbe0b data/create/recipes/crafting/logistics/yellow_postbox.json +2e387f66250e68d0dadced19d8a93197ff2481f3 data/create/recipes/crafting/logistics/yellow_postbox_from_other_postbox.json +0b2aa56bbbae1189424207afb312fc2bb69b43a1 data/create/recipes/crafting/logistics/yellow_table_cloth.json +655446f2504c7d57d11a893b0c5b1177e4217e58 data/create/recipes/crafting/logistics/yellow_table_cloth_clear.json +db333d47f9e1d6b02aa670ea0aa10dabbcb0e319 data/create/recipes/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json 44a59669177a5a1b0b0eb7cb3dd46826311f4dfe data/create/recipes/crimsite_from_stone_types_crimsite_stonecutting.json c3f4fd2206f3885904913289761f2b8b758e4c95 data/create/recipes/crimsite_pillar_from_stone_types_crimsite_stonecutting.json e1815f97fbc2786d77f5378a2696e36050d8a1fd data/create/recipes/crimson_window.json @@ -3876,11 +4382,15 @@ fe4c573326d76db2064244c7252ac83b9106d5a9 data/create/recipes/exposed_copper_tile ed6a7c88aaeba36b77315b6c35c898ea70eb6852 data/create/recipes/exposed_copper_tile_stairs_from_exposed_copper_tiles_stonecutting.json 33eb062b453631b8341111bffc4b0b14ea74061e data/create/recipes/framed_glass_from_glass_colorless_stonecutting.json 0bf76aa0c0dd584c9d86fde721adc83a1c584f98 data/create/recipes/framed_glass_pane.json +f795481ce68af75fd6039edcd48ea131f0a74c94 data/create/recipes/framed_glass_pane_from_glass_panes_colorless_stonecutting.json c1ac5bad113e067bf5cfa8d730dcc835420aecfb data/create/recipes/granite_from_stone_types_granite_stonecutting.json 1a84a0816303c0cab0cc3c894aaea74d797ae3d3 data/create/recipes/granite_pillar_from_stone_types_granite_stonecutting.json 8d6448c67261138b6331273024b757a9a58b41c4 data/create/recipes/horizontal_framed_glass_from_glass_colorless_stonecutting.json dde9d763cc1306d48e2f3b813530fca0842a5c14 data/create/recipes/horizontal_framed_glass_pane.json +8c5ae2ce4311cc652fffb41cf4912cafbdcddbab data/create/recipes/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json 61f759fec228090a60371add88cc90be3a84a735 data/create/recipes/industrial_iron_block_from_ingots_iron_stonecutting.json +813c68e25ffc543d7457a1417897dd0b579d1b1e data/create/recipes/industrial_iron_window.json +4a4e4f87a2753fb5310f7f70c39143e02b6a6fd0 data/create/recipes/industrial_iron_window_pane.json 2b4a8702db989116dbf97d0021d71a5948336805 data/create/recipes/jungle_window.json 4400d3db46b091d3ead7fbcb64cb712db2fde5de data/create/recipes/jungle_window_pane.json 66da7fc9adbe0119bc41bfad0f6422fb93dcf3b6 data/create/recipes/layered_andesite_from_stone_types_andesite_stonecutting.json @@ -4150,12 +4660,14 @@ f63031587a64ed88ddba1df07767dd8d8caa1d2e data/create/recipes/small_veridium_bric 810544f79bf4b002981e614eaa8e49b48a7b5397 data/create/recipes/spruce_window_pane.json e343a80c92dab60f99c9b441d00189aceee477a0 data/create/recipes/tiled_glass_from_glass_colorless_stonecutting.json bb0dc6d30fd1e5c0becb57961112fcef40347c34 data/create/recipes/tiled_glass_pane.json +730f7155d90836f3e222dccf533110d261d48742 data/create/recipes/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json 170f4dc4478029ba9ffa149051abb9072c59f3d1 data/create/recipes/tuff_from_stone_types_tuff_stonecutting.json fdd28fc956dbec71ba24cdea5adfc049d6eb31e3 data/create/recipes/tuff_pillar_from_stone_types_tuff_stonecutting.json 4e4861de1b7c989cb29e6383f842d7022f48279b data/create/recipes/veridium_from_stone_types_veridium_stonecutting.json 689c523599dcf37398e7217f2732723f6f726049 data/create/recipes/veridium_pillar_from_stone_types_veridium_stonecutting.json 310b9e72aebc37d1e883292c21af914b1026b8fe data/create/recipes/vertical_framed_glass_from_glass_colorless_stonecutting.json 81ec2761606bb5cce35fbd98787cc27d1173103a data/create/recipes/vertical_framed_glass_pane.json +219379d4438fe366f35b7be522e14ebca438b039 data/create/recipes/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json 0b78a940d72347671dd2fa473ed3798ed35cacc6 data/create/recipes/warped_window.json 831733099a8d873706cbb575a24bab5bacaedd9c data/create/recipes/warped_window_pane.json 8a1d0ce28f33e23e90001779374247552bcbb511 data/create/recipes/weathered_copper_shingle_slab.json @@ -4166,12 +4678,16 @@ fdd28fc956dbec71ba24cdea5adfc049d6eb31e3 data/create/recipes/tuff_pillar_from_st 93c61ebeda451ebeb37c3047459f95f14fa9f1f9 data/create/recipes/weathered_copper_tile_slab_from_weathered_copper_tiles_stonecutting.json 8a32b955b4320eddff017378785d1c95e1434229 data/create/recipes/weathered_copper_tile_stairs.json f1a03ac86925e26cbec6aeeada2eafb40008fc8e data/create/recipes/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json +4b5fc518830e3c57471f930deacf0abee4ae6313 data/create/recipes/weathered_iron_block_from_ingots_iron_stonecutting.json +a57dfe9974b8b6d338b9ab4ae124297fda7780b9 data/create/recipes/weathered_iron_window.json +11034a79e8f167249b78e6e3863e01991ac9d778 data/create/recipes/weathered_iron_window_pane.json f365be4eda73234b73aa49c97b065f1a8baafbf6 data/create/tags/blocks/brittle.json 8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/blocks/casing.json -35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/contraption_inventory_deny.json +c603fae95069714ac3d256dfa31f8d2639efafa7 data/create/tags/blocks/chest_mounted_storage.json c7ec0dbc18e9c1b58e568ed925287b89df11a136 data/create/tags/blocks/copycat_allow.json 876eb9210f4a14898a2fe6d225699c66b5bdfeef data/create/tags/blocks/copycat_deny.json 7296238b4c6b81251870addce1de8ecda63381dc data/create/tags/blocks/corals.json +35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/fallback_mounted_storage_blacklist.json f675c20350ed60da4878b5d6301f02c8c05624bd data/create/tags/blocks/fan_processing_catalysts/blasting.json 0592b99f657415f6546564ed8efa1fcbef07ba15 data/create/tags/blocks/fan_processing_catalysts/haunting.json 9386dd9a1d234813f9b8ae4ec88866d396aa1d37 data/create/tags/blocks/fan_processing_catalysts/smoking.json @@ -4179,19 +4695,24 @@ f675c20350ed60da4878b5d6301f02c8c05624bd data/create/tags/blocks/fan_processing_ 6858173c670bb593664ac3c62ded726d57d581f1 data/create/tags/blocks/fan_transparent.json 2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/girdable_tracks.json 02c0a018f2b8540dc2f1fb420172cc716552f321 data/create/tags/blocks/movable_empty_collider.json +35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/non_breakable.json +7f7eb361dcdaa2f081bfed7582c93d6b1b29f8db data/create/tags/blocks/non_harvestable.json 4970078b49ddac1b1d500ed0469cedf42bdc3d35 data/create/tags/blocks/non_movable.json 06e13efbb7b0d09ff7ecd1a7dc45a0760b91ad67 data/create/tags/blocks/ore_override_stone.json a5874f73c7dc0a3ae12999e6ae8abf45bc7fb9be data/create/tags/blocks/passive_boiler_heaters.json +f400870b8dbcd14238be3ec99c419093073ba3a6 data/create/tags/blocks/postboxes.json 9bc8c13fd80bdbe7f767b91ee1a1042e9aff02b0 data/create/tags/blocks/roots.json -79ed9149ee2ce143114db4ccafda8a2b6a293aac data/create/tags/blocks/safe_nbt.json +55dccb895bbdacfbd6ee9005486cd3fe9df01249 data/create/tags/blocks/safe_nbt.json 79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/blocks/seats.json +7d783d948cc49503fb645045fe9ef48906b74341 data/create/tags/blocks/simple_mounted_storage.json f02fc9781e8f0ae33ed3b98cf4f46ba6927c7ff8 data/create/tags/blocks/sugar_cane_variants.json +8a6ad3c63fb0c436ec8109f39358213930effd5a data/create/tags/blocks/table_cloths.json 5def5088f7fd31b80e6f28c1c4ea146aa9d7d15b data/create/tags/blocks/toolboxes.json 2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/tracks.json 1b6977d9a399cf6ee042e3f8f5e64e4d3cda5489 data/create/tags/blocks/tree_attachments.json da739ad2160e7df4e0e5cc89587670ce5e9450c3 data/create/tags/blocks/valve_handles.json 72143286fb5cb372a0696550e2eac76ca50e6fbc data/create/tags/blocks/windmill_sails.json -58987ea71d488cc48192ceb00c00aa2903e51304 data/create/tags/blocks/wrench_pickup.json +a109dab3eeeae64b2eb909ae1b5027716c5dd271 data/create/tags/blocks/wrench_pickup.json 76c0522664726c09461ad4565b6fba80b4f816b2 data/create/tags/entity_types/blaze_burner_capturable.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/entity_types/ignore_seat.json 894e1e4fd1e32712abdda18ec64ab13750d3c039 data/create/tags/fluids/bottomless/allow.json @@ -4203,13 +4724,20 @@ c9ae54a7510073b17edf82f7591e14bdb2c51837 data/create/tags/fluids/fan_processing_ 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/items/blaze_burner_fuel/regular.json 8ba98bf390a326abeebfd5d84be5f740c935a8b6 data/create/tags/items/blaze_burner_fuel/special.json 8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/items/casing.json +3e65a1f943cae7927da2f45388efe248474e5397 data/create/tags/items/chain_rideable.json f43cac8216e2a9347e48cf93a43de95dd810ca20 data/create/tags/items/contraption_controlled.json d371dfd35e49a7bef19f59c03e7f4ae20992f03d data/create/tags/items/create_ingots.json 910d0f5ccbc4c84b224eca1f1588b1695f41447b data/create/tags/items/crushed_raw_materials.json 0fa526e7e742573b603ad26b09526cf724efa1dc data/create/tags/items/deployable_drink.json +35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/items/dispense_behavior_wrap_blacklist.json +ebd7b09daf2f64c0c04d821696b0e145683d8693 data/create/tags/items/dyed_table_cloths.json +d2bb65d893d71d2d9871f81f430c233a93adb4bb data/create/tags/items/invalid_for_track_paving.json 1cebeb92bd514b75d54ac6d5708047801f0501c5 data/create/tags/items/modded_stripped_logs.json 586f8fc5a8b8559c9dc0017e13c78ad918688fae data/create/tags/items/modded_stripped_wood.json +cebf5fd98eddf5c14befdd47052be678eea79542 data/create/tags/items/packages.json +f400870b8dbcd14238be3ec99c419093073ba3a6 data/create/tags/items/postboxes.json 695d75b352fd190b303c724d1aaee9bb786a903b data/create/tags/items/pressurized_air_sources.json +22c4d4e033a61942b170aa309ed46a89a0ba0c65 data/create/tags/items/pulpifiable.json 2cd3adffd8b151354df137a990dcb97996a665bb data/create/tags/items/sandpaper.json 79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/items/seats.json e02cb3bc2373336dc04495b0b414107f6f754b61 data/create/tags/items/sleepers.json @@ -4230,6 +4758,7 @@ e22493305e0cebfb7ededae122e19ee9dd24fc9d data/create/tags/items/stone_types/scor 8034ddb85922b193ad1e6251fc6b856b4ae622b1 data/create/tags/items/stone_types/scoria.json 7e4d20c52a25a0c0d13e0122be0250718a9fb645 data/create/tags/items/stone_types/tuff.json 076c79e07eb3a65d74107577dbfd993b13780637 data/create/tags/items/stone_types/veridium.json +8a6ad3c63fb0c436ec8109f39358213930effd5a data/create/tags/items/table_cloths.json 5def5088f7fd31b80e6f28c1c4ea146aa9d7d15b data/create/tags/items/toolboxes.json 2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/items/tracks.json a5b5711d1798473a9b25db5b7f749570ed0a2769 data/create/tags/items/upgrade_aquatic/coral.json @@ -4239,23 +4768,28 @@ c59c9fc0cdd45de659aa8023d36f9decb90f708c data/create/tags/items/vanilla_stripped 64441ac1daa64c81601b94b82b21c0ee862b6344 data/create/tags/items/vanilla_stripped_wood.json edf7390f09e622193bbc720ec51ba128ea1e96e6 data/curios/tags/items/head.json 10d5f0c1763f80860a39398ecc33dbbe43099471 data/forge/tags/blocks/glass/colorless.json -de1fc89be6a52473d526d3efe0204b9b8489058c data/forge/tags/blocks/glass_panes.json +220b4c682f6cf536534e7cd6a79a9acc811bacd2 data/forge/tags/blocks/glass_panes.json +a8425bd1e4174a0beb97a3ccc348ae7d1106725f data/forge/tags/blocks/glass_panes/colorless.json 81b107ada9c6ac5679a21f8c6a006bf230f69c39 data/forge/tags/blocks/ores.json 81b107ada9c6ac5679a21f8c6a006bf230f69c39 data/forge/tags/blocks/ores/zinc.json e475ad1c52bffedfc544e5331a87c1f5c45149fd data/forge/tags/blocks/ores_in_ground/deepslate.json 2f6068972e364599b6849dc46fcb0724d4219d53 data/forge/tags/blocks/ores_in_ground/stone.json 2589b135c0e96ad29076569e144528fe32ea5b39 data/forge/tags/blocks/relocation_not_supported.json -b3af02a6fa3dc41bc3f4db933485f22b202deea3 data/forge/tags/blocks/storage_blocks.json +807ea01d3b028bd226ed0befc142cbd23647e998 data/forge/tags/blocks/storage_blocks.json 7d10cdf9e46a79753d4437c7bb958e3ab8bf0c89 data/forge/tags/blocks/storage_blocks/andesite_alloy.json 70bba470740dc7a77f51b4cb1747a105b62d4bde data/forge/tags/blocks/storage_blocks/brass.json +18f54179c6f809ff4aee792702fa35d3053e5dc4 data/forge/tags/blocks/storage_blocks/cardboard.json bcd593714f43bc6a0aefbd714c24db3cf9e71250 data/forge/tags/blocks/storage_blocks/raw_zinc.json 41b2a17b5ebcff5623e25dc6232f73cf9aa70387 data/forge/tags/blocks/storage_blocks/zinc.json 8140415f1c16f09167f41eeee25c09706a944be0 data/forge/tags/fluids/chocolate.json 0ccc9ff76001cdd7db1b79c1371f59d3283abe64 data/forge/tags/fluids/honey.json cca816b34ac2e9b7933df680aa9778ff2cfe9605 data/forge/tags/fluids/tea.json -00c856dcfa4368cca671ee5d93c4900835991d68 data/forge/tags/items/armors/boots.json +1a9ce7d5f5fe92d3b73e269cd5dbf5cd1f1fe5b8 data/forge/tags/items/armors/boots.json +6749b53c23aefe4baa55c4b2f624bbc6dfe5f423 data/forge/tags/items/armors/chestplate.json 695d75b352fd190b303c724d1aaee9bb786a903b data/forge/tags/items/armors/chestplates.json +5b91b107f48b47958db20f13cb3cc0c6f7085fdc data/forge/tags/items/armors/helmet.json 3580dae058fc75b45fab4c4ebbd1b01573ba9e11 data/forge/tags/items/armors/helmets.json +afdac448376ff5624f49cbf31feedf691ecbc4c5 data/forge/tags/items/armors/leggings.json 06ebf72e8f6c081862236d4b068b5dfb275a8385 data/forge/tags/items/buckets/honey.json 801d097b0af7153e0c5c72a924d61f8afb4cf264 data/forge/tags/items/dough.json 801d097b0af7153e0c5c72a924d61f8afb4cf264 data/forge/tags/items/dough/wheat.json @@ -4263,7 +4797,8 @@ cca816b34ac2e9b7933df680aa9778ff2cfe9605 data/forge/tags/fluids/tea.json 745512f10c4ba52f2c224607377e41011fb2ecfe data/forge/tags/items/flour.json 745512f10c4ba52f2c224607377e41011fb2ecfe data/forge/tags/items/flour/wheat.json 10d5f0c1763f80860a39398ecc33dbbe43099471 data/forge/tags/items/glass/colorless.json -de1fc89be6a52473d526d3efe0204b9b8489058c data/forge/tags/items/glass_panes.json +220b4c682f6cf536534e7cd6a79a9acc811bacd2 data/forge/tags/items/glass_panes.json +a8425bd1e4174a0beb97a3ccc348ae7d1106725f data/forge/tags/items/glass_panes/colorless.json 01d32d3b7b033aff44c047bf289d696de0b0c715 data/forge/tags/items/ingots.json 5a7bffd1d604bc6ea8b35714ef02b95773240f90 data/forge/tags/items/ingots/brass.json ccf5b08295f6362a3f6b3b595f1de1bba4b224ec data/forge/tags/items/ingots/zinc.json @@ -4277,15 +4812,17 @@ e475ad1c52bffedfc544e5331a87c1f5c45149fd data/forge/tags/items/ores_in_ground/de 2f6068972e364599b6849dc46fcb0724d4219d53 data/forge/tags/items/ores_in_ground/stone.json 12c3455bbb7edcea84d47ad6ccde9c209a25d811 data/forge/tags/items/plates.json 23f4874238f7d06e80c699b672d4e9fab6eb464f data/forge/tags/items/plates/brass.json +7f3f85d0978bc274e4689fbf41f7b80b023b7a05 data/forge/tags/items/plates/cardboard.json ef5256892a9d4167bf7371c7138a933a107a123a data/forge/tags/items/plates/copper.json 3ca40ae504b1f68d6e7279726a2bf411509ce322 data/forge/tags/items/plates/gold.json 6f72d5205b399f03e481cee15bd5c085bfe6fe3c data/forge/tags/items/plates/iron.json 07a6e69488ff6994a9ef1cca75b6e911bc3e3358 data/forge/tags/items/plates/obsidian.json 30496416fffaf4f845052a264023e64e52894ee7 data/forge/tags/items/raw_materials.json 30496416fffaf4f845052a264023e64e52894ee7 data/forge/tags/items/raw_materials/zinc.json -b3af02a6fa3dc41bc3f4db933485f22b202deea3 data/forge/tags/items/storage_blocks.json +807ea01d3b028bd226ed0befc142cbd23647e998 data/forge/tags/items/storage_blocks.json 7d10cdf9e46a79753d4437c7bb958e3ab8bf0c89 data/forge/tags/items/storage_blocks/andesite_alloy.json 70bba470740dc7a77f51b4cb1747a105b62d4bde data/forge/tags/items/storage_blocks/brass.json +18f54179c6f809ff4aee792702fa35d3053e5dc4 data/forge/tags/items/storage_blocks/cardboard.json bcd593714f43bc6a0aefbd714c24db3cf9e71250 data/forge/tags/items/storage_blocks/raw_zinc.json 41b2a17b5ebcff5623e25dc6232f73cf9aa70387 data/forge/tags/items/storage_blocks/zinc.json b69fcc7227d44fc000c8ab94524230f55b89aa27 data/forge/tags/items/stripped_logs.json @@ -4294,12 +4831,14 @@ c741ba83b562ae3459d7c4f2db69537f549ea411 data/forge/tags/items/tools/wrench.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/azalea_root_replaceable.json 529fa4332dd12a11ebb04e183121a2c63f866761 data/minecraft/tags/blocks/beacon_base_blocks.json 82274e06b6a9f3bfd83c8b59be38dee4a15b8bf3 data/minecraft/tags/blocks/climbable.json +ebd7b09daf2f64c0c04d821696b0e145683d8693 data/minecraft/tags/blocks/combination_step_sound_blocks.json 71aef080a900d9e86818cf579438c3d826d6567e data/minecraft/tags/blocks/doors.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/dripstone_replaceable_blocks.json -e3321ff14704c031a2c16953b7e391f4f24dd70b data/minecraft/tags/blocks/impermeable.json +f8bd9b33238ab9f2f2a83b63bf0c52fbf705b452 data/minecraft/tags/blocks/impermeable.json +eb080d6f0f7a4fa5e723010e1fcfa781e4d30249 data/minecraft/tags/blocks/inside_step_sound_blocks.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/lush_ground_replaceable.json -5a030817b2322e363edc8f5376f7c9de73df8b48 data/minecraft/tags/blocks/mineable/axe.json -d794a156fdc9ec9e7c935b3b8962206b7b82eb79 data/minecraft/tags/blocks/mineable/pickaxe.json +435e59881e2d9a8cae6c23fc6ce6d43111d40277 data/minecraft/tags/blocks/mineable/axe.json +47df6c90d9474d7a708063b0207e520ad01f1998 data/minecraft/tags/blocks/mineable/pickaxe.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/moss_replaceable.json 0c13aae0eeb99e89febe8dbe5e002af2ff843a9e data/minecraft/tags/blocks/needs_iron_tool.json 3cb2a92cbdf32ed5978f740dc378d363306c3e84 data/minecraft/tags/blocks/needs_stone_tool.json @@ -4315,5 +4854,6 @@ cd2613a4722ce79366433181095c27463e7c61b8 data/minecraft/tags/blocks/stairs.json 1ac7c46815461cbec0d4d97f25c085fdc8375dab data/minecraft/tags/items/slabs.json dafa3bdb72fef5e6c0201c05846db3f2b214e587 data/minecraft/tags/items/stairs.json 11427a72e181857e22ec37a22462bc652e127cc5 data/minecraft/tags/items/trapdoors.json +15d3621abbef2048a7c258d410e40d9d87e55dd7 data/minecraft/tags/items/trimmable_armor.json 2bcba05954ff7bc4cf9cc520478083da9973ec76 data/minecraft/tags/items/walls.json 71aef080a900d9e86818cf579438c3d826d6567e data/quark/tags/blocks/non_double_door.json diff --git a/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba b/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba index 1c010d34b7..24fa8bb5b6 100644 --- a/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba +++ b/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba @@ -1,4 +1,4 @@ -// 1.20.1 2024-10-09T12:24:59.1794112 Create's Advancements +// 1.20.1 2025-02-02T11:59:39.4186146 Create's Advancements 2661a689fdcf729494f46e3c719f71c62e31582e data/create/advancements/andesite_alloy.json fa16c4afe0496edc3f157858a6e0ff177a1622ff data/create/advancements/andesite_casing.json 5a694002d0a663bc869b09d15924a10c43dc522f data/create/advancements/anvil_plough.json @@ -10,6 +10,9 @@ b960076e653a3682aa4ebb82bdca957d455c7604 data/create/advancements/backtank.json ca6d0355dbd9a7de587c4ebf2aed82e920e007c1 data/create/advancements/brass.json 78224097bda936d1ba9bf682a9177ad252139a51 data/create/advancements/brass_casing.json 113f1a063d78207e600e536200004756b42e0cd7 data/create/advancements/burner.json +680a97ebbb3579e0cbe52bf3b98bfd94a1d988aa data/create/advancements/cardboard.json +b7da43c88bd8a2e065c1a0656a9831908879c988 data/create/advancements/cardboard_armor.json +ded6f5eac4eab92834e4775285ffbbc2196db081 data/create/advancements/cardboard_armor_trim.json 7c0aed400d4933d5ca13db42517efa2959a1bed0 data/create/advancements/cart_pickup.json 2970c69c310e8e3dbe295621d04a8f42bb7fd1f0 data/create/advancements/chained_drain.json 5334499c577b7531a5de2ff46f371939554f1eb8 data/create/advancements/chocolate_bucket.json @@ -19,7 +22,7 @@ e99071520e9b27b66085367683bc7b972a349c2f data/create/advancements/chute.json 041ddb4720296fc4446d5d694afe3ec1c21c881b data/create/advancements/conductor.json 848f64e1f30c1ec0eac57b6760e282cf030a25fc data/create/advancements/contraption_actors.json 5074053518627b4229bd1f79b20c67e3056f7983 data/create/advancements/copper.json -90763d18fa6cf42cb409b75bc2a3be53d76aab1d data/create/advancements/copper_casing.json +83b2703c3b79187161b44697930bb1c46a920f0b data/create/advancements/copper_casing.json f2e04dd82a25cc080a4901e03e0f1fafeb6ea191 data/create/advancements/crafter_lazy_000.json 4f88d0bf42d208bc5037509c197725bc4e4e68e4 data/create/advancements/cross_streams.json 44ed195706af6ee0cc3b98b9ea4f7d8326899391 data/create/advancements/crusher_maxed_0000.json @@ -27,7 +30,7 @@ f2e04dd82a25cc080a4901e03e0f1fafeb6ea191 data/create/advancements/crafter_lazy_0 01c6fa0494e5915b99a0b0aebd941ebbb177cd3a data/create/advancements/cuckoo_clock.json ac78707d112458c7f771260cf65f0e9bc928d1b6 data/create/advancements/deployer.json 48c3af4499797cfb695a235e4527c52c608d40ad data/create/advancements/display_board_0.json -24be041d833017d7e7e02a5a92fd04060ea62594 data/create/advancements/display_link.json +ef4055989f4ffc7432ed9531ec4639c69fd48ba6 data/create/advancements/display_link.json cc2c729cf82a0c80b4966ac6382984da08429b9d data/create/advancements/diving_suit.json e1af547fd148cf9e60c1725ab03545fe3010eac7 data/create/advancements/diving_suit_lava.json 4d91e6a7bbf08191d8d1e11943650dfc1dc170e6 data/create/advancements/drain.json @@ -35,9 +38,11 @@ dee06f0f78a97a6358b67459d05fb479e5318fe9 data/create/advancements/ejector_maxed. 3300ee54dc1e9d04fd13a11c971e046d9db24e10 data/create/advancements/encased_fan.json fb61193b9d02d1fd595ac99721812a59dc7c7c29 data/create/advancements/extendo_grip.json 845a6c63b26a238c5ff82f37ca25ef5a8f7c11fc data/create/advancements/extendo_grip_dual.json +7ea086b6667879458bbc3cfd5b7bef59cd22f5b3 data/create/advancements/factory_gauge.json 46950345e76ef2d98bf3ea737530976781901a0f data/create/advancements/fan_processing.json 8f0f884dbc6eb94e03ffae374105c7100a073d85 data/create/advancements/fist_bump.json 5e39ecb68037ade25897dff1dc419065752d2c43 data/create/advancements/foods.json +9b029a15bd4c6bfa71da0a256df5a12532d4645a data/create/advancements/frogport.json 7c72b9440b3f0525658b5c12d46a56d48521ca93 data/create/advancements/funnel.json 1dcfded7b20756ad6dfd4a6c4d0106c343e9e17e data/create/advancements/glass_pipe.json 94a4e1ac38935288cc84f4b374cf1553ed39b2b0 data/create/advancements/hand_crank_000.json @@ -56,6 +61,8 @@ d89152d4f3c992b892e8ec4bef03605ef20c1520 data/create/advancements/mechanical_cra 5b50f84f2b697d630294e2b8db8b60dba84a1011 data/create/advancements/mechanical_pump_0.json 8adbdf6e0b0df40fed5ecfc5a5b13ca6a075be83 data/create/advancements/millstone.json 82a61db27464e2ede2b2079276cf69bb465a5085 data/create/advancements/musical_arm.json +87f554c3621a11dd5f49553202e76d6a8df30623 data/create/advancements/packager.json +a59b972ef1ebb7bee001282a2d71553363a3ee92 data/create/advancements/package_chute_throw.json a7119c747a2c16d93b9df669f80ccb3863a331ce data/create/advancements/pipe_organ.json 8118ffd53c264f535517936a0fc720a7850e8907 data/create/advancements/portable_storage_interface.json 826768f46254a9fc0ea048e600511cab4a0a781f data/create/advancements/potato_cannon.json @@ -73,15 +80,17 @@ a1e44c8ff2b7ed96d4b76e6122fd41fa528826b1 data/create/advancements/speed_controll 28c7898ee0dad051744b95c0154744caf025e849 data/create/advancements/steam_engine.json b3c18b1d41126d135318769f83ccc6fe51da2c54 data/create/advancements/steam_engine_maxed.json 742b75d31271e5f58ba2572606a10a43db8acea1 data/create/advancements/steam_whistle.json +e6317ea94e3f891f6767fb054fc6955e8c948a96 data/create/advancements/stock_ticker.json 90954d173a67584221ee02114971d515247607ae data/create/advancements/stressometer.json b77e7b17c397cc88ca2f75f68c52d60488ece97a data/create/advancements/stressometer_maxed.json cc75b35e53137d229896c334f09ebc5930f56307 data/create/advancements/sturdy_sheet.json 4794a7d7ea140333809bb78b77a30997bbb606bd data/create/advancements/super_glue.json +3b3b1778c82b14f029a803d45bd0f3985004999b data/create/advancements/table_cloth_shop.json cbc796a4bd3dd9bb3e66ab437b27fcf5a1fdc050 data/create/advancements/track_0.json 916a9a75900fa36aa3c5422d4e35eeeb57d20f61 data/create/advancements/track_crafting_factory.json 4938c2be415c15a70a41570bbb49f772eaed5af0 data/create/advancements/track_signal.json 797f76512083d562549a20e9abc679846cce885f data/create/advancements/train.json -227f401a440746c02ce0713c44b4cc623307e014 data/create/advancements/train_casing_00.json +62d418a19498cb9f788d64c967ee1c15c886c60e data/create/advancements/train_casing_00.json f1645a6cfdfcade5366d9f3be501e596b1600330 data/create/advancements/train_crash.json 484986302e8c1708064b5dbb5ce35e443f6151d7 data/create/advancements/train_crash_backwards.json 22c39846ee59d7c71468fe795fa354cb0a4aafd9 data/create/advancements/train_portal.json diff --git a/src/generated/resources/.cache/499d9d953ee69b539ff4dd4c95a6cbd849f63f67 b/src/generated/resources/.cache/499d9d953ee69b539ff4dd4c95a6cbd849f63f67 index 96f56121bf..72dd1ea710 100644 --- a/src/generated/resources/.cache/499d9d953ee69b539ff4dd4c95a6cbd849f63f67 +++ b/src/generated/resources/.cache/499d9d953ee69b539ff4dd4c95a6cbd849f63f67 @@ -1,4 +1,4 @@ -// 1.20.1 2024-10-09T12:24:59.1824022 Create Train Hat Information +// 1.20.1 2025-02-02T11:59:39.4206093 Create Train Hat Information be16d47aa64e673b1107a36ce06475016e316fca assets/minecraft/train_hat_info/axolotl.json b8ae6d9c8014439f4049622e0d6e79b9d6716260 assets/minecraft/train_hat_info/bat.json 5053a6c9fb412dfac1bf17eb0f57f9fd314198e4 assets/minecraft/train_hat_info/bee.json @@ -47,6 +47,6 @@ e524c61954660d3cb605f01395edb25572b59a1c assets/minecraft/train_hat_info/skeleto b8ae6d9c8014439f4049622e0d6e79b9d6716260 assets/minecraft/train_hat_info/turtle.json 78950a0bb66d28d1939049400a8cfd194f92f906 assets/minecraft/train_hat_info/warden.json 5ed6eccda89a6721f1b70eca7e7869cfc30aa612 assets/minecraft/train_hat_info/wither.json -0ac114bc3a5d0a0ab3153cae258a30fe970d4264 assets/minecraft/train_hat_info/wolf.json +0e92893e2b9d3e6586610e4e13c678e11beb1e64 assets/minecraft/train_hat_info/wolf.json daac75dcadb6e00db5cf1a5b30a450f137da54ae assets/minecraft/train_hat_info/zoglin.json e524c61954660d3cb605f01395edb25572b59a1c assets/minecraft/train_hat_info/zombie_horse.json diff --git a/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 b/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 index 0a84a5228e..58b9d1aab7 100644 --- a/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 +++ b/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 @@ -1,4 +1,4 @@ -// 1.20.1 2024-10-09T12:24:59.2726698 Create's Mechanical Crafting Recipes +// 1.20.1 2025-02-02T11:59:39.6030726 Create's Mechanical Crafting Recipes f076d64d9f30709bed34775136c9241097b28aa9 data/create/recipes/mechanical_crafting/crushing_wheel.json 694dca9dcff246bb7f560b3304fcc244c53217d5 data/create/recipes/mechanical_crafting/extendo_grip.json c03bc27f537e2d6531438bf58a17d977a7e16c7b data/create/recipes/mechanical_crafting/potato_cannon.json diff --git a/src/generated/resources/.cache/7d46d12a3645c7522a1eb5ebfbd8f5637c3a20d8 b/src/generated/resources/.cache/7d46d12a3645c7522a1eb5ebfbd8f5637c3a20d8 new file mode 100644 index 0000000000..564011532a --- /dev/null +++ b/src/generated/resources/.cache/7d46d12a3645c7522a1eb5ebfbd8f5637c3a20d8 @@ -0,0 +1,3 @@ +// 1.20.1 2025-02-20T18:50:30.47100651 Create's Contraption Type Tags +700982b6682ea583e7f08e44198af1b3219531d5 data/create/tags/create/contraption_type/opens_controls.json +08384ffb27c43caadbd36c2d390ed9af1c357084 data/create/tags/create/contraption_type/requires_vehicle_for_render.json diff --git a/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 b/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 index 52e3dc4f30..17c7de3f6c 100644 --- a/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 +++ b/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 @@ -1,4 +1,4 @@ -// 1.20.1 2024-10-09T12:24:59.2686824 Create's Standard Recipes +// 1.20.1 2025-02-12T10:49:57.1801346 Create's Standard Recipes a8cc4af26f6c7c45a9eef12e92af1452fe042454 data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json 2c2639c7b307ee7c7a4e97e5efebf496788998ad data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json 81dcf0cb1aa99e39bc7d1a386e07cad4cee7d8b9 data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json @@ -34,6 +34,13 @@ b90af96817d6c38ec446f7464642a473a55c2027 data/create/advancements/recipes/misc/b 0337c63f3fa75e8ae8ece4a05c85d52313e04f13 data/create/advancements/recipes/misc/blasting/zinc_ingot_from_raw_ore.json 979ce50c0238ee2512acbe568f093b96d253adbe data/create/advancements/recipes/misc/campfire_cooking/bread.json 3d2decdb350a8ba7f553dec5ee5f7b79d6cfd9c4 data/create/advancements/recipes/misc/crafting/appliances/attribute_filter_clear.json +84d6c2b2c256ead627764816f389729c6954d38e data/create/advancements/recipes/misc/crafting/appliances/book.json +28dfbb796d48a7bb2ba4a69003dfa30a7a4a2c7e data/create/advancements/recipes/misc/crafting/appliances/cardboard_boots.json +52a32f67c9303fe18c51c40b49ca359cc556eb26 data/create/advancements/recipes/misc/crafting/appliances/cardboard_chestplate.json +6a0d06d354aa7f81e6141a03aeef9a51d03e3cd4 data/create/advancements/recipes/misc/crafting/appliances/cardboard_helmet.json +dd3d469cc9899f3f7299cbd6903a2b541df5c7ff data/create/advancements/recipes/misc/crafting/appliances/cardboard_leggings.json +f94a848698e7e52e0fb15b240a4e0ef89a3974fd data/create/advancements/recipes/misc/crafting/appliances/cardboard_sword.json +52f97cc60de343ce7980113b2b458376dd8cbd74 data/create/advancements/recipes/misc/crafting/appliances/chain_from_zinc.json 8b0f0b4342adbd3466c81298c87b5ed8993c3636 data/create/advancements/recipes/misc/crafting/appliances/clipboard.json 42f06a32b53c954a54fa1d5ffb1afd2e161cbde2 data/create/advancements/recipes/misc/crafting/appliances/clipboard_clear.json 6fa2794d2d8d8d5ffeea22701862d79578adf7f2 data/create/advancements/recipes/misc/crafting/appliances/copper_backtank.json @@ -42,7 +49,10 @@ b90af96817d6c38ec446f7464642a473a55c2027 data/create/advancements/recipes/misc/b 0746cb63e224d7620e781e1494b9a8b9d56b186b data/create/advancements/recipes/misc/crafting/appliances/crafting_blueprint.json c4d0901541855ea2fda0cef7f0270edfa16d70e2 data/create/advancements/recipes/misc/crafting/appliances/dough.json 79b6501f8cb069dc55b78871a5fecf40a5b3dbd5 data/create/advancements/recipes/misc/crafting/appliances/filter_clear.json +37ad1d645de355b261b9bb6b611bd136723233b7 data/create/advancements/recipes/misc/crafting/appliances/item_frame.json 3271ad36fbab51d87d0baad8c69cb7b2add506b8 data/create/advancements/recipes/misc/crafting/appliances/linked_controller.json +54ed96f8c7d040058e5e682d68279d197b08e5e1 data/create/advancements/recipes/misc/crafting/appliances/name_tag.json +9ce5a607b16146339de77128aec3747f8054d03b data/create/advancements/recipes/misc/crafting/appliances/package_filter_clear.json d4d13730d982713b5809ecf30187e01707248d75 data/create/advancements/recipes/misc/crafting/appliances/schedule_clear.json 44c1a131bed101ad4b87d57816ff5a375cc36bf4 data/create/advancements/recipes/misc/crafting/appliances/slime_ball.json 7d0fa7ac8a04b19cd3db31342e276d2da4860a1d data/create/advancements/recipes/misc/crafting/appliances/tree_fertilizer.json @@ -59,6 +69,7 @@ a8a3a16f1990f73cc0a6b7bca23a96ffa22f416d data/create/advancements/recipes/misc/c f7517ad35e98d11c7244be86ba4a7bde85eeaf13 data/create/advancements/recipes/misc/crafting/kinetics/brass_door.json 627b0ebad7cbc45d8a0c5803de626fa520bb2023 data/create/advancements/recipes/misc/crafting/kinetics/brass_hand.json 2408e2a5b5ca63f196a90a20bcf7f0d301fa2aa0 data/create/advancements/recipes/misc/crafting/kinetics/cart_assembler.json +ab387bedffc75758e85c66c7004c13f329611cf1 data/create/advancements/recipes/misc/crafting/kinetics/chain_conveyor.json aaaf7e0649acebf491229781c56a7b95a71a1c84 data/create/advancements/recipes/misc/crafting/kinetics/chute.json e8ba77b35a1f6cb364e143a9397a6314125b592f data/create/advancements/recipes/misc/crafting/kinetics/clockwork_bearing.json 71f386d073b9e0fb647a751cd6b75c0b70f1b001 data/create/advancements/recipes/misc/crafting/kinetics/clutch.json @@ -77,6 +88,7 @@ a85aecdec18802b97c23cf21f57e59bf71bfe690 data/create/advancements/recipes/misc/c 5eddf6af005751b5628d8bc032d064861c7070e0 data/create/advancements/recipes/misc/crafting/kinetics/elevator_pulley.json df55f1a1e16f8a1771b617acfeb22cb5991dbab0 data/create/advancements/recipes/misc/crafting/kinetics/empty_blaze_burner.json b0ec44a665cfcc180f5f6a534ef963f431f252d1 data/create/advancements/recipes/misc/crafting/kinetics/encased_chain_drive.json +dc29c1449cecf840e3c2db0f56884950cad7543c data/create/advancements/recipes/misc/crafting/kinetics/encased_chain_drive_from_zinc.json 82d47f9b54917def4ed1a73b4d90d98071d30341 data/create/advancements/recipes/misc/crafting/kinetics/encased_fan.json aae73187c99468804f57403864846116745d04a0 data/create/advancements/recipes/misc/crafting/kinetics/filter.json 8b85fc7d791aafac0b330d2a7820c71f80257cce data/create/advancements/recipes/misc/crafting/kinetics/fluid_pipe.json @@ -90,7 +102,7 @@ a11a4e11fe9b762ccf8be72adffd59e45f6d47fe data/create/advancements/recipes/misc/c 8eb770396aa27283baabbc708698f5419a65a657 data/create/advancements/recipes/misc/crafting/kinetics/gantry_carriage.json 1c5e47b8dde41e2947c2f6111616cc0493a4aa7e data/create/advancements/recipes/misc/crafting/kinetics/gantry_shaft.json 2d413928c4305a5bf2b7bc9787ec2cb7ae5a062d data/create/advancements/recipes/misc/crafting/kinetics/gearbox.json -005c2d4110a88f08561edf23835b626103e1ebdd data/create/advancements/recipes/misc/crafting/kinetics/gearboxfrom_conversion.json +2fe7506d05f1fffbbcc6b870d3fc343bb587faef data/create/advancements/recipes/misc/crafting/kinetics/gearbox_from_conversion.json d2dded1337838b08b79e6648dba326eca1cf3a1a data/create/advancements/recipes/misc/crafting/kinetics/gearshift.json 146325fa3698e3622fd848e8e6852e9a345d9919 data/create/advancements/recipes/misc/crafting/kinetics/goggles.json 5afa3600386e6a4cd00827d8c8ba6f48d186d968 data/create/advancements/recipes/misc/crafting/kinetics/hand_crank.json @@ -101,7 +113,7 @@ d2dded1337838b08b79e6648dba326eca1cf3a1a data/create/advancements/recipes/misc/c 7c29cbb89566ed33f44e77cba339c52f70929359 data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheel_from_little.json 3085e5ac3822c41d5b52c19114149dc59aa5a976 data/create/advancements/recipes/misc/crafting/kinetics/large_water_wheel.json 73c5818c85cf3908a77ca2380b71ffd8e2f6eb44 data/create/advancements/recipes/misc/crafting/kinetics/linear_chassis.json -c7f3dfb1fdca94ad9d54992f0217786674705a23 data/create/advancements/recipes/misc/crafting/kinetics/linear_chassisfrom_conversion.json +42e85c0a63282d052b2dd979caaa50280af2a4d7 data/create/advancements/recipes/misc/crafting/kinetics/linear_chassis_from_conversion.json ba22885e1a95a0deaa8546dd977978c60b515f65 data/create/advancements/recipes/misc/crafting/kinetics/mechanical_arm.json d00bc56d415fd2c5a073961838173704fdcc43a7 data/create/advancements/recipes/misc/crafting/kinetics/mechanical_bearing.json 88142129f4c99e4266cfb1c172db6a6c1de83799 data/create/advancements/recipes/misc/crafting/kinetics/mechanical_crafter.json @@ -121,6 +133,7 @@ e918e8844c6ef4f5adcc95665a05f64c5372abcc data/create/advancements/recipes/misc/c 4c03ca9d953e800c23ca049c4428d9dd40a18d26 data/create/advancements/recipes/misc/crafting/kinetics/mysterious_cuckoo_clock.json d283b37887dc62e22965dbafbd3a3eb98d0488cf data/create/advancements/recipes/misc/crafting/kinetics/nixie_tube.json 27e3d4b5011ce17cc687a4a8b38b574dfff279d3 data/create/advancements/recipes/misc/crafting/kinetics/nozzle.json +fd5c479e8ad77d130a5e3be292f8d0b54baa13f2 data/create/advancements/recipes/misc/crafting/kinetics/package_filter.json df79a596a5b07701620a8bb86a7df4601b58c77d data/create/advancements/recipes/misc/crafting/kinetics/piston_extension_pole.json 384efeea25b1968b3131905da2d7cd73455768c5 data/create/advancements/recipes/misc/crafting/kinetics/placard.json 293f057653f70b25e9f94ddb514c8b95be3169ed data/create/advancements/recipes/misc/crafting/kinetics/portable_fluid_interface.json @@ -130,21 +143,21 @@ c56ed6c06c97571d88e1dd270e6ed8dc917c1c4c data/create/advancements/recipes/misc/c 0cc198acbc6355e66febbb10c890a15517043290 data/create/advancements/recipes/misc/crafting/kinetics/rope_pulley.json 0171ff48525e4f52556d4052ce61a2651c94ee4e data/create/advancements/recipes/misc/crafting/kinetics/rose_quartz_lamp.json a48ba9ff9296828767929cdece32b105911def6b data/create/advancements/recipes/misc/crafting/kinetics/rotation_speed_controller.json -b0015a697c8c9e4de401822be7146b503b2a9517 data/create/advancements/recipes/misc/crafting/kinetics/sail_framefrom_conversion.json +9ba063e03d56eef75cffcb1b3b1e6e9dfe594704 data/create/advancements/recipes/misc/crafting/kinetics/sail_frame_from_conversion.json df5d477fe7e901ac33187160081061ace0a291a9 data/create/advancements/recipes/misc/crafting/kinetics/schedule.json -b3222b4ad0e076b5dbedb93e49e947a960572f95 data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassisfrom_conversion.json +98b67a463a5988cd318b9ed1123ca51f4121dbd4 data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassis_from_conversion.json 319154470d3c5289e1657947b312323e6bc0da52 data/create/advancements/recipes/misc/crafting/kinetics/sequenced_gearshift.json b7b1cddd6964faf54efa794aa6697c16855c968c data/create/advancements/recipes/misc/crafting/kinetics/shaft.json 28b94c9f030cd0f4c4c68f2c6123566066af4a0f data/create/advancements/recipes/misc/crafting/kinetics/smart_chute.json 298f59618e269714385fb9cf7a2e973d61380a40 data/create/advancements/recipes/misc/crafting/kinetics/smart_fluid_pipe.json a6dfc4c646a359ebfb4fc839bde6ebcde54ae1a6 data/create/advancements/recipes/misc/crafting/kinetics/speedometer.json -a48f86ff4efc8f322feef41db862a39e681043b9 data/create/advancements/recipes/misc/crafting/kinetics/speedometerfrom_conversion.json +ba1bb5ce9a0dc8438fe128b31cb97dc0892a6d55 data/create/advancements/recipes/misc/crafting/kinetics/speedometer_from_conversion.json d2315557fb6d9c5086c8801033b6562c775e35e6 data/create/advancements/recipes/misc/crafting/kinetics/spout.json 31c0a0d5d6d1a01b4f9702e5a23c9341727fe4e8 data/create/advancements/recipes/misc/crafting/kinetics/steam_engine.json a5396817b5978fd150f8c3ef33a0cbff22a9e315 data/create/advancements/recipes/misc/crafting/kinetics/steam_whistle.json 0123b8926c6e37551b8e3fdb72f44da181cd4e03 data/create/advancements/recipes/misc/crafting/kinetics/sticker.json c510077aaf3b7b8cea230578f835bf4e679089bf data/create/advancements/recipes/misc/crafting/kinetics/sticky_mechanical_piston.json -8e2048e5e795b971ede965d56b2eb46eb71e106e data/create/advancements/recipes/misc/crafting/kinetics/stressometerfrom_conversion.json +2ff567b433359b6b59ba95219abbeb2e874da663 data/create/advancements/recipes/misc/crafting/kinetics/stressometer_from_conversion.json fc9a10e60637cb2da98825a1d79359431fdd8e9b data/create/advancements/recipes/misc/crafting/kinetics/super_glue.json 32086aec6acc2e236ccd1bdcad8077355cfbc801 data/create/advancements/recipes/misc/crafting/kinetics/track_observer.json 4c109779fa881db7589ced1b7816b48700ad9d17 data/create/advancements/recipes/misc/crafting/kinetics/track_observer_from_other_plates.json @@ -154,12 +167,12 @@ d05bf9eb0708fd08727414a05432119547683c82 data/create/advancements/recipes/misc/c 13c05d4a0d21a98633f332cf4e29fa9d984c2b97 data/create/advancements/recipes/misc/crafting/kinetics/train_trapdoor.json 2a765b5135e700fc7051d4b66e6be8d971445bda data/create/advancements/recipes/misc/crafting/kinetics/turntable.json 32a8453e28678b0efb9cc70cf38e72801a718793 data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearbox.json -8eca7b132f53c805ef71bbe148a4b6eb482d5d0d data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearboxfrom_conversion.json +a7c1f6598b040fa90f8e27b3c4ac5512cf124e0b data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearbox_from_conversion.json dd4849e6ac91a82a4663477dd2ea51375d184bb3 data/create/advancements/recipes/misc/crafting/kinetics/water_wheel.json 3bee8e0d4e324868eff29a6a86080d7a8656f298 data/create/advancements/recipes/misc/crafting/kinetics/weighted_ejector.json 370503ffc2272ceac8e48cabb745d9b3fd255745 data/create/advancements/recipes/misc/crafting/kinetics/whisk.json 45e1e9501b61eebec228cd2b9832103ec837f391 data/create/advancements/recipes/misc/crafting/kinetics/white_sail.json -7f4908fac450a7a8d74ad7d4fbbe970f177d272c data/create/advancements/recipes/misc/crafting/kinetics/white_sailfrom_conversion.json +49fedb2b8097c115b363021580f078a48db3bb6e data/create/advancements/recipes/misc/crafting/kinetics/white_sail_from_conversion.json 74f446a14c9b70174d2a4d59d99907322ea74c61 data/create/advancements/recipes/misc/crafting/kinetics/windmill_bearing.json 28e5044c7c9cfdefa23f9371ee995c04ecb10d2c data/create/advancements/recipes/misc/crafting/kinetics/wooden_bracket.json fddb0494d761952a22046cd17b74ff3de1e50246 data/create/advancements/recipes/misc/crafting/kinetics/wrench.json @@ -168,22 +181,41 @@ aa20a408807e09045d1f50b8c50311229272593c data/create/advancements/recipes/misc/c f3e387ae41a55cdb5ff745f40e2ddb5e2595e9b8 data/create/advancements/recipes/misc/crafting/logistics/brass_funnel.json dc61a327753684a0d8a7bcc408d656b53ac633b1 data/create/advancements/recipes/misc/crafting/logistics/brass_tunnel.json 03c367840951af268047c407b15aad52f0b094b4 data/create/advancements/recipes/misc/crafting/logistics/content_observer.json +4f8c6d91cff3e24e39847d23dc9e3015fff5fb0d data/create/advancements/recipes/misc/crafting/logistics/desk_bell.json 09454f1d4db813c89a0a2f3af966298fc5f7da7b data/create/advancements/recipes/misc/crafting/logistics/display_link.json +17a2c0315685dcb732eab1939676c95175820e54 data/create/advancements/recipes/misc/crafting/logistics/factory_gauge.json +02fd978c4f9f3c247710b052486cb498aebce95b data/create/advancements/recipes/misc/crafting/logistics/factory_gauge_clear.json +0e7dbb15985de28fd5e2e60cfbee409143fdff73 data/create/advancements/recipes/misc/crafting/logistics/item_hatch.json +fd14b161b827719d7ea709b88cb1d16adb1d5fbb data/create/advancements/recipes/misc/crafting/logistics/packager.json +375fa83a5c6f1e33ec42e2a3fa56403b4c0546f7 data/create/advancements/recipes/misc/crafting/logistics/packager_from_conversion.json +802efaee476f8be8cba6754fe584324957be76e8 data/create/advancements/recipes/misc/crafting/logistics/package_frogport.json 95b357cbac39acfbc68ac04d0d4681a4d91746ee data/create/advancements/recipes/misc/crafting/logistics/powered_latch.json ef84b382bd4f6ba9558574f2c8e63030813594e9 data/create/advancements/recipes/misc/crafting/logistics/powered_toggle_latch.json c443707391ce79dc1ec8cfacee74757b0c00bd3e data/create/advancements/recipes/misc/crafting/logistics/pulse_extender.json 77c3df89a06fc10cd8bd1cc35f0353441860ec11 data/create/advancements/recipes/misc/crafting/logistics/pulse_repeater.json +95484003dc94bb919402f72115cdbae9a4eedfb9 data/create/advancements/recipes/misc/crafting/logistics/pulse_timer.json 96b4998626e624fb79c79fb754c28b21ddc27254 data/create/advancements/recipes/misc/crafting/logistics/redstone_contact.json -1b50ed47c37e48d1112c76059574eed71ecea4e5 data/create/advancements/recipes/misc/crafting/logistics/redstone_link.json +e210638d1b198f1ce1379c88fc2f15e0c974bd09 data/create/advancements/recipes/misc/crafting/logistics/redstone_link.json +8ed69a5a2fcbc6e1cb2de901017ebd3fc3fb3dc3 data/create/advancements/recipes/misc/crafting/logistics/redstone_requester.json +cea78bc9b093a8a6a85ef1df53ddf11d9c37a114 data/create/advancements/recipes/misc/crafting/logistics/redstone_requester_clear.json +8ec1937280c6d6ba8b79de8652f3b1c588f4b4e2 data/create/advancements/recipes/misc/crafting/logistics/repackager_from_conversion.json 831588b3f29411d5c4b358006051152eb2b23e6b data/create/advancements/recipes/misc/crafting/logistics/stockpile_switch.json +2408cdbac7edb7857223d716e466ed6d16dd50ee data/create/advancements/recipes/misc/crafting/logistics/stock_link.json +972ce787e625ad95588ba1fdd36098173798f198 data/create/advancements/recipes/misc/crafting/logistics/stock_link_clear.json +d4b4da954149a3ab94966639b1fbfb7f3820c3a1 data/create/advancements/recipes/misc/crafting/logistics/stock_ticker.json +1e0fc9f4971286a69d9706006bd8358931382c9c data/create/advancements/recipes/misc/crafting/logistics/stock_ticker_clear.json cb416511a219d2bc5806c6880c01820a8b563b80 data/create/advancements/recipes/misc/crafting/materials/andesite_alloy.json 3b65a04da4e16442bfa8accfe209b7c5342b1db9 data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_block.json 2715b888b6d96ee4c7208af21bb4dfb1a1bd544c data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_from_block.json 2ca100aa71cc3419c47d1028f5c77aa9387ab216 data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_from_zinc.json +652779172d0058cfe3d380a0462a71f82e6dd91c data/create/advancements/recipes/misc/crafting/materials/bound_cardboard_block.json 47e965b7ba2b12000efcf6f9090b5622833cc9ab data/create/advancements/recipes/misc/crafting/materials/brass_block_from_compacting.json 8aa51bd8685a70f200506d3efd4e73ce9b2d7370 data/create/advancements/recipes/misc/crafting/materials/brass_ingot_from_compacting.json 9e703c5fa1bd44eb6581e745f06923d40126ada4 data/create/advancements/recipes/misc/crafting/materials/brass_ingot_from_decompacting.json 4cb9d1fc5289b11df4610a85aa2cd67877556b32 data/create/advancements/recipes/misc/crafting/materials/brass_nugget_from_decompacting.json +f07788c42f4c49d0b4fc7253742d95e94bd5346d data/create/advancements/recipes/misc/crafting/materials/cardboard_block.json +86439f388e88fe56d3931ab46fce5a111b2c15f4 data/create/advancements/recipes/misc/crafting/materials/cardboard_from_block.json +fa758dda053e4e0f44fe234026417124594b0e63 data/create/advancements/recipes/misc/crafting/materials/cardboard_from_bound_block.json ffcd3f0339794c782a8be8434cd79de15d0ab3cc data/create/advancements/recipes/misc/crafting/materials/copper_ingot.json 58c23978d7222951cba2bbf3020cd0c2c6f85ac9 data/create/advancements/recipes/misc/crafting/materials/copper_nugget.json d4879e7721bdbb6c7029ac88ff5684acec8223d6 data/create/advancements/recipes/misc/crafting/materials/electron_tube.json @@ -193,9 +225,10 @@ aa2067bedd73d45dcf4bf2c1a30d227d4de4f57d data/create/advancements/recipes/misc/c 06a3797c9c16641e05a257980a6afc522d2635b5 data/create/advancements/recipes/misc/crafting/materials/raw_zinc_block.json 59018ba1b05242dfc25d5de72fcff572ab18d424 data/create/advancements/recipes/misc/crafting/materials/red_sand_paper.json 03560f4fe648ea51160efaff89d3b7ef0cd87d69 data/create/advancements/recipes/misc/crafting/materials/rose_quartz.json -5aeaf7bdfb4a8abec97af7b055ea9209221fef9d data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tilesfrom_conversion.json +4fb6101ff037b9da3f030729dd991dab4c934267 data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tiles_from_conversion.json 489c20709121bfe0408566b0b89dfa685efef8e4 data/create/advancements/recipes/misc/crafting/materials/sand_paper.json -4fa119d82266d6b8390433842d610effb1a8ace1 data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tilesfrom_conversion.json +6cd07e204c574b1419ba81cfffc1967a1c7d4f75 data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tiles_from_conversion.json +dc1e07242564e81694f151cecfc2b6115e5862ca data/create/advancements/recipes/misc/crafting/materials/transmitter.json 0d60ad8d0436ed33a8013616390ca5e970e042ee data/create/advancements/recipes/misc/crafting/materials/zinc_block_from_compacting.json 8b9692de75d0c1d694bb3a2ce2316200ef3ff197 data/create/advancements/recipes/misc/crafting/materials/zinc_ingot_from_compacting.json dd7c250fa8e41cbaae65754f38b8861397718ae4 data/create/advancements/recipes/misc/crafting/materials/zinc_ingot_from_decompacting.json @@ -273,6 +306,13 @@ b3c4585dc6ed9c4a38d7923ae399b88ab8912df9 data/create/recipes/blasting/zinc_ingot 23077aeccd8712038ef04542713c2b365765346d data/create/recipes/blasting/zinc_ingot_from_raw_ore.json 785636ad3752d7a78059757d7ba21118be2a3289 data/create/recipes/campfire_cooking/bread.json 208487a2d020c2603391f55e815a39a28f8fd9e8 data/create/recipes/crafting/appliances/attribute_filter_clear.json +dad85e5945795a3f61f5e6b2bb13c36cf11a3966 data/create/recipes/crafting/appliances/book.json +1c507eb168fa55354e26b76704012ae85fed5edb data/create/recipes/crafting/appliances/cardboard_boots.json +b42fe3c262a33657b098b036ae0864af988b9f10 data/create/recipes/crafting/appliances/cardboard_chestplate.json +efbfccade226b34d22abb77138dab8726725752e data/create/recipes/crafting/appliances/cardboard_helmet.json +1f49a67c1698a56cfd017a9e89a17c640052e1e3 data/create/recipes/crafting/appliances/cardboard_leggings.json +c063d8143b5f93b258b2e5ce7c8b828af6a49e93 data/create/recipes/crafting/appliances/cardboard_sword.json +cbd0357cfa7afdd877b6e772cad34df7e19a2ad3 data/create/recipes/crafting/appliances/chain_from_zinc.json 66c24da136abee4521d788df83f55b1c224d19fe data/create/recipes/crafting/appliances/clipboard.json 28d1dabd689b855964151100a80247b2ea150bd4 data/create/recipes/crafting/appliances/clipboard_clear.json 97932adf38574c2baf0ed2d5e3d62e7514e0c2bf data/create/recipes/crafting/appliances/copper_backtank.json @@ -281,18 +321,22 @@ c500139f545fea4568575b93b1ab9e56f004f137 data/create/recipes/crafting/appliances 3e3f71d579ec7453e453d5b65aaee3c43169b679 data/create/recipes/crafting/appliances/crafting_blueprint.json b7c8f3c5e80749c6c38d5c0153dc68a79c32535f data/create/recipes/crafting/appliances/dough.json 409b5d70ee1ef9164c327d79472e6d66ce55dec6 data/create/recipes/crafting/appliances/filter_clear.json +854f7efc8724f733ed7f4ac08c1d252cf949512d data/create/recipes/crafting/appliances/item_frame.json 265ead7993ae9e9b617dbfae749a77fed6b7b1ba data/create/recipes/crafting/appliances/linked_controller.json +48c48579dda926b348ba56b8b640436cb81650bf data/create/recipes/crafting/appliances/name_tag.json 32d4ba22e5133284793b4854f1a6798dd1f50ea0 data/create/recipes/crafting/appliances/netherite_backtank.json de4c3f66e8664c607900c672ee1c20d3442fdebc data/create/recipes/crafting/appliances/netherite_backtank_from_netherite.json b5b29558d4efe161f6edaeae2c449735d46261ca data/create/recipes/crafting/appliances/netherite_diving_boots.json 5a6d3e59e8fa623b147600cae7065e22af9c2cbf data/create/recipes/crafting/appliances/netherite_diving_boots_from_netherite.json 5eae779a8c16a4efb8fa61996c608bc44c55da7f data/create/recipes/crafting/appliances/netherite_diving_helmet.json 26eec27acd056e62510bc831cc6e6823a45c51b8 data/create/recipes/crafting/appliances/netherite_diving_helmet_from_netherite.json +bbf63119e3ee54afd49fe2ccfe2c06baaa9f6f41 data/create/recipes/crafting/appliances/package_filter_clear.json 0b83c52c90948141e5807b7d1243fb5d48d4c998 data/create/recipes/crafting/appliances/schedule_clear.json 05e4700f7fd59029ba19bcfb7b49fd3a30a93cad data/create/recipes/crafting/appliances/slime_ball.json d0bad974476c54315e4b656c67dbf6165d183bbc data/create/recipes/crafting/appliances/tree_fertilizer.json 5b499ce4eee741d17813f96274333abfa2de99a9 data/create/recipes/crafting/curiosities/brown_toolbox.json 05eb422734dcdd4c499437ae564e73af5c2e4673 data/create/recipes/crafting/curiosities/cake.json +b961ce60986ebfed1b0cc0f7053d6e558de13e86 data/create/recipes/crafting/curiosities/item_copying.json c3444000827e1f9553818dedec6d3dba4af9dfcd data/create/recipes/crafting/curiosities/minecart_coupling.json 1323b7c6d30d4e343e010902b7ebbfa2590a4cf5 data/create/recipes/crafting/curiosities/peculiar_bell.json e54646485af774e490409e9912a3799f7ac44e01 data/create/recipes/crafting/curiosities/toolbox_dyeing.json @@ -305,6 +349,7 @@ ea6479a3cb257bfe0bfaac380973ed068195620e data/create/recipes/crafting/kinetics/a 989bd8580e18c716d588fbf3cf863ea238fffee8 data/create/recipes/crafting/kinetics/brass_door.json a2e433b367baf9df12ced3a99c38940d67450440 data/create/recipes/crafting/kinetics/brass_hand.json 3c7cacaace022bd8b40e92d1e7ce0b371ed822d5 data/create/recipes/crafting/kinetics/cart_assembler.json +06c11a79bfcaf40e93216b84e6e78884f8ca18e3 data/create/recipes/crafting/kinetics/chain_conveyor.json d0ac43c060418f273245316d62b4d87651d76c78 data/create/recipes/crafting/kinetics/chute.json e51a22443987fdddbc7b3e48ca07fd341811f0e9 data/create/recipes/crafting/kinetics/clockwork_bearing.json de55cc506471580096b73c66e14d0d1de2c01f11 data/create/recipes/crafting/kinetics/clutch.json @@ -323,6 +368,7 @@ d26d0a2f3836bdc92f9c43913acac2a93d713976 data/create/recipes/crafting/kinetics/d 03bf164f5332018731ac6b216b4f50baed3211bd data/create/recipes/crafting/kinetics/elevator_pulley.json 59278e0e0e75eb1c0f926bc90e19edfda5993261 data/create/recipes/crafting/kinetics/empty_blaze_burner.json ca3e3063cdf135426e28d3474b5289ba1c5d9a1d data/create/recipes/crafting/kinetics/encased_chain_drive.json +1b470cc502f95473da205218bcf7ea1a2354ded2 data/create/recipes/crafting/kinetics/encased_chain_drive_from_zinc.json 7bb683f2398124b62595d6aa0afbdcde80acc028 data/create/recipes/crafting/kinetics/encased_fan.json 6c3a8f04e52a82c675c76963701244c78553cd32 data/create/recipes/crafting/kinetics/filter.json 871fae440820ae1145a86fe2d14a191b81bcd85f data/create/recipes/crafting/kinetics/fluid_pipe.json @@ -336,7 +382,7 @@ be87c0108dae97d6bcb637715749b96fbc656002 data/create/recipes/crafting/kinetics/f 5ee1c8ad641287e649fd56505e673f37c16089fa data/create/recipes/crafting/kinetics/gantry_carriage.json f9550471dcd0e446034d0c7010779ec10247ccf8 data/create/recipes/crafting/kinetics/gantry_shaft.json 32baae49676966ef04019c6c54e2e8363a23d883 data/create/recipes/crafting/kinetics/gearbox.json -a98b568daee4051397176d2fa2b6b2992b412a52 data/create/recipes/crafting/kinetics/gearboxfrom_conversion.json +a98b568daee4051397176d2fa2b6b2992b412a52 data/create/recipes/crafting/kinetics/gearbox_from_conversion.json 096d09e6021e0c47f9daa259c0a9200ff36b3fbb data/create/recipes/crafting/kinetics/gearshift.json 18d983aaef9e32073ec656e60855cd2d56ef168f data/create/recipes/crafting/kinetics/goggles.json bc69dfe59b369eead6f3da593eae5a107933d339 data/create/recipes/crafting/kinetics/hand_crank.json @@ -347,7 +393,7 @@ ef525f4a19bc17fdfdd73c1e7ad65da0c8423b59 data/create/recipes/crafting/kinetics/l 04a9cd133f7e1f88a35653ea205bb5a7e63cbecd data/create/recipes/crafting/kinetics/large_cogwheel_from_little.json b24ff0cffeb7c69e3c8f6fdc55e88e8067454142 data/create/recipes/crafting/kinetics/large_water_wheel.json 984f2dcd5d43959f5830231fbf0f535de9fb4b41 data/create/recipes/crafting/kinetics/linear_chassis.json -27944146a510a98193140b5bed5feef2c05c8014 data/create/recipes/crafting/kinetics/linear_chassisfrom_conversion.json +27944146a510a98193140b5bed5feef2c05c8014 data/create/recipes/crafting/kinetics/linear_chassis_from_conversion.json d3c5afadd966993262a89cad0c6892bacf15f4e0 data/create/recipes/crafting/kinetics/mechanical_arm.json 68ccedb968fb15507f553eba8e0f38730209c076 data/create/recipes/crafting/kinetics/mechanical_bearing.json 355d65ca635d657423dab36c22bfb6cdb6c66d67 data/create/recipes/crafting/kinetics/mechanical_crafter.json @@ -367,6 +413,7 @@ dfd470b78af59f937893e71b6545e1ef0b05950e data/create/recipes/crafting/kinetics/m 768c1afbd543a11b1b7c029c8c58c9c02c360a19 data/create/recipes/crafting/kinetics/mysterious_cuckoo_clock.json c3463cbc2b2305b5f3ac28950c8deaead6838814 data/create/recipes/crafting/kinetics/nixie_tube.json 8384b63525d3412a00dbc8f4cd61b4f585d67c1d data/create/recipes/crafting/kinetics/nozzle.json +79cb0e11b402636391ce889b02fca1f961c8b317 data/create/recipes/crafting/kinetics/package_filter.json d1cc2faa5dc722f435008ad93e9e27e932607690 data/create/recipes/crafting/kinetics/piston_extension_pole.json a653f85993ea7749beb57c93ebbe29aa2634e2ef data/create/recipes/crafting/kinetics/placard.json 041369b6aaca1cf870f970fd9d505b812f4e3c0b data/create/recipes/crafting/kinetics/portable_fluid_interface.json @@ -376,21 +423,21 @@ fa58c3eeca2d2cd2a42a60f8e72021288773d20f data/create/recipes/crafting/kinetics/r d772312c83aff31d1fc27156e254cb95fd27fc2c data/create/recipes/crafting/kinetics/rope_pulley.json bb59333590f4408750a8e86ab6dabb4f8ea145ac data/create/recipes/crafting/kinetics/rose_quartz_lamp.json 42d334d81633d5f346b7e0c5005c1811fed293d9 data/create/recipes/crafting/kinetics/rotation_speed_controller.json -faaa02462c428daeefc7bc2d32d491afa49128c3 data/create/recipes/crafting/kinetics/sail_framefrom_conversion.json +faaa02462c428daeefc7bc2d32d491afa49128c3 data/create/recipes/crafting/kinetics/sail_frame_from_conversion.json dda3e44d83e8e2e4c45eda27758fc6f87118eb9d data/create/recipes/crafting/kinetics/schedule.json -0f3f10a756d32e438fdb51fb1e6d00ee1c05bc3f data/create/recipes/crafting/kinetics/secondary_linear_chassisfrom_conversion.json +0f3f10a756d32e438fdb51fb1e6d00ee1c05bc3f data/create/recipes/crafting/kinetics/secondary_linear_chassis_from_conversion.json a282f8e372b14819c20319736a52506f508f9c17 data/create/recipes/crafting/kinetics/sequenced_gearshift.json b80b9bf1a36aab395cdd6200bcd3497c8e693ce1 data/create/recipes/crafting/kinetics/shaft.json a1d7e73399044cab19fd564d71d5fdfa754181ae data/create/recipes/crafting/kinetics/smart_chute.json 31698b810c00c5bff2b213d465614bbde2cae2aa data/create/recipes/crafting/kinetics/smart_fluid_pipe.json 001868b8959c6d1583daa08ce7098a0bda349d08 data/create/recipes/crafting/kinetics/speedometer.json -fcd251937ad8ec78213d8d4277fefff3ae998061 data/create/recipes/crafting/kinetics/speedometerfrom_conversion.json +fcd251937ad8ec78213d8d4277fefff3ae998061 data/create/recipes/crafting/kinetics/speedometer_from_conversion.json 4549864bccf0fafeb190fe0fc0427c1feb6602cb data/create/recipes/crafting/kinetics/spout.json ff9fa17b98d37c1814962fafb1ca60f07a3d0e8f data/create/recipes/crafting/kinetics/steam_engine.json 2b24f72c4d33d035db32005ff72623a61819ddcf data/create/recipes/crafting/kinetics/steam_whistle.json 87c25c7aa34b699586696344c83cdc181a93761c data/create/recipes/crafting/kinetics/sticker.json 19cc465a5e738785e91e2663f1b0c0e03f656b3a data/create/recipes/crafting/kinetics/sticky_mechanical_piston.json -27879de3fe0dbea5e4b6cec110459ce01cfa2556 data/create/recipes/crafting/kinetics/stressometerfrom_conversion.json +27879de3fe0dbea5e4b6cec110459ce01cfa2556 data/create/recipes/crafting/kinetics/stressometer_from_conversion.json 1fd12eac975ce2ffb6212e25f2309ad08537a4b6 data/create/recipes/crafting/kinetics/super_glue.json ae836d3103b16bb7084109c4d25295f0a3bc6f7c data/create/recipes/crafting/kinetics/track_observer.json 1747771e1eb570c0cfdc97681d8b9d0ccb1db73d data/create/recipes/crafting/kinetics/track_observer_from_other_plates.json @@ -400,12 +447,12 @@ af645fe446e0df755fb748383a51facbe9101ede data/create/recipes/crafting/kinetics/t 26d9401533332cbc7580b32b45cdebf6ad3c523d data/create/recipes/crafting/kinetics/train_trapdoor.json a02e799451c8051250ab077ee94bec8f17705d5f data/create/recipes/crafting/kinetics/turntable.json c2644263571eb8a14ed535c1e88924a6098e2e6f data/create/recipes/crafting/kinetics/vertical_gearbox.json -613d2ef5c381445d9a0bb1020f9d0ab9fb04d766 data/create/recipes/crafting/kinetics/vertical_gearboxfrom_conversion.json +613d2ef5c381445d9a0bb1020f9d0ab9fb04d766 data/create/recipes/crafting/kinetics/vertical_gearbox_from_conversion.json af2fc528dacef0300115977c681976b793329c8d data/create/recipes/crafting/kinetics/water_wheel.json 97054ad290c974f60d9be41c642e661442a98bca data/create/recipes/crafting/kinetics/weighted_ejector.json 9ab4fa87c54b6580d3f7a1f8be8790c8f30f41fa data/create/recipes/crafting/kinetics/whisk.json 7a933e80436c256804e8e448e954399933ccdcf4 data/create/recipes/crafting/kinetics/white_sail.json -9c7a4511aa52c4ab80ff692f0d7eca5cbf3fc470 data/create/recipes/crafting/kinetics/white_sailfrom_conversion.json +9c7a4511aa52c4ab80ff692f0d7eca5cbf3fc470 data/create/recipes/crafting/kinetics/white_sail_from_conversion.json 2e1e7414ec81f21640efb72f74eec8b4f6e9e105 data/create/recipes/crafting/kinetics/windmill_bearing.json 04162aed9da6d5c8f5da33d041d95c960bd743f8 data/create/recipes/crafting/kinetics/wooden_bracket.json 4818f756d9198fe17a27176c51fda90a830504e7 data/create/recipes/crafting/kinetics/wrench.json @@ -414,22 +461,41 @@ e18098af26d3e0d28fb7f2ac49379787384f0d03 data/create/recipes/crafting/logistics/ a24f11d979f40994b9f881b0f49fff5d93185296 data/create/recipes/crafting/logistics/brass_funnel.json d994ef262b16357984d3ed62f6563d2f37266193 data/create/recipes/crafting/logistics/brass_tunnel.json 0b18d9964f2d580eb465cc72208f7a7fdba7b63e data/create/recipes/crafting/logistics/content_observer.json -cc837e8b014c121ed9d959baddea134ebf669350 data/create/recipes/crafting/logistics/display_link.json +4f3ce7533d77e5bcab8da815d0fd5d41c95efe4e data/create/recipes/crafting/logistics/desk_bell.json +5ed926477160d18871cce4306da2f8d4ae17f7e5 data/create/recipes/crafting/logistics/display_link.json +4daadd2c67fe8bbf5594fb50dcf051dad7f9997a data/create/recipes/crafting/logistics/factory_gauge.json +2fb7722137990b9b9be967a1f766e138678d0573 data/create/recipes/crafting/logistics/factory_gauge_clear.json +f3ba21e8979256fb78cd618ac4f1082b0b2f9e0c data/create/recipes/crafting/logistics/item_hatch.json +7d66c3b5d704f583e32617b37620e749462eaa1f data/create/recipes/crafting/logistics/packager.json +6b51fa6a5bd1e9dc8e7387269d985cd622ab8ada data/create/recipes/crafting/logistics/packager_from_conversion.json +6852cb8ff6916981920ab9c987c6e357e9236511 data/create/recipes/crafting/logistics/package_frogport.json dd28b63ceb46a1e9071549c4f8ff32f520c667f6 data/create/recipes/crafting/logistics/powered_latch.json 9ee6e19644928dc78e6f8a5e59f30cd42ac3e454 data/create/recipes/crafting/logistics/powered_toggle_latch.json aa8a704ad643ff5f06db34f4047f7f740a556236 data/create/recipes/crafting/logistics/pulse_extender.json 8b0b342baa18cc47c7a60a3c9812fece28210cf6 data/create/recipes/crafting/logistics/pulse_repeater.json +ade2e66f03bab8843e2dff82b0f04ca92fff956e data/create/recipes/crafting/logistics/pulse_timer.json c81f852f1d1514184ff235e790a6ca907f7b6ad4 data/create/recipes/crafting/logistics/redstone_contact.json -00877e6b56f28d8691080ef18b654f0a141835ce data/create/recipes/crafting/logistics/redstone_link.json +ae3ce2ea0f938b65c875b5c227adc0cb93b8adde data/create/recipes/crafting/logistics/redstone_link.json +06670fd44389b2b1755c80d02898a68c7c490620 data/create/recipes/crafting/logistics/redstone_requester.json +8446b3ca07575ea978ddde4121900207d54be8b3 data/create/recipes/crafting/logistics/redstone_requester_clear.json +e156e092a9c719e91cd62e23f8ee2201dce4c2a8 data/create/recipes/crafting/logistics/repackager_from_conversion.json eff0d37e98e8badd8d2c3c9de17ee5560b110dbd data/create/recipes/crafting/logistics/stockpile_switch.json +8f8e7800431590b06f287fc6a24389ec71fc3eb4 data/create/recipes/crafting/logistics/stock_link.json +e19544e2ef88a4d10f6dc8a3a973793cb00085ba data/create/recipes/crafting/logistics/stock_link_clear.json +d4671c9d3c654aadd3fd238dfaa6939587f8a81b data/create/recipes/crafting/logistics/stock_ticker.json +38aa7b9b3c4724ec8b8d94f00a98d684110ad5ca data/create/recipes/crafting/logistics/stock_ticker_clear.json ac524c110f66a7433208a888c5f3bb69e5e95743 data/create/recipes/crafting/materials/andesite_alloy.json e6bb68a1d2ed5a629c83f5a0eefb843bb890736d data/create/recipes/crafting/materials/andesite_alloy_block.json eebacb477bcce876622173289b06e1ad21424686 data/create/recipes/crafting/materials/andesite_alloy_from_block.json 5008707e622c0fa0b6df32da5da7230a4da574ca data/create/recipes/crafting/materials/andesite_alloy_from_zinc.json +ba8ec9cb0894132cd4e0d14322a388c061706a29 data/create/recipes/crafting/materials/bound_cardboard_block.json f9f94e5082e7971e55b25bc00ba86c3579b492aa data/create/recipes/crafting/materials/brass_block_from_compacting.json ecd8581ad4a04cc1217133363bd15d76129cb651 data/create/recipes/crafting/materials/brass_ingot_from_compacting.json fe2f3c0722aa0f6b41ad0f497b9742eb856c0dd0 data/create/recipes/crafting/materials/brass_ingot_from_decompacting.json 941b2c1007c4b3afb6e141a754141de1b1c9a43a data/create/recipes/crafting/materials/brass_nugget_from_decompacting.json +4c92a1eadc2e5dfba9e871537671702ccf35368a data/create/recipes/crafting/materials/cardboard_block.json +cb1188148d18e456cecd33279aaf695787ddbf74 data/create/recipes/crafting/materials/cardboard_from_block.json +00d637b64b6dfa18be86cb921f920a63bacb096d data/create/recipes/crafting/materials/cardboard_from_bound_block.json d4d6664d05c7406b4f839413d4e3c60cf0347fb7 data/create/recipes/crafting/materials/copper_ingot.json 4863d3feda514d414962c1947abaa232ab3f6cd5 data/create/recipes/crafting/materials/copper_nugget.json 66c0b1d060395826c4a45082a03295b5df450801 data/create/recipes/crafting/materials/electron_tube.json @@ -439,9 +505,10 @@ bc0a0b576a8895c5e31374cd3e6f9f2c8e20d542 data/create/recipes/crafting/materials/ e89aa3ab801e3ce25387ae67c5e47bab518b9225 data/create/recipes/crafting/materials/raw_zinc_block.json 388654485ad957c58c4d6019273a85cebd468cca data/create/recipes/crafting/materials/red_sand_paper.json 712255438e212e37cad4bbf65b995385d37b3ce1 data/create/recipes/crafting/materials/rose_quartz.json -46cb889dd23d9a8a47f8b340abcbdbec35b21ee3 data/create/recipes/crafting/materials/rose_quartz_tilesfrom_conversion.json +46cb889dd23d9a8a47f8b340abcbdbec35b21ee3 data/create/recipes/crafting/materials/rose_quartz_tiles_from_conversion.json cde25f253da4d9800fd8f879a7d208e40510df82 data/create/recipes/crafting/materials/sand_paper.json -39d9f3238bffd32a0bbe85f300bee0c71161f2df data/create/recipes/crafting/materials/small_rose_quartz_tilesfrom_conversion.json +39d9f3238bffd32a0bbe85f300bee0c71161f2df data/create/recipes/crafting/materials/small_rose_quartz_tiles_from_conversion.json +909cb6ddb17b7db28d2c67c18762444feb3bfe2b data/create/recipes/crafting/materials/transmitter.json 24c99b98a2acb744a05f9ff4f22b783689e2b2f9 data/create/recipes/crafting/materials/zinc_block_from_compacting.json 5effb47ad68c8bacc4b1984a37b63ae3b02b3e88 data/create/recipes/crafting/materials/zinc_ingot_from_compacting.json 2636700eda7f06a9297af688c8b7963b2611ea42 data/create/recipes/crafting/materials/zinc_ingot_from_decompacting.json diff --git a/src/generated/resources/.cache/ad9bf59631726a3f24738ebf1a6cd44c7f88ba0f b/src/generated/resources/.cache/ad9bf59631726a3f24738ebf1a6cd44c7f88ba0f index 65eee720eb..af39d392c6 100644 --- a/src/generated/resources/.cache/ad9bf59631726a3f24738ebf1a6cd44c7f88ba0f +++ b/src/generated/resources/.cache/ad9bf59631726a3f24738ebf1a6cd44c7f88ba0f @@ -1,4 +1,4 @@ -// 1.20.1 2024-10-09T12:24:59.2656887 Create's Damage Type Tags +// 1.20.1 2025-02-02T11:59:39.5960908 Create's Damage Type Tags 7884716b2f4bb1330ff215366bb4bab06e4728c2 data/minecraft/tags/damage_type/bypasses_armor.json 1fcad1f89265fba8bdb05b03a1dfcc88d7b7a550 data/minecraft/tags/damage_type/is_explosion.json 08324c61115b72bb8a6370d7f34d84d9a31afd16 data/minecraft/tags/damage_type/is_fire.json diff --git a/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 b/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 index ce1e4f80e5..d4eeb07047 100644 --- a/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 +++ b/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 @@ -1,4 +1,4 @@ -// 1.20.1 2024-12-15T23:26:23.3573034 Create's Processing Recipes +// 1.20.1 2025-02-09T10:52:38.3168881 Create's Processing Recipes 3c94326fb730f68c1e44fe1e2ef09c9db6ffd92b data/create/recipes/compacting/andesite_from_flint.json 8d3d5b31f3601b9f681ff710e0545a483a1494c6 data/create/recipes/compacting/blaze_cake.json 8bd7f4e3a686ab520b2d55594d2018d0e9a50c91 data/create/recipes/compacting/chocolate.json @@ -54,6 +54,9 @@ c9f6c53c34c4891a245dd9515eb573b40b4f3e0b data/create/recipes/crushing/compat/exn 0fedb41388b4f04e544f45d7182d91b2e9230bc6 data/create/recipes/crushing/compat/galosphere/allurite.json 9e255904c7a3277d6084183c0921392df0c7918d data/create/recipes/crushing/compat/galosphere/amethyst.json b04f95c02f37a0398c209a02ad08a8b0e9aaaaa9 data/create/recipes/crushing/compat/galosphere/lumiere.json +0e812bd72411b42378fe29efa31a11f087d57e2e data/create/recipes/crushing/compat/immersiveengineering/coal_coke.json +02bcdd13739c05df6e8cb49908a0103ce8ec896b data/create/recipes/crushing/compat/immersiveengineering/coke_block.json +113b6dcce9801ee18d5771855c3750c1358f9c65 data/create/recipes/crushing/compat/immersiveengineering/slag.json bea05bc584958f479078cd6c16a06c50eae859cc data/create/recipes/crushing/compat/neapolitan/ice.json 2358ce4b7a3acb08d3d0a3e64295fb97dea2ec02 data/create/recipes/crushing/compat/quark/moss_block.json f900b850c6202c0445bdfcb4eb69d8e18dce5d26 data/create/recipes/crushing/compat/silentgems/alexandrite_end_ore.json @@ -203,19 +206,9 @@ e4cdcc67baffa90e27a73a2ba59ec92b323e1d4f data/create/recipes/crushing/veridium.j bfd5baa72a48ef29c3141b57a88f5ead0f723614 data/create/recipes/crushing/veridium_recycling.json b135e3faf6afef4b6a5f00197997b47ff8e90568 data/create/recipes/crushing/wool.json 931a66992ccb5accdb435dca6fe6532e86250c0d data/create/recipes/crushing/zinc_ore.json -b5c33d039e3c9771b3ffc322aadae7e75a823635 data/create/recipes/cutting/acacia_log.json -b45b88bf2ac614b2518437656746f8e8a465d693 data/create/recipes/cutting/acacia_wood.json cdb26cd91feeda5901f31f57c16517dda5287810 data/create/recipes/cutting/andesite_alloy.json 5afeada82e71eb5012e35725821792f64d92a6b3 data/create/recipes/cutting/bamboo_block.json 4ac4bb94de7b25a3eec85e8290ab5f2f6b2b4167 data/create/recipes/cutting/bamboo_planks.json -1a3dd0e51603a3e47da4465da210004c78028faf data/create/recipes/cutting/birch_log.json -71c3a093c849a99fbaef8772114ac9305627f2c1 data/create/recipes/cutting/birch_wood.json -31a1713f8bc5577b3fcf2fcfd2d42dac145f9560 data/create/recipes/cutting/cherry_log.json -0f54293540ad75e6395452253f4ab5c8e5166e93 data/create/recipes/cutting/cherry_wood.json -4f756e256a7814e2b9a6632d38633bb78c5046cd data/create/recipes/cutting/compat/architects_palette/stripped_twisted_log.json -310dfb6c7e7649c0ede306fda71459e7f2bc8c7e data/create/recipes/cutting/compat/architects_palette/stripped_twisted_wood.json -8645e8ee47b0a6a432f85b7f2e07957e21adeb70 data/create/recipes/cutting/compat/architects_palette/twisted_log.json -085c2e98ccd55576f4948bccfda443ff3d95824b data/create/recipes/cutting/compat/architects_palette/twisted_wood.json 60a64dc871d6b23274e01edfa9cdd331aa4365c9 data/create/recipes/cutting/compat/ars_nouveau/blue_archwood_log.json e4c23f6502bae92d3baa1845da87073e1719938e data/create/recipes/cutting/compat/ars_nouveau/blue_archwood_wood.json 1ff887f11099b4536bf6fad3e407a37e83d3bfca data/create/recipes/cutting/compat/ars_nouveau/green_archwood_log.json @@ -232,489 +225,66 @@ af1ca00e05d554bba1d85c766e52560d5ea8fe4d data/create/recipes/cutting/compat/ars_ 1a66e7e6dfba9531bbb5a1d0bf014e16d6cbb6be data/create/recipes/cutting/compat/ars_nouveau/stripped_purple_archwood_wood.json 5c1c8275b2e30fdf387dcf358fd41e995e817c86 data/create/recipes/cutting/compat/ars_nouveau/stripped_red_archwood_log.json 9dc5bd8a1002b9d299d60a405720950eb0b4e9ab data/create/recipes/cutting/compat/ars_nouveau/stripped_red_archwood_wood.json -08337ca1d46e04197fa31ccc21c3fcbbc0efde5a data/create/recipes/cutting/compat/atmospheric/aspen_log.json -1077e644ee8e83e39dbd695e5ed7b12591aedcfa data/create/recipes/cutting/compat/atmospheric/aspen_wood.json -339cc9026c5d89c8b78283baf5f21cb8b4471bad data/create/recipes/cutting/compat/atmospheric/grimwood.json -a8c2ff06f663881b1edbf7eab5e91083e59cf568 data/create/recipes/cutting/compat/atmospheric/grimwood_log.json -16640492eab4c22bf18e06fdf7a0469e1326f10b data/create/recipes/cutting/compat/atmospheric/kousa_log.json -0f2b8fa779cd3bc6e2ac04aa16596e08bda29578 data/create/recipes/cutting/compat/atmospheric/kousa_wood.json -0689201dddce046ef830ae791dc614ebcd6bb26d data/create/recipes/cutting/compat/atmospheric/morado_log.json -f3968dddde6ace179c0b6463aba17e212a93629a data/create/recipes/cutting/compat/atmospheric/morado_wood.json -41bb788e28c66d8a7415ec3731ca09f440864a9a data/create/recipes/cutting/compat/atmospheric/rosewood.json -4c49e3ac52fd466929a63e5009dce631040ba6ba data/create/recipes/cutting/compat/atmospheric/rosewood_log.json -a90a322d3acc2115e9a52c0e288215991c5ed143 data/create/recipes/cutting/compat/atmospheric/stripped_aspen_log.json -482e9a0464c877c21cf37925e20b6aeff633676c data/create/recipes/cutting/compat/atmospheric/stripped_aspen_wood.json -2d05a0460606960c7e73d2a67012b7dc55c00356 data/create/recipes/cutting/compat/atmospheric/stripped_grimwood.json -c2bfa5fa40905cb3bd2511d94907252e86afe7b8 data/create/recipes/cutting/compat/atmospheric/stripped_grimwood_log.json -092cae4bd9d8dd5626fd4b5c072520977dfa8a4e data/create/recipes/cutting/compat/atmospheric/stripped_kousa_log.json -cc69f0162e8fdd56e2e6a8d3423acd09a977f56d data/create/recipes/cutting/compat/atmospheric/stripped_kousa_wood.json -e9d88cf3cd60e6d43af7d1d16a174f88fcf1233d data/create/recipes/cutting/compat/atmospheric/stripped_morado_log.json -5f55e43d57c00b48c010609da73e7aa009f6c49a data/create/recipes/cutting/compat/atmospheric/stripped_morado_wood.json -ecfda5a9474fda3772c4cdfbe213c1350ed9ee38 data/create/recipes/cutting/compat/atmospheric/stripped_rosewood.json -c4e9a1327e2926f0517feaaf39c9629da8629312 data/create/recipes/cutting/compat/atmospheric/stripped_rosewood_log.json -924b4b9d24d2544aa04e7a713e6ce4674450b616 data/create/recipes/cutting/compat/atmospheric/stripped_yucca_log.json -ec6c644a9381526ea5c507a1968627fc880041ac data/create/recipes/cutting/compat/atmospheric/stripped_yucca_wood.json -c528538d50280aa575d642076b4d82e905cd5742 data/create/recipes/cutting/compat/atmospheric/yucca_log.json -fa41576ce1f7524bcd5c9d0bd755872c61594906 data/create/recipes/cutting/compat/atmospheric/yucca_wood.json -bca0cb14b60f7982d3e25f1fa082fc6c1d297cac data/create/recipes/cutting/compat/autumnity/maple_log.json -d95f86b26b21356ce3a9305d31143984489bd044 data/create/recipes/cutting/compat/autumnity/maple_wood.json -b66953dee0ea9804e22aa6f296c49e81f34d2d18 data/create/recipes/cutting/compat/autumnity/sappy_maple_log.json -bf5a4170f365901a3d850387ff6338e576f8e8eb data/create/recipes/cutting/compat/autumnity/sappy_maple_wood.json -598201da89849526cc316b63b297814bc52d75d1 data/create/recipes/cutting/compat/autumnity/stripped_maple_log.json -b93e929d2078211fd70d6df8d4eb065e6d4cc112 data/create/recipes/cutting/compat/autumnity/stripped_maple_wood.json -76872508fd1b302d4e94a2017ea72f7d38de6273 data/create/recipes/cutting/compat/biomesoplenty/dead_log.json -6bee03a37457acfc937c36ffb2d58ca97218c002 data/create/recipes/cutting/compat/biomesoplenty/dead_wood.json -c62f06b79bdac37704f0fa31459f98aeb2d4f7ae data/create/recipes/cutting/compat/biomesoplenty/fir_log.json -530425aed6c6acd1463f17e88aba7794118758a1 data/create/recipes/cutting/compat/biomesoplenty/fir_wood.json -e88e60e59fe0eb3118b00b02af9e529c866785d3 data/create/recipes/cutting/compat/biomesoplenty/hellbark_log.json -6997475ab7fb0c489188749447a0212d5facc1ca data/create/recipes/cutting/compat/biomesoplenty/hellbark_wood.json -4838e37981d65e3a732e320fd75f8e4762271ef9 data/create/recipes/cutting/compat/biomesoplenty/jacaranda_log.json -96bac76034038740a7c9e84c48ba90442a669774 data/create/recipes/cutting/compat/biomesoplenty/jacaranda_wood.json -4c5c28264e05e294de2b316fdd0dd2de8b8a1ed2 data/create/recipes/cutting/compat/biomesoplenty/magic_log.json -3634bb459019791c1010b7b93886e9d70fb00aa4 data/create/recipes/cutting/compat/biomesoplenty/magic_wood.json -697be2e1eccbf5ec96d5f00ab7ec03918a32f5c3 data/create/recipes/cutting/compat/biomesoplenty/mahogany_log.json -fa8a8440905213675dd769ae29509a1cbcabb1c1 data/create/recipes/cutting/compat/biomesoplenty/mahogany_wood.json -1130274e3e8abc3d3c7fe646898db7c68a59fed0 data/create/recipes/cutting/compat/biomesoplenty/palm_log.json -184b9042633580815a6d1e2e1f1d3c543f26a3e4 data/create/recipes/cutting/compat/biomesoplenty/palm_wood.json -919a8fbf9f8e7f398a28a8af71ca4ad48ed8d6db data/create/recipes/cutting/compat/biomesoplenty/redwood_log.json -165e2642f98885734b3f815579ff589b8f0b870e data/create/recipes/cutting/compat/biomesoplenty/redwood_wood.json -1a3f84111c5027304bfe8d037fa853125b2183c2 data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_log.json -8f2c2015927767d627be865dc603530dd05328ee data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_wood.json -822d84a550496c7f2c3ee127314a50512dfe5c8c data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_log.json -737f59278b7b08c743b1ba5dc336c906b7fdd0e5 data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_wood.json -03196fc1d845abe7f16ebbf25c64c86ad9c42efe data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_log.json -b067086760701e8c11ced7b871b97e0ef7b1b2f0 data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_wood.json -06dc710f86bfebb1a6927f3dff8d64e48009acf2 data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_log.json -a300edf8cae5ad7b3e2c129b44d1ea956e517c41 data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_wood.json -285b0ec232953870c714ce0b05b129e3e5833ee1 data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_log.json -91647155034c4ffa87005d38416704dbb3c7b569 data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_wood.json -3df1098856ffc9ae705f3ed577be378801e1fff9 data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_log.json -be8856c7ddcac88a2d51980d963964c98b623dd8 data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_wood.json -a77cbccc69c38b78bf15ee90fa377c11a8539cef data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_log.json -e5df4bc6f127838474fadcb14e7bfaee739dddad data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_wood.json -dfe420fd232ddf6ef27dd97baebef38b1087a55b data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_log.json -5bb6720ae1472207587a935d3fca5f065e0efa1a data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_wood.json -079b43a27f33868a776e27f22432d81051067ea1 data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_log.json -35c64750475e72b01333694c1d588213838528cd data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_wood.json -cf2036fe04660304257d7e5822eeff6656685417 data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_log.json -f69bfa1c375c67d63d7b35475dedbe76644c10a5 data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_wood.json -71a5963ad5dd9de348451ae4bfbad46cc06b8d8f data/create/recipes/cutting/compat/biomesoplenty/umbran_log.json -4cc971f56409befacd039a09ed5b561702681172 data/create/recipes/cutting/compat/biomesoplenty/umbran_wood.json -f3c630ba88419ea2fdf55b03eac22aac88acd56c data/create/recipes/cutting/compat/biomesoplenty/willow_log.json -f661dc5faff7e08489ef6ac4996864b79e53804a data/create/recipes/cutting/compat/biomesoplenty/willow_wood.json -c3c4999b33f2f29f31f1ac2cd0256694e530b6ab data/create/recipes/cutting/compat/blue_skies/bluebright_log.json -686bb3eab9fd2fc0439ffe7c31c08dee37eb17c3 data/create/recipes/cutting/compat/blue_skies/bluebright_wood.json -dfcee56f35b64e0b6d9a86a113f56de78f0ce6b3 data/create/recipes/cutting/compat/blue_skies/crystallized_log.json -0f6fa127bf9fd14a799985437eb1554a527f71c8 data/create/recipes/cutting/compat/blue_skies/crystallized_wood.json -a0ca7db3a2a631be843c697347ad70501b4e700c data/create/recipes/cutting/compat/blue_skies/dusk_log.json -ccfa435f7714312b8f307503203cb53d1643282a data/create/recipes/cutting/compat/blue_skies/dusk_wood.json -d7d5a3b1dfc58f0779819ce96fb382a5b023fba5 data/create/recipes/cutting/compat/blue_skies/frostbright_log.json -eee254d6e658b9584223d3fdb52d02e6257cbf02 data/create/recipes/cutting/compat/blue_skies/frostbright_wood.json -80499299707fbaad688fada38255b0dd076371f0 data/create/recipes/cutting/compat/blue_skies/lunar_log.json -177c8fd94e40a9ed839f43fbf6ee6afa53da7d93 data/create/recipes/cutting/compat/blue_skies/lunar_wood.json -a8cbd0e4f80fa6cf5b295c488a5795af9d20c923 data/create/recipes/cutting/compat/blue_skies/maple_log.json -a5ceee5b1c402dfcb06851a696c4ba4e3c15d790 data/create/recipes/cutting/compat/blue_skies/maple_wood.json -137ccda54b20e644f2aedafd924a976ffd88d452 data/create/recipes/cutting/compat/blue_skies/starlit_log.json -1960934756be7cb82421e9428622eb853c96c451 data/create/recipes/cutting/compat/blue_skies/starlit_wood.json -c96c5ecb3913b7611cea45dd45be447313a53278 data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_log.json -26af6c6fc9e093d466b8a920de16e95aca9e0fe6 data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_wood.json -2ef370bdc202010ef3f3d28a3df050b785178966 data/create/recipes/cutting/compat/blue_skies/stripped_dusk_log.json -e64dc0f1b77303152596c2c092783d06cfaed371 data/create/recipes/cutting/compat/blue_skies/stripped_dusk_wood.json -523239c7e97a4d0ea9a602324926ff8c7de21122 data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_log.json -a29748d29a707f36cc660b833fc1d1caab2c7c2a data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_wood.json -5eec34196ea44c10cd72a75a843b22fa5a4ab419 data/create/recipes/cutting/compat/blue_skies/stripped_lunar_log.json -c3be04b553399fe0a7e0ec551086abc7c3eedf36 data/create/recipes/cutting/compat/blue_skies/stripped_lunar_wood.json -43af28179df2cdd235293c8be0ec9fdd30393b6d data/create/recipes/cutting/compat/blue_skies/stripped_maple_log.json -6972e2bde54d352e14431fd334a06bfb1c83ecb6 data/create/recipes/cutting/compat/blue_skies/stripped_maple_wood.json -d4c2e45ea9525bb4d8df7e8ffaa4fba18c40d30f data/create/recipes/cutting/compat/blue_skies/stripped_starlit_log.json -964a494326ee801e693c9f4d870a8420a532e8cb data/create/recipes/cutting/compat/blue_skies/stripped_starlit_wood.json -158cde5b02ffefebe1d2a393f443c918fce9987e data/create/recipes/cutting/compat/botania/dreamwood.json -159b2c750e34c4782146554c6dc4b10a67e68c98 data/create/recipes/cutting/compat/botania/dreamwood_log.json -5d137232772d1f78be59fb8f382cee312b6df601 data/create/recipes/cutting/compat/botania/glimmering_dreamwood.json -eb5e05b5cab9fa314277121a0cbf94bdafa2e14b data/create/recipes/cutting/compat/botania/glimmering_dreamwood_log.json -f335b36e818ad653a245f54c9c77a7d9c041c561 data/create/recipes/cutting/compat/botania/glimmering_livingwood.json -49b875f3a21b5a85c33ac5de992d071aa0c8f4fd data/create/recipes/cutting/compat/botania/glimmering_livingwood_log.json -eb48e281f17bc125511870ff02a58cab915e435d data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood.json -217ea2bc83a98334f0f155a64a1ea1e19a661e56 data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood_log.json -8e39b16d4d1db2643cc5ec79773b1ae2b5bed1ab data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood.json -407698357fb1ff81ef4e35b32f3f1692cbb317c9 data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood_log.json -0c43382655638d8bca0c84fadb6d609ecc16ecd2 data/create/recipes/cutting/compat/botania/livingwood.json -da68af0ba1b040e8049a224e8ea8ada7fcc1f45a data/create/recipes/cutting/compat/botania/livingwood_log.json -eed98e7a9d5c4cd1bf39e4268bac6f1dc348d512 data/create/recipes/cutting/compat/botania/stripped_dreamwood.json -7fadb54f614bfe0af2c2c22f46c6923a14fefa8c data/create/recipes/cutting/compat/botania/stripped_dreamwood_log.json -2786670eacfe51a1f4adc4b83e825f93c328a1ea data/create/recipes/cutting/compat/botania/stripped_livingwood.json -9f471696da339cadeb3d805c3ea61310b1d81ff4 data/create/recipes/cutting/compat/botania/stripped_livingwood_log.json -4e775fd59f7c5b4ca0861cd9a077d3e0e464b4a4 data/create/recipes/cutting/compat/byg/aspen_log.json -bd21d721698b1d46f2a0483e2ea926558ba8f0ea data/create/recipes/cutting/compat/byg/aspen_wood.json -cef520dc7a7c4ec257f2b4ab2b1b134ef29874f0 data/create/recipes/cutting/compat/byg/baobab_log.json -56002a9c9d210fdce2d21c4abb17851b5bc770f9 data/create/recipes/cutting/compat/byg/baobab_wood.json -5492c3b2db0fefb3f1498bbb440d5c92bad7e072 data/create/recipes/cutting/compat/byg/blue_enchanted_log.json -6b32af35555c83fee27c43858ebe03711c825d36 data/create/recipes/cutting/compat/byg/blue_enchanted_wood.json -2325864b4f7a80d466f5eef373f65cccb0557d55 data/create/recipes/cutting/compat/byg/bulbis_stem.json -52320312ae0aa6d957f841b430355d96afdbfe0b data/create/recipes/cutting/compat/byg/bulbis_wood.json -588ea2463640155d79724a694b5152574ea3f2a7 data/create/recipes/cutting/compat/byg/cika_log.json -880d0190030e3a70fd2a21ab4fc11604fbaac447 data/create/recipes/cutting/compat/byg/cika_wood.json -1fc63cafc946178443d1e362b9730455f2192b25 data/create/recipes/cutting/compat/byg/cypress_log.json -c27c16aec08599e76020ac4b40dc5085b2a85d3a data/create/recipes/cutting/compat/byg/cypress_wood.json -5daca7d84f07e72a961fce6e405cd13428411bd3 data/create/recipes/cutting/compat/byg/ebony_log.json -5e7650fdc0541e996db733880ddd7746f6998660 data/create/recipes/cutting/compat/byg/ebony_wood.json -0357f1d46f7b79de4b20af24eff754c5d280ed3f data/create/recipes/cutting/compat/byg/ether_log.json -464978c5018fb884aecad8455caefa3396b88bea data/create/recipes/cutting/compat/byg/ether_wood.json -3053408dcc0deedd992e4ca8c9181fff1a952ad8 data/create/recipes/cutting/compat/byg/fir_log.json -dfd2ce56f18327ac7feea783d5c7439dd2516884 data/create/recipes/cutting/compat/byg/fir_wood.json -40af5f403a0681833109b26b6da8762d99df484a data/create/recipes/cutting/compat/byg/fungal_imparius_hyphae.json -3d7de0bab24b7ea34c34a25383c4937cc9f585d8 data/create/recipes/cutting/compat/byg/fungal_imparius_stem.json -121375152c841b695bbd23fa4a4ad408243464fe data/create/recipes/cutting/compat/byg/green_enchanted_log.json -16b991e08d10fe32b93d987113c12dc9568517c3 data/create/recipes/cutting/compat/byg/green_enchanted_wood.json -65d3c6f12bd86be2060487adce703896c596207d data/create/recipes/cutting/compat/byg/holly_log.json -6ccd44a9607d8ac1b34896f6b0f427865a18a447 data/create/recipes/cutting/compat/byg/holly_wood.json -47dd1a429986a790a418c97f56884fa19dcbc74e data/create/recipes/cutting/compat/byg/imparius_hyphae.json -a24ac854f3b3ebf57bea9ebd58fd9655fed8e922 data/create/recipes/cutting/compat/byg/imparius_stem.json -6152e117579369ae3388f6f458331a6747a83272 data/create/recipes/cutting/compat/byg/jacaranda_log.json -3e58caf860dfa0432bad58aae44d5713264010da data/create/recipes/cutting/compat/byg/jacaranda_wood.json -58c4d750ed6a08f30908c7508106a224c2047de8 data/create/recipes/cutting/compat/byg/lament_log.json -d93f6deefd5bcf4d91242534d9b588fa2ab1a7de data/create/recipes/cutting/compat/byg/lament_wood.json -6f3a120fae7fdcc98a416185107381a6caf739b0 data/create/recipes/cutting/compat/byg/mahogany_log.json -19cf897802135c3ebdf68f6e2bc41f3cf8d0ddb0 data/create/recipes/cutting/compat/byg/mahogany_wood.json -d13e02245ca4acd0c4c4d38359eddf3b22fcff7f data/create/recipes/cutting/compat/byg/maple_log.json -9c947dd9fb94709b481daa3ec5156b227b061cdd data/create/recipes/cutting/compat/byg/maple_wood.json -f25cdfa7c0ff0d9c0bfb8fd4c678d1ad61d6f755 data/create/recipes/cutting/compat/byg/nightshade_log.json -7b58e103b01afc4b730b5b3f71cb9fd893427916 data/create/recipes/cutting/compat/byg/nightshade_wood.json -ab8cd4e768bb4b6945498249f9d5302909de199e data/create/recipes/cutting/compat/byg/palm_log.json -c446697efd034229fb5334af83f75b6418806074 data/create/recipes/cutting/compat/byg/palm_wood.json -476fceb3e5b0284125de9c53227e318e1025ca63 data/create/recipes/cutting/compat/byg/palo_verde_log.json -bb3f841b52b75cd14aa5ea82f1459f2a7b234c36 data/create/recipes/cutting/compat/byg/palo_verde_wood.json -eeb2e2db22875cfe74b30f834637dd74006bde5d data/create/recipes/cutting/compat/byg/pine_log.json -911a25900b077a512dc59331055b06481944f207 data/create/recipes/cutting/compat/byg/pine_wood.json -4ca5a84e9f098c9a935b1321fca795f6fcccd0f9 data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_log.json -5735995aa9f0717817b819268e3885ac6f7ed1e0 data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_wood.json -28823f07067a1df8f152d6c1ddeeae8e61bf47eb data/create/recipes/cutting/compat/byg/redwood_log.json -dbd5003c9b08a7794b0aeac2eb1e0996f00de73f data/create/recipes/cutting/compat/byg/redwood_wood.json -0a25e874ba7b36357a6d4172eb74af363db339cb data/create/recipes/cutting/compat/byg/skyris_log.json -0ff912a98f11fdeee6f5ad34f36c591ce944b1cf data/create/recipes/cutting/compat/byg/skyris_wood.json -201ef4c331f3083cf2272ce1bf3aacbd76d91c54 data/create/recipes/cutting/compat/byg/stripped_aspen_log.json -cc9d820a5d2a987494884a682d9648dfcbfb1055 data/create/recipes/cutting/compat/byg/stripped_aspen_wood.json -a844fac33edd99c0f166f17cd493c4c01ffe1d35 data/create/recipes/cutting/compat/byg/stripped_baobab_log.json -bb1d318dbfb3deada9db8c5c679977684468b60f data/create/recipes/cutting/compat/byg/stripped_baobab_wood.json -fec45c1d4084c9de211876a3fd313313c18920b2 data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_log.json -608a3d0bb5ca12e95141016099085821e47f4e98 data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_wood.json -087dd3a1c516f9db9729974781bc68e13ff4b3de data/create/recipes/cutting/compat/byg/stripped_bulbis_stem.json -f45c17bea93fc15f10b0c135ebf334a41a2e68d2 data/create/recipes/cutting/compat/byg/stripped_bulbis_wood.json -4187543812af8be22977b2b503ffb16ff82e38e6 data/create/recipes/cutting/compat/byg/stripped_cika_log.json -72c90971b638693cf7425ff59530672f37433b52 data/create/recipes/cutting/compat/byg/stripped_cika_wood.json -c66c179d9989be618909104ba8e0f399ca34a630 data/create/recipes/cutting/compat/byg/stripped_cypress_log.json -0dbf97db4afd35580faadb6d5964ef9098438ac4 data/create/recipes/cutting/compat/byg/stripped_cypress_wood.json -944b0993af3591956df6c2c5cd7fd08643c2dccb data/create/recipes/cutting/compat/byg/stripped_ebony_log.json -ee3de122e8ff85f1eda9a1834e3c19eef1250685 data/create/recipes/cutting/compat/byg/stripped_ebony_wood.json -e64357b673fe4f983e9547305f8f95272e8b8b77 data/create/recipes/cutting/compat/byg/stripped_ether_log.json -c2ecdaadf564d496ab679b38356ce9614237668b data/create/recipes/cutting/compat/byg/stripped_ether_wood.json -a267fc6425816b6bc01396221470e0814e6bd942 data/create/recipes/cutting/compat/byg/stripped_fir_log.json -b7647e89ee29a4e116c49c1ae419d3d053608017 data/create/recipes/cutting/compat/byg/stripped_fir_wood.json -3b0e0a3a91e8f19b2f48f53044a2e3d5479578a3 data/create/recipes/cutting/compat/byg/stripped_green_enchanted_log.json -1406357c702c4d82f372e4f1a837591586faff97 data/create/recipes/cutting/compat/byg/stripped_green_enchanted_wood.json -2772e21459b48648f3c54b82243994f38a691c84 data/create/recipes/cutting/compat/byg/stripped_holly_log.json -46b523df1967aca55cc9f9763016bcd6133a3cb8 data/create/recipes/cutting/compat/byg/stripped_holly_wood.json -0b4b05df393e5e0bda59877b9f9048b7c510043d data/create/recipes/cutting/compat/byg/stripped_jacaranda_log.json -503bc3dcefeee34b91527eeb61a6ebd50d678fbd data/create/recipes/cutting/compat/byg/stripped_jacaranda_wood.json -4fbaedf8e7a601f592c6c671de6435b52c44b6d4 data/create/recipes/cutting/compat/byg/stripped_lament_log.json -0b4478eba4e2d9bd835d9ad91dcf2eccfc538f12 data/create/recipes/cutting/compat/byg/stripped_lament_wood.json -3550d5eb7f8eab95f4dd840d72cc14dea7acdb67 data/create/recipes/cutting/compat/byg/stripped_mahogany_log.json -d66b3e69b6bcf38a9d01fc9290b81778b46459f0 data/create/recipes/cutting/compat/byg/stripped_mahogany_wood.json -4778e5d9e1b5a5d254483dedf9cf22cbda73ca2d data/create/recipes/cutting/compat/byg/stripped_maple_log.json -18b5f67be3d28bc6c8764d2ad576f16745d95109 data/create/recipes/cutting/compat/byg/stripped_maple_wood.json -1446329655130e0cf0f0da7c1c17f517bbfb9d79 data/create/recipes/cutting/compat/byg/stripped_nightshade_log.json -c1ddc415556ebf6c6b518d3dc1c54f389ecc6ca9 data/create/recipes/cutting/compat/byg/stripped_nightshade_wood.json -cc7a000cf42f792912531e83f00cc694bf47d0ee data/create/recipes/cutting/compat/byg/stripped_palm_log.json -6ad7a35bfef1334a0566496f9a4658c4213db72e data/create/recipes/cutting/compat/byg/stripped_palm_wood.json -1ac1701b9779eb875b371a3e8742b1de203a0339 data/create/recipes/cutting/compat/byg/stripped_pine_log.json -9be87d49f1f20967d115c842d551cbcfe813fe50 data/create/recipes/cutting/compat/byg/stripped_pine_wood.json -39bda1670d29736ae18a72115b5525e2b54b26c2 data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_log.json -da8e26696706d6a0c5af520bcde6246f463a6e7d data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_wood.json -b2720a4858848f941e264a8f78653477d7283403 data/create/recipes/cutting/compat/byg/stripped_redwood_log.json -ff3707171e4422b08b6eb9b9bf6a1a4bdffdbe16 data/create/recipes/cutting/compat/byg/stripped_redwood_wood.json -a72ab3e1f450e11903d403ede28ac1395c360d2e data/create/recipes/cutting/compat/byg/stripped_skyris_log.json -096b56116fe9c02005e68c84c15d7ba4c590572a data/create/recipes/cutting/compat/byg/stripped_skyris_wood.json -b6f1b9584cb32d329023815be6b3df8e17dbcf0b data/create/recipes/cutting/compat/byg/stripped_willow_log.json -8925bfb2575712dd3abc306b64bafd93d168dd3b data/create/recipes/cutting/compat/byg/stripped_willow_wood.json -03bda6ad269d122e39adb211b1f3a8ed1ba11eb9 data/create/recipes/cutting/compat/byg/stripped_witch_hazel_log.json -03865937f2c740871024d8bd51ef5e07567f1c3d data/create/recipes/cutting/compat/byg/stripped_witch_hazel_wood.json -611bed180fa9ec6fa5e7cc3e8958836c2fb24489 data/create/recipes/cutting/compat/byg/stripped_zelkova_log.json -f4283de13917784d85c0ba84f68424ec8b69545f data/create/recipes/cutting/compat/byg/stripped_zelkova_wood.json -667d33f61cb4c5f5d204169c9e3adf11154bdfc2 data/create/recipes/cutting/compat/byg/willow_log.json -53f2571f67a1991676981a239875814d99f62e6c data/create/recipes/cutting/compat/byg/willow_wood.json -73e9929c94048d2fa4646dc92eaf02cc0f2b71da data/create/recipes/cutting/compat/byg/witch_hazel_log.json -88b328cf0c0a02f296056abb423e4f3745e5ab4d data/create/recipes/cutting/compat/byg/witch_hazel_wood.json -31a331b2294c726f0e6b4573b1db14c2423116b2 data/create/recipes/cutting/compat/byg/zelkova_log.json -f249713773128375a0869a8df3205b384e2b54f4 data/create/recipes/cutting/compat/byg/zelkova_wood.json -363da3d703f57ccac27632b573734a940799374b data/create/recipes/cutting/compat/ecologics/azalea_log.json -052c45bc088143aae8508af521a8f91a2c263459 data/create/recipes/cutting/compat/ecologics/azalea_wood.json -10b5a67570271c02e12d3d46e48c2ed8fe2fd2fb data/create/recipes/cutting/compat/ecologics/coconut_log.json -8d34f87daf269250af59bae242322bc869017d84 data/create/recipes/cutting/compat/ecologics/coconut_wood.json -bec2975b6e10bb12261feb952e8e7cd6e0019619 data/create/recipes/cutting/compat/ecologics/flowering_azalea_log.json -701a522dbdfab4a7772b0f8dd5d9759ce24052e3 data/create/recipes/cutting/compat/ecologics/flowering_azalea_wood.json -b12bab3ed019328ce83f64b828b366b72503e823 data/create/recipes/cutting/compat/ecologics/stripped_azalea_log.json -2a5d12c6b39847533e6940931ad201e6924aae38 data/create/recipes/cutting/compat/ecologics/stripped_azalea_wood.json -37a3e9f0220b51d51250fe6febb7348858f0e8b5 data/create/recipes/cutting/compat/ecologics/stripped_coconut_log.json -e2308624a37abc099e2349456afa1c4064b02fdb data/create/recipes/cutting/compat/ecologics/stripped_coconut_wood.json -c6b1455c29d3bd0ff387edad10328ba4dd8b7f44 data/create/recipes/cutting/compat/ecologics/stripped_walnut_log.json -0026f35ef1445df9c3bb83bdfe25898cceffd5e4 data/create/recipes/cutting/compat/ecologics/stripped_walnut_wood.json -e4c5b799335a71a4259de6519ff9fe86fc014c85 data/create/recipes/cutting/compat/ecologics/walnut_log.json -45734ddd48ac17b25b88cf1f5b0d227431946cf7 data/create/recipes/cutting/compat/ecologics/walnut_wood.json -b0be23a2a268557b1ab26518a9d6ff1e492068fa data/create/recipes/cutting/compat/endergetic/poise_stem.json -1581ae3f152ba5784d6b737ed37e0fe8e6317a76 data/create/recipes/cutting/compat/endergetic/stripped_poise_stem.json -513c32af17004085c152de0c50ecdc0821ad5736 data/create/recipes/cutting/compat/environmental/cherry_log.json -dd7f392a18fa58dbcd02e1700a89d847ef912f6a data/create/recipes/cutting/compat/environmental/cherry_wood.json -bb5be6efdf3a134baed80179e9f65a5e9402e001 data/create/recipes/cutting/compat/environmental/stripped_cherry_log.json -8938bac54128e55540b9061333cebadb615c5531 data/create/recipes/cutting/compat/environmental/stripped_cherry_wood.json -962dd25663096fe3883f0aa5a89cea00c312625a data/create/recipes/cutting/compat/environmental/stripped_willow_log.json -ee28f2a0519c41df80647ec643d20b3ce05d5ca7 data/create/recipes/cutting/compat/environmental/stripped_willow_wood.json -bfa59f4024105be24f441ec9e1fe2394bb4c32ed data/create/recipes/cutting/compat/environmental/stripped_wisteria_log.json -15cb849317c8038750000708c93cce535d7662e5 data/create/recipes/cutting/compat/environmental/stripped_wisteria_wood.json -9c9b4b63d736e9bef583e3e3085df9547bee1ad3 data/create/recipes/cutting/compat/environmental/willow_log.json -6a6b47c7c058fe67ea0f0f479145e0e921fcd571 data/create/recipes/cutting/compat/environmental/willow_wood.json -590fa0d5dbc357c4d22f7e79f94365c50ca1c812 data/create/recipes/cutting/compat/environmental/wisteria_log.json -62b927056738fbbbb1ceb7b2b3f23e45c94cdd1b data/create/recipes/cutting/compat/environmental/wisteria_wood.json -97d07cbd21b147d93cbfea6534258f0b5faabbbb data/create/recipes/cutting/compat/forbidden_arcanus/aurum_log.json -b08980c7deb9a4de4983fdae188f0c5ac627c1e5 data/create/recipes/cutting/compat/forbidden_arcanus/aurum_wood.json -47902025354c45f34fa62402fc5f32db6648a7c3 data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_log.json -f8f97315cfcd7e76229b9856ca6b2942bd7754f5 data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_wood.json -c6e138b6adf0311deebeff7cacdcdb57337f41da data/create/recipes/cutting/compat/goodending/cypress_log.json -cac6d3d763a3909d9a1f3eebe83190013e323e8a data/create/recipes/cutting/compat/goodending/cypress_wood.json -a3664dc30807cbc7903f79944bfb9b7d08a91671 data/create/recipes/cutting/compat/goodending/muddy_oak_log.json -c0bde27c6ff867dbfe7bea538bce82ddd12d4fea data/create/recipes/cutting/compat/goodending/muddy_oak_wood.json -eb749011e1c688f2005a63eb9953d29c6287eae4 data/create/recipes/cutting/compat/goodending/stripped_cypress_log.json -228632291f42fb47b73a6e3058a27475d97c20f1 data/create/recipes/cutting/compat/goodending/stripped_cypress_wood.json -c9e3c6e1b591822283f4436c70a52ce27034e8cf data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_log.json -f6cabdcbdb8aeffb03228bf65183bbec5aaba182 data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_wood.json -3a9be23a966c2737c5059474c17a86566bc5505f data/create/recipes/cutting/compat/hexcasting/edified_log.json -3f3879c426acb1753f2985ed19f0a905bdbd3797 data/create/recipes/cutting/compat/hexcasting/edified_wood.json -68d80d00d15d6ad14100025eecbd76c1fa8e3a52 data/create/recipes/cutting/compat/hexcasting/stripped_edified_log.json -9e665be213a1eca08df0dcf38766d2ce3a76de8a data/create/recipes/cutting/compat/hexcasting/stripped_edified_wood.json -f87872a26b790bd29abfc036486474c5db8ee518 data/create/recipes/cutting/compat/integrateddynamics/menril_log.json -cd568df5168a0cfccbdaaf767ec63d71871ba3ba data/create/recipes/cutting/compat/integrateddynamics/menril_log_stripped.json -b5573785c73cbf3b2c2bd096bb0a12b054819b74 data/create/recipes/cutting/compat/integrateddynamics/menril_wood.json -ebca8e98bca0a5c8926c4aa5b197d5d436e2e00b data/create/recipes/cutting/compat/integrateddynamics/menril_wood_stripped.json -1b91f83f2c6e4c6087abc7a136478027b2c7092d data/create/recipes/cutting/compat/nethers_exoticism/jabuticaba_log.json -5f074e7d51d851e95469a234666485ae1f913731 data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_log.json -d8ea31f8eac026d99a26ab200eeca6faee064d9c data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_wood.json -536ed770010fcf8ba56f6333d58fa09b974b95c4 data/create/recipes/cutting/compat/nethers_exoticism/stripped_jabuticaba_log.json -8c84afc4870ff5c8d936dd1363e18531f27c6233 data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_log.json -4119174e4e7126b66d05e78e7415558a31ba6540 data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_wood.json -5a8b70f884741f155924174f8f8911574a782928 data/create/recipes/cutting/compat/quark/ancient_log.json -0b6953e5fd8f5d248f5327a8775e4e30a355ca49 data/create/recipes/cutting/compat/quark/ancient_wood.json -a0194f77f72349786f6b87e641c9628f7fe46fdf data/create/recipes/cutting/compat/quark/azalea_log.json -17daa6e2505ae75e51def1f1523f9d6f120de696 data/create/recipes/cutting/compat/quark/azalea_wood.json -118122fbd3154c0090768d9103e802d2e68b3f06 data/create/recipes/cutting/compat/quark/blossom_log.json -57b23b572f4d75bb39f7f84277f0a0a4e6be992b data/create/recipes/cutting/compat/quark/blossom_wood.json -d36666b83bf934aabd20aac182c4863de693903e data/create/recipes/cutting/compat/quark/stripped_ancient_log.json -a666d4c2d54acfa924eeef535415b993d40ca015 data/create/recipes/cutting/compat/quark/stripped_ancient_wood.json -e05b81a5609420153b3ecace758a153bd88a4bef data/create/recipes/cutting/compat/quark/stripped_azalea_log.json -f820204e8d99f21203b001da23e8b44cf61e33e2 data/create/recipes/cutting/compat/quark/stripped_azalea_wood.json -af71513af8de414036ff73fee0eaca4b823de99c data/create/recipes/cutting/compat/quark/stripped_blossom_log.json -071c8a562233a342875c9cdd392bbebfe719e321 data/create/recipes/cutting/compat/quark/stripped_blossom_wood.json -9fe1249c4b24d82699829f1e8f3dc19de791dbd1 data/create/recipes/cutting/compat/regions_unexplored/alpha_log.json -27585fe96d7e211e4469c437c82c89c1268cf0bf data/create/recipes/cutting/compat/regions_unexplored/ashen_log.json -bf04910ca9246aec3146eff28bc7d5d778c5d6d4 data/create/recipes/cutting/compat/regions_unexplored/ashen_wood.json -371e7f6a13a45006c21837847999e6e1b69e6320 data/create/recipes/cutting/compat/regions_unexplored/baobab_log.json -2cadb9f9d714f8668291122519a73458d6e6afdb data/create/recipes/cutting/compat/regions_unexplored/baobab_wood.json -f124b677daea80e9efdcb58451442403f79ecc59 data/create/recipes/cutting/compat/regions_unexplored/blackwood_log.json -809aba67a96fcf9766c4278697ddfbd89ff63db1 data/create/recipes/cutting/compat/regions_unexplored/blackwood_wood.json -d6263c38f2a54be9310530cfd5f23aaddda0dbca data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_hyphae.json -3904212da6e2eb60c453520a44eb22d33fc1c128 data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_stem.json -780ddd7800cc138177752ee965ccd7cad8e53c6e data/create/recipes/cutting/compat/regions_unexplored/brimwood_log.json -15ca75b81a207a347e06c730da7afa106714b9ed data/create/recipes/cutting/compat/regions_unexplored/brimwood_log_magma.json -44d643b1724377c9019436f6927b0e1c2de63a42 data/create/recipes/cutting/compat/regions_unexplored/brimwood_wood.json -d449dc8b30400627cb509b0bcdc6b63bbb595172 data/create/recipes/cutting/compat/regions_unexplored/cobalt_log.json -7ff17654f134c7c13f6008619b76b4e19751728c data/create/recipes/cutting/compat/regions_unexplored/cobalt_wood.json -8446d9a9b3ff0140c64d549e33f9f5718fdcceb6 data/create/recipes/cutting/compat/regions_unexplored/cypress_log.json -620d71dee83ac1aa16d30c1b4833e15f00a04208 data/create/recipes/cutting/compat/regions_unexplored/cypress_wood.json -0fa6e6ac5c19c8660111c07b13f0d82cf339910b data/create/recipes/cutting/compat/regions_unexplored/dead_log.json -30a08ae6222bebf4c6fbfc5801ccc30b5d01e417 data/create/recipes/cutting/compat/regions_unexplored/dead_wood.json -696b5f3eb788a5ab8dc35f91ffbc575d987af4b1 data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_log.json -641e17384aa1ed504157ee8b4c3bf839f864199c data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_wood.json -e8b754d24ae46631a97ffa6b15f4676768c4e219 data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_hyphae.json -3401ba3b7c8fa6023566e99532f035e4d78463ea data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_stem.json -0e2885c8819270dd0ea9b423eb17aabce17f50b6 data/create/recipes/cutting/compat/regions_unexplored/joshua_log.json -fd296307a65df37d2c952b3de9e79234b36c8bf8 data/create/recipes/cutting/compat/regions_unexplored/joshua_wood.json -b063c34700782af4ba8e5b353faa93a6af63e133 data/create/recipes/cutting/compat/regions_unexplored/kapok_log.json -44375fea18ff6312a05eb4948cf23916cad31bb7 data/create/recipes/cutting/compat/regions_unexplored/kapok_wood.json -74e328e600a2ce311638acf6b0cda2dca7e689bd data/create/recipes/cutting/compat/regions_unexplored/larch_log.json -519d0a467bafd51425e588c1452b326485ac504a data/create/recipes/cutting/compat/regions_unexplored/larch_wood.json -9d8f4845c835ba07d4f1f0f07b8d9ed39fb3514a data/create/recipes/cutting/compat/regions_unexplored/magnolia_log.json -4b367599792101bd5403aba96e973748fc91e8cf data/create/recipes/cutting/compat/regions_unexplored/magnolia_wood.json -caaefb19635f7fbec31d87d7ef40172c25e48b72 data/create/recipes/cutting/compat/regions_unexplored/maple_log.json -b8731d1b36bac59a519a496ce5253595be58ca57 data/create/recipes/cutting/compat/regions_unexplored/maple_wood.json -3cb94f34a0318442ea3a9225366587bf1aa0a01a data/create/recipes/cutting/compat/regions_unexplored/mauve_log.json -587727f7998dd25ee3441aa6f0ed1736262b8a55 data/create/recipes/cutting/compat/regions_unexplored/mauve_wood.json -aecbe7b08f8374331f976434daff89c4e4922efd data/create/recipes/cutting/compat/regions_unexplored/palm_log.json -3a83e8d7cac67638b76a8b30d469faaae71e9d6a data/create/recipes/cutting/compat/regions_unexplored/palm_wood.json -40b46cba392e02498406b90536b8da540df0eb76 data/create/recipes/cutting/compat/regions_unexplored/pine_log.json -9fe88b00cb4c42ed5677f46bccdf2c05fd085c5f data/create/recipes/cutting/compat/regions_unexplored/pine_wood.json -7a11eb2ede6e9d5f1284e6223c52465493901f79 data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_hyphae.json -78fb2663e91d8f6494ff1348f2d83633e50713ee data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_stem.json -eb7b75678cf8ae102eee91456bd8d4387acfb146 data/create/recipes/cutting/compat/regions_unexplored/redwood_log.json -d1da4369daa6c4fd16dfeff7551c218949e122d5 data/create/recipes/cutting/compat/regions_unexplored/redwood_wood.json +c2f1bca179d6218aa75526df386106b72eb0dd67 data/create/recipes/cutting/compat/immersiveengineering/wire_aluminum.json +4e1ae62cb3f11d79b2ba979aa647a49518615525 data/create/recipes/cutting/compat/immersiveengineering/wire_copper.json +e9086dc98d03798ded6f3170a5c51528d1f5eba7 data/create/recipes/cutting/compat/immersiveengineering/wire_electrum.json +ca543d1e95ac73dbf3eaac91e80830fb3a071276 data/create/recipes/cutting/compat/immersiveengineering/wire_lead.json +bcab848fda66d20cf871f97db3c7c41f7c4b55c9 data/create/recipes/cutting/compat/immersiveengineering/wire_steel.json aa75d5f92d23fb24aece736145ac8372f6cff3f3 data/create/recipes/cutting/compat/regions_unexplored/silver_birch_log.json 3218231281a0afda1cef330a022e450efac18927 data/create/recipes/cutting/compat/regions_unexplored/silver_birch_wood.json -2002a66ac280b0a41679cb84422a591760fd88bc data/create/recipes/cutting/compat/regions_unexplored/socotra_log.json -de2954580e05806befc31b2d445577d3fae6ba47 data/create/recipes/cutting/compat/regions_unexplored/socotra_wood.json -7a3bf3bbdb5ff29682d60ac068ffa9f4bb423b34 data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_log.json -2c961586f828dca3a4107dc181e7e99ef7fecf7d data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_wood.json -497877a6e23c6f337f46e784e64f725e7507d98a data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_log.json -092003ce37ad550040026e2913e9670f5c25169e data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_wood.json -fa85fe2cf25bdfffb5bfcb0d7d2fc2733c8e2961 data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_hyphae.json -68b7452484be51a5ca9e1f5daa5ef960e84c4a24 data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_stem.json -25793b4b9d6bd7222da6e49c59a134f36c708d2b data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_log.json -cec8ba2be437e8e50f18277dd7464cb5a51783c6 data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_wood.json -d131167166b5eaabc2b116920693399624cc969c data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_log.json -eb2300ca83bcffaf96fb192cd8f5f6be6ce4d1a5 data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_wood.json -2bde40143b3b9e400f3e921dd74100f6e4c2febf data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_log.json -7dd7b4e0478e42f4141a384f5f5db3d24c6256ba data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_wood.json -55992382313212af1448785769cb98272736f913 data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_log.json -b1808c9c2afea6f77cbc008d89a0d98c0baacb5b data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_wood.json -4af8a646e1cda8e7cfb54d848af04bcd071cb742 data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_log.json -892f2b15212cdd1ab5aa94bdced37c8ecd502fad data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_wood.json -a0b555a70b9c45671175ea9d67c7f9bb6291ce39 data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_hyphae.json -0b361b9f1b0fffb0934f347e93e01f7f99c8c598 data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_stem.json -7887134005361356b59e3e8f79f747461aa90967 data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_log.json -12bcc42d67c110b7b57a2c15bfd184a7c8d5ced3 data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_wood.json -9c192bac86ada1020093ec7a38bae39f890f6867 data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_log.json -5cf8658dec167a5eae2555e231d86c6dee1e9f86 data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_wood.json -9b9d6b4ff28a9ee9d38e8ff7e2f66c5d741792d1 data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_log.json -477187045049395be4b50747e70b8682bf627745 data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_wood.json -9444611d488463cf40113a522c0125bcc901f59d data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_log.json -c7093db236a350421fb1963233472c8d7b09407b data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_wood.json -6ba2945063856e34dfde713c8b6caf9bcd0b59ad data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_log.json -cb536b2a2638a6e378423c2ea2a3c8785f6fc7c7 data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_wood.json -3ff0ebc63da709a8f4958b7439cf9a88c4f9a349 data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_log.json -a274dadaba1e1f489e7b531ac4eb02e808fc4f01 data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_wood.json -626e2bb1d62ab57bcadf3732491a6a1efd249035 data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_log.json -50dee41bd5c412aa444a2fcc5c3d7638ab01133d data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_wood.json -9270af6499ef6e5c0e097bee06637a518d3a83d7 data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_log.json -58c10356ba51c77959e8f66f83e178d20cec097b data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_wood.json -01b11c8a041883e21d5374b8afdef2fa47a55aee data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_hyphae.json -0c4826e7e49e2cc704627235c2f1c8fab604019f data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_stem.json -1177ce8821f01c08ab918ea24ea33b61cbd733cf data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_log.json -af8789a2a697cd2118d6809100a0c04d4c74794e data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_wood.json -4e441e9502ba4be4fc1c0da98bb53af30f366d1f data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_log.json -3f93dd9538e68c9b1482c41d531c359e6b144914 data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_wood.json -bcba754ec947af79701a5ffb0e64ff7a7ff92a09 data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_log.json -f104dc175e416d675e358e6601442c09c356858e data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_wood.json -6c4a98aa0396f330924d5be6a1fb7c1123c5d236 data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_hyphae.json -b1440d5254bf8dc5b619a7d871f2c51511498184 data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_stem.json -54ed3844da6abdf55939f1d3ed42394c55ce57c5 data/create/recipes/cutting/compat/regions_unexplored/willow_log.json -d0419337ab011df3685a6fea849c17904a03f2d7 data/create/recipes/cutting/compat/regions_unexplored/willow_wood.json -365f090b94466b7695e7beb7d0fc7b7e084e636c data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_hyphae.json -22d48a8e9cf5a566bbc566a92e6bf9762a33586a data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_stem.json -8a9e25c2c196ab94c9e7b5fcb2cf27bc161a8d1c data/create/recipes/cutting/compat/silentgear/netherwood_log.json -9e869a4b7bbb08fefa140292f0cb0806a795fc59 data/create/recipes/cutting/compat/silentgear/netherwood_wood.json -d9cdc0eb674cdf08963ac8f97ee6a7ea2f99e779 data/create/recipes/cutting/compat/silentgear/stripped_netherwood_log.json -071ed83f5ce7f15688e95a1bf33142061ec4aa22 data/create/recipes/cutting/compat/silentgear/stripped_netherwood_wood.json -b2ced0a8d2f9e610ccca5c849bf460492d5fa568 data/create/recipes/cutting/compat/tconstruct/bloodshroom_log.json -9a3551fe7a74cbf4107fa4b26eb2b92a4f19dc44 data/create/recipes/cutting/compat/tconstruct/bloodshroom_wood.json -2a8f39581c635bb98ab437fb48796505df99cfec data/create/recipes/cutting/compat/tconstruct/greenheart_log.json -c68a24ed72589e9427f60fbf8c33cbf8403297fa data/create/recipes/cutting/compat/tconstruct/greenheart_wood.json -4a548deea4a151fc1d58c81ab26bd30a61900864 data/create/recipes/cutting/compat/tconstruct/skyroot_log.json -763616da266a28b8c4b1a88df0ce87c6ce37367c data/create/recipes/cutting/compat/tconstruct/skyroot_wood.json -ad4a650ace874dab7f039e53afa0164de2601a05 data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_log.json -fcda399dee09fd7b7f8486fe5000522a4211c6d2 data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_wood.json -e7f542ab1523379f218d47c7365f1d3be41036b4 data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_log.json -aaa2b8cde03e0141fc4ccd3702fcb0d13966b391 data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_wood.json -dec7bfbdc2c974655110651365f701121370394a data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_log.json -0486cee0f932eee89bb26c2fe5b0ed076d05d1be data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_wood.json -0dcbd6c92adce8bc1fe8a1a6f4c21ad436d4852f data/create/recipes/cutting/compat/the_vault/chromatic_log.json -bb89e77d7cdb54b37434f65c1652112b14fcfcc7 data/create/recipes/cutting/compat/the_vault/driftwood_log.json -e7f497ec5ea4860147d5941df4b594526361886d data/create/recipes/cutting/compat/the_vault/overgrown_wooden_log.json -e04c07431e80d779b2bfdb1227d2b43896ead7f5 data/create/recipes/cutting/compat/the_vault/stripped_chromatic_log.json -e91c945669e5b838e28b73079be0218b7dbb438c data/create/recipes/cutting/compat/the_vault/stripped_driftwood_log.json -dcb888781e53a4bd13a39dc8dcf52d68c70daa11 data/create/recipes/cutting/compat/the_vault/stripped_overgrown_wooden_log.json -95824dae54de5c99be7f108882bb0add80d9f4f4 data/create/recipes/cutting/compat/the_vault/stripped_wooden_log.json -f43130d8c47dbfd21c89d519539e2d8b5437c108 data/create/recipes/cutting/compat/the_vault/wooden_log.json -9a2d7361718e64bf25c3660123ab9f506fad7dba data/create/recipes/cutting/compat/twilightforest/canopy_log.json -35f470c4fb8c1e651bcf8f161ebcaa0f9f888be2 data/create/recipes/cutting/compat/twilightforest/canopy_wood.json -02ef237d075e3033676e0229946c9c2bc9ae27e0 data/create/recipes/cutting/compat/twilightforest/dark_log.json -a032ee8a436f2f7efc993a6d791217d4096c55a9 data/create/recipes/cutting/compat/twilightforest/dark_wood.json -541b21973ffebe85f9e6c31879a46e60d29ec3ba data/create/recipes/cutting/compat/twilightforest/mangrove_log.json -7a8f8746a1d3851ed064138600439749fb619225 data/create/recipes/cutting/compat/twilightforest/mangrove_wood.json -f0018c0a0276f09c26a4ffa8dbff756e70e84af9 data/create/recipes/cutting/compat/twilightforest/mining_log.json -d6e04a2c5139229993067515749038519e664407 data/create/recipes/cutting/compat/twilightforest/mining_wood.json -d03b8d192ba433bd1660fee4cbac81b52b37b332 data/create/recipes/cutting/compat/twilightforest/sorting_log.json -acade83e3e155d869bb66a4c514eff14eaf43130 data/create/recipes/cutting/compat/twilightforest/sorting_wood.json -a819a899a63885169df3c5ff9a21981821154222 data/create/recipes/cutting/compat/twilightforest/stripped_canopy_log.json -cfa1a8b90368d788c29ef3ff57dafad780c29ca4 data/create/recipes/cutting/compat/twilightforest/stripped_canopy_wood.json -bbd6724c3e7b294620d148a283724847428e41ec data/create/recipes/cutting/compat/twilightforest/stripped_dark_log.json -31a5f34120e0fabe91e532e0e86d77a71c66139c data/create/recipes/cutting/compat/twilightforest/stripped_dark_wood.json -ef5428c754626c390bdc3bd5f0c4ceaae069259c data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_log.json -4db7b6856995a1fcb3d4f019816607bf242c043a data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_wood.json -49fd097bf3182fcdd2cf180dc333f7fe853b586c data/create/recipes/cutting/compat/twilightforest/stripped_mining_log.json -4f231e9c88cc7441a097effd59caca0ff8c7b291 data/create/recipes/cutting/compat/twilightforest/stripped_mining_wood.json -939d8b45db3554e7d9a6157ab13889606f5926ec data/create/recipes/cutting/compat/twilightforest/stripped_sorting_log.json -a4beff8b63bfcaef2e14fc74eaf991a2f0e09b09 data/create/recipes/cutting/compat/twilightforest/stripped_sorting_wood.json -1388f289e43aa0b7a4642af5fff252602dd274c4 data/create/recipes/cutting/compat/twilightforest/stripped_time_log.json -6f21b5b4c2d4aee61ac2d990fee1651def801a67 data/create/recipes/cutting/compat/twilightforest/stripped_time_wood.json -c7c462798f3935b300e0fbc1a616736276e13292 data/create/recipes/cutting/compat/twilightforest/stripped_transformation_log.json -4770650398d3787991fa0dde2274611e241ab330 data/create/recipes/cutting/compat/twilightforest/stripped_transformation_wood.json -d87200bda38ba06d6eaf732e05ba74110cb888e5 data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_log.json -d1a18db626fb8c1ed4684e99154a73f1ba94c341 data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_wood.json -bc6a18b90847c9e27a28c19a391fd343237f1788 data/create/recipes/cutting/compat/twilightforest/time_log.json -d9ea151935b7257f9a799be5959d736a20eabf44 data/create/recipes/cutting/compat/twilightforest/time_wood.json -917862f3314fd636f65ef8ca1826182cce386ee2 data/create/recipes/cutting/compat/twilightforest/transformation_log.json -29649f4c23ddc00eebe7352dcca0d4c695807c62 data/create/recipes/cutting/compat/twilightforest/transformation_wood.json -10227f5cf8a9995f7e59c509ad20a33f907a1203 data/create/recipes/cutting/compat/twilightforest/twilight_oak_log.json -60c949a998c4ffe6f838faf729ef9a7a247a59df data/create/recipes/cutting/compat/twilightforest/twilight_oak_wood.json -b6c3111236dea7685ed893a2ddab6bacbb606170 data/create/recipes/cutting/compat/upgrade_aquatic/driftwood.json -b86b4710a31b8ab98d3f61972fd0e3a80d1cb788 data/create/recipes/cutting/compat/upgrade_aquatic/driftwood_log.json -1a155ced39a05ccbaa1fcd57052c8acced381860 data/create/recipes/cutting/compat/upgrade_aquatic/river_log.json -9b29505252b5c529d86e24c9c53d1190e73537d7 data/create/recipes/cutting/compat/upgrade_aquatic/river_wood.json -1104de0e8917d4fa8e51b036b573ef54bfbc7980 data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood.json -3fd253db6046bd5276cac5aea203f5293a49f843 data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood_log.json -ab08c98c58c2beab4805d0576cac3874c4774553 data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_log.json -b368756fa5ec34fa279f53fb99aea8f47757828a data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_wood.json -2619c5f3916147bf13a21f986f1889a67f885d1b data/create/recipes/cutting/compat/windswept/chestnut_log.json -40068203261db20d74bd84fa8c9e9a6fa9fc4ef5 data/create/recipes/cutting/compat/windswept/chestnut_wood.json -70a5cf4ac9996f9f424c064fc39fab8901f5c71c data/create/recipes/cutting/compat/windswept/holly_log.json -28833896273e3da215da3dee4da13e43ac56aecf data/create/recipes/cutting/compat/windswept/holly_wood.json -0e20d4166a792d5beba3e3ca17beb61253ceb162 data/create/recipes/cutting/compat/windswept/stripped_chestnut_log.json -33de028562009de6bdccd54f5b3835b7bbfe06a7 data/create/recipes/cutting/compat/windswept/stripped_chestnut_wood.json -68ddfcd839417094d75e889ed42ea244d07e2c0f data/create/recipes/cutting/compat/windswept/stripped_holly_log.json -a22e7839d935d0aca9de371ba50d956e0cbfa137 data/create/recipes/cutting/compat/windswept/stripped_holly_wood.json -0a3c2e35782d54a28c3c60eae10bdd6247d5977f data/create/recipes/cutting/crimson_hyphae.json -cc4d09728d2407c0c972e696037d1b45db9a8bc2 data/create/recipes/cutting/crimson_stem.json -ebdf404a6de7880a42527c35727fa4214eb8cff3 data/create/recipes/cutting/dark_oak_log.json -5b3eab6a44b9c76e6317254214991128450c0cd7 data/create/recipes/cutting/dark_oak_wood.json -8dc8b46f4e75470466806da9d851db52a8166baf data/create/recipes/cutting/jungle_log.json -e34df7cc80df6139a0f77cd5f7b8b17b0abbffa9 data/create/recipes/cutting/jungle_wood.json -7f2d46fb9d896915469177e1647615de926cac08 data/create/recipes/cutting/mangrove_log.json -9f6520bfecff967456ca5c529810e1245e51bebd data/create/recipes/cutting/mangrove_wood.json -3617011bd39d6cdc5b9b326272d19df0b3510590 data/create/recipes/cutting/oak_log.json -554409e54c85164ae8e832208623f3400fd80750 data/create/recipes/cutting/oak_wood.json -0e67c6e6685d4b752b129456c607039a203d341a data/create/recipes/cutting/spruce_log.json -85cf63074b922696ea691cfbc2cf7c348d4e0977 data/create/recipes/cutting/spruce_wood.json -1e83972fa75e6cef279da72312ae0577e6b074a3 data/create/recipes/cutting/stripped_acacia_log.json -070aa9790369a368666c03bf1cea9643ed0e5bc7 data/create/recipes/cutting/stripped_acacia_wood.json 558e81291da72b7f042b3b3270744b2c05ddc6fa data/create/recipes/cutting/stripped_bamboo_block.json -944dc5880749a146067716dd34b7edef77b925f5 data/create/recipes/cutting/stripped_birch_log.json -0ce39eb489b8d876954cbfcf715e94af79a57119 data/create/recipes/cutting/stripped_birch_wood.json -67c248e1be1e67054d4a65b94396d874156d5f29 data/create/recipes/cutting/stripped_cherry_log.json -1e34d2b0a2ae375ee312ca49aaaad8ff9e35b465 data/create/recipes/cutting/stripped_cherry_wood.json -b90e5b0a18d6d2e7eae62d0caf41fb3dd597c1e9 data/create/recipes/cutting/stripped_crimson_hyphae.json -7244f0450df30a3b08139a1a43c82d3dfcc9f9a7 data/create/recipes/cutting/stripped_crimson_stem.json -fc37b271373157c95e306bb33b6585dae45d3edb data/create/recipes/cutting/stripped_dark_oak_log.json -a6ea6cec83389e333fb5f4a422043a1bd9f70f32 data/create/recipes/cutting/stripped_dark_oak_wood.json -7ec8691fc9236ded232cbac0454fb0f8ea57949b data/create/recipes/cutting/stripped_jungle_log.json -a8970a4ea88a0c3c75df9ab5e7a70e6ed385f5ce data/create/recipes/cutting/stripped_jungle_wood.json -6e96401efad8c35011369717614cd0f81f45c71b data/create/recipes/cutting/stripped_mangrove_log.json -a31d2317362342119530798385f12e76402fc0e8 data/create/recipes/cutting/stripped_mangrove_wood.json -4ff147a23e6314ab02b904b9026970f9a2498c99 data/create/recipes/cutting/stripped_oak_log.json -ba1eb67a609cecffd2ec06cb21a17191960bbc67 data/create/recipes/cutting/stripped_oak_wood.json -4c212147311aec6714936a630b95c5102d50acf9 data/create/recipes/cutting/stripped_spruce_log.json -d9f2558fd566bc362c8330b26d201b2774a530ea data/create/recipes/cutting/stripped_spruce_wood.json -58b61b31381bd7d663a6575b074dfb4bec8a50d3 data/create/recipes/cutting/stripped_warped_hyphae.json -39060c0293e8681bbce3444f702c1ec5cae967fb data/create/recipes/cutting/stripped_warped_stem.json -ddb27a32c1b01812db7cc317c962e35d794dae88 data/create/recipes/cutting/warped_hyphae.json -688e5c5719ce1c6a331cd9ac05ba21fdb2da96a9 data/create/recipes/cutting/warped_stem.json 7a01147d3c7d8fb9acb870b33e5a792328f88c3c data/create/recipes/deploying/cogwheel.json +71823595ba3f587a0940125d87f2d33a99d317d8 data/create/recipes/deploying/copper_block_from_deoxidising.json +2e94155860aae80bc3c66e92cb0815cf259dfff4 data/create/recipes/deploying/copper_block_from_removing_wax.json +05053abe2e15cc6eb885c220e7c4fcac983611eb data/create/recipes/deploying/copper_shingles_from_deoxidising.json +aec726a5c61af90cd67bf30b8f3db07253fd42d0 data/create/recipes/deploying/copper_shingles_from_removing_wax.json +728e234e700be32ee721e245e274eb050ef4f606 data/create/recipes/deploying/copper_shingle_slab_from_deoxidising.json +e46c329904515063d9fc58c3006b432248d84ebe data/create/recipes/deploying/copper_shingle_slab_from_removing_wax.json +a44bf77f812215cdb6bb24f2bbf97667ce7db990 data/create/recipes/deploying/copper_shingle_stairs_from_deoxidising.json +7e1fddd9635b98e778eb122f5a000618d16b11c2 data/create/recipes/deploying/copper_shingle_stairs_from_removing_wax.json +c0960ea4e0379f56b653262052fb2de3c4b0bce7 data/create/recipes/deploying/copper_tiles_from_deoxidising.json +4920419c9bd94d05c237b6b8b12c4d2e4795bf42 data/create/recipes/deploying/copper_tiles_from_removing_wax.json +67dc0704987c703fd49183994e6470e104858a95 data/create/recipes/deploying/copper_tile_slab_from_deoxidising.json +7e7f8c3decba1506b22b72b644a2025318fc8822 data/create/recipes/deploying/copper_tile_slab_from_removing_wax.json +a6eaa28d82bda3f6b24b408f7c67aab88c93829e data/create/recipes/deploying/copper_tile_stairs_from_deoxidising.json +4066d8d646a9ce873cac5177beb2fa107b290956 data/create/recipes/deploying/copper_tile_stairs_from_removing_wax.json +a45a2f53e770e9f7435b0159e2a6ffe13d91d82d data/create/recipes/deploying/cut_copper_from_deoxidising.json +a0f38792e9b993a793e6c35a4e0e0c68906218c9 data/create/recipes/deploying/cut_copper_from_removing_wax.json +45db539abee9c99e5683f993b003bfe4e27afa67 data/create/recipes/deploying/cut_copper_slab_from_deoxidising.json +7cf609fef56ed53becf7a55e134aaa2d1093ab40 data/create/recipes/deploying/cut_copper_slab_from_removing_wax.json +cffe8fdd5375773b8d91cd375c3d47e03774675f data/create/recipes/deploying/cut_copper_stairs_from_deoxidising.json +4fb27e34f4315be61b0708c53800ee72bf6809a1 data/create/recipes/deploying/cut_copper_stairs_from_removing_wax.json +13bf7a638b279a2b84d68bbcde2ef2a0e6957f97 data/create/recipes/deploying/exposed_copper_from_deoxidising.json +faaa8eab8175bb55c7ade06491d0be3419a2258d data/create/recipes/deploying/exposed_copper_from_removing_wax.json +09353cbd6cd87e622668303cc83d5cf6c96d14f4 data/create/recipes/deploying/exposed_copper_shingles_from_deoxidising.json +e5f64c97b09c9609f2bfb1c7e9a931f016144961 data/create/recipes/deploying/exposed_copper_shingles_from_removing_wax.json +9bac720038284c15807b1af46fb737061fc408e1 data/create/recipes/deploying/exposed_copper_shingle_slab_from_deoxidising.json +ff63016d6a4e3d3fabc233e1c343524b0cd3eec6 data/create/recipes/deploying/exposed_copper_shingle_slab_from_removing_wax.json +cb0dff707a1ce997c60475397e694087d235288d data/create/recipes/deploying/exposed_copper_shingle_stairs_from_deoxidising.json +ff93d9667bc252c5f7323d6613756ad884499eac data/create/recipes/deploying/exposed_copper_shingle_stairs_from_removing_wax.json +9c5491e571dbd52a758bacc77fd193d3f435d19f data/create/recipes/deploying/exposed_copper_tiles_from_deoxidising.json +72359d16366ce29ba88f2536c2af82e7ba33af92 data/create/recipes/deploying/exposed_copper_tiles_from_removing_wax.json +6ec863a95f4bdd0917f9cacec5c02e09ef843b34 data/create/recipes/deploying/exposed_copper_tile_slab_from_deoxidising.json +68777658e9ecac0653cd22a154edd7af06b36138 data/create/recipes/deploying/exposed_copper_tile_slab_from_removing_wax.json +fc936eb34042c2fdb751a4f5b53c7bd283aa8f82 data/create/recipes/deploying/exposed_copper_tile_stairs_from_deoxidising.json +ea381bc5a0adcb7f1b74e7dac02e988b5e93f056 data/create/recipes/deploying/exposed_copper_tile_stairs_from_removing_wax.json +1612bd37a109f7876ac03c5988dc7d6ddfad0ff8 data/create/recipes/deploying/exposed_cut_copper_from_deoxidising.json +6151c9f5925ead0056d338fdfd673500902e417d data/create/recipes/deploying/exposed_cut_copper_from_removing_wax.json +a44eaf00ef5e746c62aa72552a37447676fcd385 data/create/recipes/deploying/exposed_cut_copper_slab_from_deoxidising.json +3ae4559c67d0a390c2dd4deb3a17df8aab66bb64 data/create/recipes/deploying/exposed_cut_copper_slab_from_removing_wax.json +5ecc9b889c9012616454d3ddeff1608fe87a0f93 data/create/recipes/deploying/exposed_cut_copper_stairs_from_deoxidising.json +98ac326a1e2c80fd0f3cb73c7ad80b86ba7cf980 data/create/recipes/deploying/exposed_cut_copper_stairs_from_removing_wax.json 1230f449873262e79585752d3430e5f7f383bcb2 data/create/recipes/deploying/large_cogwheel.json +051faceb93f5cba4be8632198272500bcf461334 data/create/recipes/deploying/oxidized_copper_from_removing_wax.json +00cad77046b42466fb40798f11480d7370cab579 data/create/recipes/deploying/oxidized_copper_shingles_from_removing_wax.json +deecff3e485442af83fb01d16b0a46d98e5214bb data/create/recipes/deploying/oxidized_copper_shingle_slab_from_removing_wax.json +162ddbeb10da4eec0709813d3f55465a658e76d1 data/create/recipes/deploying/oxidized_copper_shingle_stairs_from_removing_wax.json +6f4ad2120309481203e1ac839263099bb7e36ea0 data/create/recipes/deploying/oxidized_copper_tiles_from_removing_wax.json +dff292537e007aabdffdf997509838c6168799b4 data/create/recipes/deploying/oxidized_copper_tile_slab_from_removing_wax.json +42cc953f2f2cf2b2af7d3d1480abf6d7d363abec data/create/recipes/deploying/oxidized_copper_tile_stairs_from_removing_wax.json +58e6abf60ee8d830143fa6a48830c3d20acfc8c0 data/create/recipes/deploying/oxidized_cut_copper_from_removing_wax.json +52eb357d1d13edc250726f70c7b3639cb902a933 data/create/recipes/deploying/oxidized_cut_copper_slab_from_removing_wax.json +5daf82089854fda3a264b26303fe02764539a87e data/create/recipes/deploying/oxidized_cut_copper_stairs_from_removing_wax.json dc35369da8514a5650704fd39e84861cce084b5d data/create/recipes/deploying/waxed_copper_block_from_adding_wax.json 7b7d596cdaa4000222177b405c04c6e8906561b4 data/create/recipes/deploying/waxed_copper_shingles_from_adding_wax.json afbe0c612651ee90651ee7b39683c8baac2a115e data/create/recipes/deploying/waxed_copper_shingle_slab_from_adding_wax.json @@ -755,6 +325,26 @@ d0fc937a3e7ae42fb1891b7b87adb2b57292e01d data/create/recipes/deploying/waxed_wea 9ab3ba5847c3abbc17c476436978141f2c039ce9 data/create/recipes/deploying/waxed_weathered_cut_copper_from_adding_wax.json 733dd94b46186c19fdecced5d8231e46ea612cf2 data/create/recipes/deploying/waxed_weathered_cut_copper_slab_from_adding_wax.json cd4c050e6ad9227bf293768f2d8b965c0ecafeab data/create/recipes/deploying/waxed_weathered_cut_copper_stairs_from_adding_wax.json +20c2fefb17fcdde2b817b1634d805dececf8b0e5 data/create/recipes/deploying/weathered_copper_from_deoxidising.json +ba026a1c407eca2f8acc66a10a1fcc97cb318b1e data/create/recipes/deploying/weathered_copper_from_removing_wax.json +5e01f5da2ad67a939a7630bf2607a0159d1dd177 data/create/recipes/deploying/weathered_copper_shingles_from_deoxidising.json +7f962473189c296c02f5e97fa3e920cc7e26f112 data/create/recipes/deploying/weathered_copper_shingles_from_removing_wax.json +4c903ea6449f7ef494c66e20671a323b6703fa05 data/create/recipes/deploying/weathered_copper_shingle_slab_from_deoxidising.json +231350a2d36a11b5848052fe20e11f32b0cd7838 data/create/recipes/deploying/weathered_copper_shingle_slab_from_removing_wax.json +94cb495f52ca2b88b8680a6bcd2d326a91357e0c data/create/recipes/deploying/weathered_copper_shingle_stairs_from_deoxidising.json +0160f12204d05b0f094a7b7d189692501aa90ed0 data/create/recipes/deploying/weathered_copper_shingle_stairs_from_removing_wax.json +6210a2a41161ff2d0ceca8ca209954af4c63002a data/create/recipes/deploying/weathered_copper_tiles_from_deoxidising.json +03ad0e1d06b1197fa45db23d73eb9f76a45944f8 data/create/recipes/deploying/weathered_copper_tiles_from_removing_wax.json +3f218e4ab4a52d0df55725088c4128582c9b6918 data/create/recipes/deploying/weathered_copper_tile_slab_from_deoxidising.json +18bbbcdbf4e57e6fe567b3494f492332745cd6fc data/create/recipes/deploying/weathered_copper_tile_slab_from_removing_wax.json +a24e82558aa7aee7840f6310531cec46b626cee4 data/create/recipes/deploying/weathered_copper_tile_stairs_from_deoxidising.json +6b8b807ebd14158d2d14c5210d5c60c781d112db data/create/recipes/deploying/weathered_copper_tile_stairs_from_removing_wax.json +45dfc86b09a4b777974026697bfd444063920374 data/create/recipes/deploying/weathered_cut_copper_from_deoxidising.json +b19f74374347bb123ad32b9d1bb680763467fe1d data/create/recipes/deploying/weathered_cut_copper_from_removing_wax.json +58cf0f39fd70e58a97a8458907ea6af393efe5b8 data/create/recipes/deploying/weathered_cut_copper_slab_from_deoxidising.json +5c63c7500f25ca09c348b24c077f79f315d958b3 data/create/recipes/deploying/weathered_cut_copper_slab_from_removing_wax.json +5458bc361b6022323c7aeed19cbd4f9d278b55bb data/create/recipes/deploying/weathered_cut_copper_stairs_from_deoxidising.json +0e05f35e930aa74cc64c91f5a69615aaa0e52565 data/create/recipes/deploying/weathered_cut_copper_stairs_from_removing_wax.json 6a9fa669a5cbdc2406ecc5eaf6992e0e8fa83b88 data/create/recipes/emptying/builders_tea.json 0b20bddac967edea53442c05c59ccf3306e9eb76 data/create/recipes/emptying/compat/alexsmobs/lava_bottle.json 5fb7e705b53ed84b607858be1db6a6d2765bea9c data/create/recipes/emptying/compat/farmersdelight/milk_bottle.json @@ -767,6 +357,7 @@ aea7837e33bfcbdd1e0b4386372b6595fd00ad1d data/create/recipes/filling/builders_te f158f5e509b43746871722edf802984e2b9cc024 data/create/recipes/filling/compat/alexsmobs/lava_bottle.json 5770b60bd7e89f2cac74df71b463a1101601d86f data/create/recipes/filling/compat/byg/lush_grass_block.json 1280689ba81877c6583c6941ed307ca35d4f00e4 data/create/recipes/filling/compat/farmersdelight/milk_bottle.json +a48a8862847dab2a75f8e2710203ed5f7d00533e data/create/recipes/filling/compat/immersiveengineering/treated_wood_in_spout.json fd578bb1e05901d0b959b1f445273619b55cde57 data/create/recipes/filling/compat/neapolitan/milk_bottle.json 3f0f458c0c044c7b1c4e203d7394d890ba286d86 data/create/recipes/filling/compat/regions_unexplored/peat_grass_block.json ff16c74f09edbc67ed969f64270ca376bb8ea955 data/create/recipes/filling/compat/regions_unexplored/silt_grass_block.json @@ -802,6 +393,7 @@ a701fb82072d60320aa9b0280fa58c58296e8e42 data/create/recipes/haunting/soul_sand. b18c81c17d395fb6e9291fc010576914000f069d data/create/recipes/haunting/warped_fungus.json 409c94b597bc0e35cce51282428fc02b919bb55e data/create/recipes/item_application/andesite_casing_from_log.json 4816a96aa0117b826ec01f9351c98eaec4e132fd data/create/recipes/item_application/andesite_casing_from_wood.json +59b5145feb9f433aaab98bb7e3f1070499768210 data/create/recipes/item_application/bound_cardboard_inworld.json ac734bd72012ab3f0fd362fdcf237191874e1eae data/create/recipes/item_application/brass_casing_from_log.json df1d95a4e41fb01d0ac240f89dcf734e00d92853 data/create/recipes/item_application/brass_casing_from_wood.json a9e164ba47552af7df82f011080d981420388bc6 data/create/recipes/item_application/copper_casing_from_log.json @@ -1018,6 +610,7 @@ a91dae829938d3f69a7007d3cf8db02b70fe3a7f data/create/recipes/milling/white_tulip 5f1b8a82af091cd4589ecfa5c13a4db6ad9c51b9 data/create/recipes/mixing/andesite_alloy.json 48604c2205b18fe1401eac58d14aa1677cbd9c2b data/create/recipes/mixing/andesite_alloy_from_zinc.json d06c1d0362dccc4e5f8b22f851dc8316b35c06b0 data/create/recipes/mixing/brass_ingot.json +84a789f57691cb1e515f98cb162d7eda416eae7a data/create/recipes/mixing/cardboard_pulp.json 840a9008d4531425beadfcf224d21e938acc4502 data/create/recipes/mixing/chocolate.json e7b86d4ca5de2df474794424d93b447e5f9dcdc3 data/create/recipes/mixing/chocolate_melting.json 39e832016fa5e360434271505d09ced17a40e7eb data/create/recipes/mixing/compat/ae2/fluix_crystal.json @@ -1031,19 +624,28 @@ ac2a2456e2f0ccd74db6dc5ad029eb4e6781a25d data/create/recipes/mixing/honey.json 77de88a8d25b974a63a5d132dd5461523e798fe2 data/create/recipes/pressing/aether_dirt_path.json 92a1198c990660458565ca871520b7c32fb0e24b data/create/recipes/pressing/aether_dirt_path_from_grass.json 8bd950c78b4db3b7f5a9a1f42c116677049b77fc data/create/recipes/pressing/brass_ingot.json +6ceffc42f77201423f42b537b0567d0213c4427d data/create/recipes/pressing/cardboard.json 1fe1caaec87a1a7b3cd739c372829f48386d2f8a data/create/recipes/pressing/compat/atmospheric/crustose_path.json 4d4821506da8c82eabc6109d1cfcb4fa980e54c8 data/create/recipes/pressing/compat/betterendforge/amber_moss_path.json 16c653a9c8771662d060a6151fa77ab4ce8d2614 data/create/recipes/pressing/compat/betterendforge/cave_moss_path.json e715dd1d3961de8a817ddcd6a1c411761966e57e data/create/recipes/pressing/compat/betterendforge/chorus_nylium_path.json 29a514bea64e7e3f7fe04c2d19749d174b4e42b3 data/create/recipes/pressing/compat/betterendforge/crystal_moss_path.json 7b377ce79e3e32a7b3fece940fb0b234d255e3fe data/create/recipes/pressing/compat/betterendforge/end_moss_path.json -17c68db229cef447679eeba25da1fe7de17be50d data/create/recipes/pressing/compat/betterendforge/end_myclium_path.json +e4df3cd1f80b62382ea0941c3dde030c67dba03f data/create/recipes/pressing/compat/betterendforge/end_mycelium_path.json fb6d54e0ee3c8831060a8573d16814217888ae0e data/create/recipes/pressing/compat/betterendforge/jungle_moss_path.json 77dbbdd01f36f1ede5018bc1feb3dff960988129 data/create/recipes/pressing/compat/betterendforge/pink_moss_path.json 200b0a7f459b4c5f5bd7d6fe46ad1959923b9cb0 data/create/recipes/pressing/compat/betterendforge/shadow_grass_path.json 8a53f6ea8dab59477d462eb929f7815f52b34095 data/create/recipes/pressing/compat/byg/lush_grass_path.json 4454d7dda6c2b5555227c5c147373df195adedb4 data/create/recipes/pressing/compat/environmental/mycelium_path.json ed3edcf493402051fcff435a5840295b218a078c data/create/recipes/pressing/compat/environmental/podzol_path.json +39fc8e85aad2f06ca042905b2398fde9fec13a74 data/create/recipes/pressing/compat/immersiveengineering/plate_aluminum.json +479f7dd3e3223cb5795c12881d0dec767eccc483 data/create/recipes/pressing/compat/immersiveengineering/plate_constantan.json +556d43a7920d6258a1511e4be44dc39f133009a3 data/create/recipes/pressing/compat/immersiveengineering/plate_electrum.json +d559dccf3e58486731af81e595fc4e250c10d54a data/create/recipes/pressing/compat/immersiveengineering/plate_lead.json +b5af4395d9602909be9373821c951006afcf4734 data/create/recipes/pressing/compat/immersiveengineering/plate_nickel.json +8e16e97cb74efd7340dd5bde1c586cc8cad372ee data/create/recipes/pressing/compat/immersiveengineering/plate_silver.json +fe79367892205e41c39332663a235e07fbfb695e data/create/recipes/pressing/compat/immersiveengineering/plate_steel.json +ca7a836c4eff7d0dbf01726726258401ee98795b data/create/recipes/pressing/compat/immersiveengineering/plate_uranium.json 0afcbaa527a8063982caf9a541d1af43fe6becbb data/create/recipes/pressing/compat/infernalexp/crimson_nylium_path.json 621f9c7eae4f6f5065ecd48ffe1b0c5c9e6147d3 data/create/recipes/pressing/compat/infernalexp/soul_soil_path.json e049a1c6951c93a53122fc5adb27bee35ca62786 data/create/recipes/pressing/compat/infernalexp/warped_nylium_path.json @@ -1052,7 +654,7 @@ e049a1c6951c93a53122fc5adb27bee35ca62786 data/create/recipes/pressing/compat/inf 24bb356954866c69a279a9f0435035d8bafdddec data/create/recipes/pressing/cursed_earth_path_from_grass.json 744e1a66857f20a094ba02a3e3613210a815493e data/create/recipes/pressing/gold_ingot.json fb105ac920ce9dc0b883bfa40029b69709bceb38 data/create/recipes/pressing/iron_ingot.json -daf5c0c9e3f13d2004d53c54f4c1c36ae098d1ae data/create/recipes/pressing/path.json +747264a014a851af703660d4f189bfdb159466ff data/create/recipes/pressing/path.json 1c1224d02f5f9941d2e99620fa68767ba5578603 data/create/recipes/pressing/peat_dirt_path.json 3fbfc3b129748f2e5f1964f1e797812d331c8719 data/create/recipes/pressing/peat_dirt_path_from_grass.json a2330ec4b822b3109efdf86a244ffa5b71e3a16c data/create/recipes/pressing/silt_dirt_path.json @@ -1094,6 +696,9 @@ b5a0a0fc79bf310965aa16e78044b3f6a8a9998f data/create/recipes/splashing/ic2/crush 6707b4319280ce28e1edd594e58549f65cd8376c data/create/recipes/splashing/immersiveengineering/crushed_raw_nickel.json d379607eda7fba5048751d806a245d58e91acc1f data/create/recipes/splashing/immersiveengineering/crushed_raw_silver.json 8afc0810a0166a62d8d394f2841d27e7f7a3e6c5 data/create/recipes/splashing/immersiveengineering/crushed_raw_uranium.json +cafec636b007eeb5df2092824464c91661a13004 data/create/recipes/splashing/industrial_iron_block.json +38ed0fb231d19ed30ba3debc0bebf8ffbc5f5a72 data/create/recipes/splashing/industrial_iron_window.json +ffede841a2104f7266425288bd328e7236ebd9e4 data/create/recipes/splashing/industrial_iron_window_pane.json 676a409aadcbf2497b366234c5186c6192a67c8d data/create/recipes/splashing/light_blue_concrete_powder.json d4053dba524524329f43df5bdde81d9ee07838b5 data/create/recipes/splashing/light_gray_concrete_powder.json 3d87975758344a4e420c3c5a138dd300e97cf3c4 data/create/recipes/splashing/lime_concrete_powder.json diff --git a/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 b/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 index 4184c4f4cf..aeebf148e8 100644 --- a/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 +++ b/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 @@ -1,2 +1,2 @@ -// 1.20.1 2024-10-09T12:24:59.2018604 Create's Custom Sounds -bcfd9320f8ed54f3282b1757a41da0d1753e1754 assets/create/sounds.json +// 1.20.1 2025-02-02T11:59:39.428609 Create's Custom Sounds +0bca17432111ff732e5188cd3098201330e386bc assets/create/sounds.json diff --git a/src/generated/resources/.cache/e0a39a97205b7149114f15de91b614248d05fd95 b/src/generated/resources/.cache/e0a39a97205b7149114f15de91b614248d05fd95 index ba866d79a0..efe7fb1321 100644 --- a/src/generated/resources/.cache/e0a39a97205b7149114f15de91b614248d05fd95 +++ b/src/generated/resources/.cache/e0a39a97205b7149114f15de91b614248d05fd95 @@ -1,2 +1,2 @@ -// 1.20.1 2024-10-09T12:24:59.2646915 Create's Recipe Serializer Tags +// 1.20.1 2025-02-02T11:59:39.5950933 Create's Recipe Serializer Tags 0d8718f7383761bc5d7bc45306ed266ebf25dc1d data/create/tags/recipe_serializer/automation_ignore.json diff --git a/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e b/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e index 5a2a21ad8f..154112cac0 100644 --- a/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e +++ b/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e @@ -1,4 +1,29 @@ -// 1.20.1 2024-10-09T12:24:59.2666858 Create's Generated Registry Entries +// 1.20.1 2025-02-27T16:48:57.1024754 Create's Generated Registry Entries +abb9dd2c98388abb430343d4ac02d460e5edc086 data/create/create/potato_projectile/type/apple.json +1a20cb4e64dc07918a28fbccc73102bca3560f16 data/create/create/potato_projectile/type/baked_potato.json +8450576952f7723d22250da6f554dd0fda4e9fce data/create/create/potato_projectile/type/beetroot.json +9d927ec9c8b76a093e7ff8ff8f81be3a438d4aba data/create/create/potato_projectile/type/blaze_cake.json +46ccaf468caaa4faaca4f1494f60e99cd00785c9 data/create/create/potato_projectile/type/cake.json +6cef3daecf686b417c6dfbe02556fcdff9b1e417 data/create/create/potato_projectile/type/carrot.json +af17d72549ee9421d2643a215ffc2291874fff93 data/create/create/potato_projectile/type/chocolate_berry.json +8cb4811601d46db5fdc0291edce3ec2f3a64e902 data/create/create/potato_projectile/type/chorus_fruit.json +9dd1298993a4657d69a9d2ac4de3ad7879d9aa8d data/create/create/potato_projectile/type/enchanted_golden_apple.json +e3ab3c4bd70ad742d37091ae05774aadffb1d1d5 data/create/create/potato_projectile/type/fallback.json +98bf0ce51484c5a9709fc69d046d0c70d987cfdd data/create/create/potato_projectile/type/fish.json +afe4e7cc87110d6f045f6672fb312a09290ca04a data/create/create/potato_projectile/type/glistering_melon.json +050c9333d41efd2577e1e597c7c68b00436b0963 data/create/create/potato_projectile/type/glow_berry.json +52046463af1abc92c5257992c302d7ab26c63e28 data/create/create/potato_projectile/type/golden_apple.json +c6234751ccad5111857b0ae9e297e42f529ad32a data/create/create/potato_projectile/type/golden_carrot.json +583b75978a4f920c2969473e5353fcc89886b612 data/create/create/potato_projectile/type/honeyed_apple.json +0a968b4dd96cd7743336b0cce76eafae59a10a6a data/create/create/potato_projectile/type/melon_block.json +352402ba2fff3f23af178d15d61b0ba0a151097a data/create/create/potato_projectile/type/melon_slice.json +cbfd3028ad878bddbdaeb0eec0cd5a1c50d4c901 data/create/create/potato_projectile/type/poison_potato.json +38116c664c63ca9da0ea043edc16a3ce9264c706 data/create/create/potato_projectile/type/potato.json +d15070ca23129e7d4025d86cb4be5701a466e593 data/create/create/potato_projectile/type/pufferfish.json +63e2df2c83982204bc92479b1df26561922e795d data/create/create/potato_projectile/type/pumpkin_block.json +7d58a0671c55e40cdb728c60152665c89209fb91 data/create/create/potato_projectile/type/pumpkin_pie.json +0e73e50b02e9afe5f170729935ae5921d22d7091 data/create/create/potato_projectile/type/suspicious_stew.json +b4a7c10bd9cdcfe67df2a5766e5ec2e35a3f9b24 data/create/create/potato_projectile/type/sweet_berry.json 030ede1044384c4117ac1e491bf5c78bbd2842f5 data/create/damage_type/crush.json 92b0416950ffeb3ba68811e587177c2f8811c2c5 data/create/damage_type/cuckoo_surprise.json d2a4fdb64f4ba817e13a7b20c73fd1ca34b825fc data/create/damage_type/fan_fire.json diff --git a/src/generated/resources/.cache/f5350c6189acfbe5425c2432489f46008c69099a b/src/generated/resources/.cache/f5350c6189acfbe5425c2432489f46008c69099a new file mode 100644 index 0000000000..a185aa953b --- /dev/null +++ b/src/generated/resources/.cache/f5350c6189acfbe5425c2432489f46008c69099a @@ -0,0 +1,3 @@ +// 1.20.1 2025-02-20T19:36:44.18737762 Create's Mounted Item Storage Type Tags +c65f95f356db09e468847e5799a2cdd8e1417cac data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json +fdadceec842a4cd12dd95f7e271645a52829ec6e data/create/tags/create/mounted_item_storage_type/internal.json diff --git a/src/generated/resources/assets/create/blockstates/andesite_table_cloth.json b/src/generated/resources/assets/create/blockstates/andesite_table_cloth.json new file mode 100644 index 0000000000..e5afa390f5 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/andesite_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/andesite_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/bamboo_window.json b/src/generated/resources/assets/create/blockstates/bamboo_window.json new file mode 100644 index 0000000000..1c3d582245 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/bamboo_window.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/bamboo_window" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/bamboo_window_pane.json b/src/generated/resources/assets/create/blockstates/bamboo_window_pane.json new file mode 100644 index 0000000000..08a969744e --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/bamboo_window_pane.json @@ -0,0 +1,77 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/bamboo_window_pane_post" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_noside" + }, + "when": { + "north": "false" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_noside_alt", + "y": 90 + }, + "when": { + "south": "false" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_noside", + "y": 270 + }, + "when": { + "west": "false" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/bamboo_window_pane_noside_alt" + }, + "when": { + "east": "false" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/black_postbox.json b/src/generated/resources/assets/create/blockstates/black_postbox.json new file mode 100644 index 0000000000..767cf098ed --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/black_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/black_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/black_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/black_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/black_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/black_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/black_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/black_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/black_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/black_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/black_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/black_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/black_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/black_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/black_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/black_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/black_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/black_table_cloth.json b/src/generated/resources/assets/create/blockstates/black_table_cloth.json new file mode 100644 index 0000000000..c359608ab8 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/black_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/black_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/blue_postbox.json b/src/generated/resources/assets/create/blockstates/blue_postbox.json new file mode 100644 index 0000000000..2397fcbcea --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/blue_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/blue_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/blue_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/blue_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/blue_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/blue_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/blue_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/blue_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/blue_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/blue_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/blue_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/blue_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/blue_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/blue_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/blue_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/blue_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/blue_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/blue_table_cloth.json b/src/generated/resources/assets/create/blockstates/blue_table_cloth.json new file mode 100644 index 0000000000..d0a8ea92fa --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/blue_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/blue_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/bound_cardboard_block.json b/src/generated/resources/assets/create/blockstates/bound_cardboard_block.json new file mode 100644 index 0000000000..7f9aae8a0e --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/bound_cardboard_block.json @@ -0,0 +1,11 @@ +{ + "variants": { + "axis=x": { + "model": "create:block/bound_cardboard_block", + "y": 90 + }, + "axis=z": { + "model": "create:block/bound_cardboard_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brass_table_cloth.json b/src/generated/resources/assets/create/blockstates/brass_table_cloth.json new file mode 100644 index 0000000000..e7d0f7161c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brass_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/brass_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brown_postbox.json b/src/generated/resources/assets/create/blockstates/brown_postbox.json new file mode 100644 index 0000000000..ae56daf98b --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brown_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/brown_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/brown_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/brown_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/brown_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/brown_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/brown_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/brown_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/brown_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/brown_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/brown_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/brown_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/brown_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/brown_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/brown_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/brown_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/brown_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brown_table_cloth.json b/src/generated/resources/assets/create/blockstates/brown_table_cloth.json new file mode 100644 index 0000000000..20a016bf8b --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brown_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/brown_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/cardboard_block.json b/src/generated/resources/assets/create/blockstates/cardboard_block.json new file mode 100644 index 0000000000..0ffaa202ae --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/cardboard_block.json @@ -0,0 +1,11 @@ +{ + "variants": { + "axis=x": { + "model": "create:block/cardboard_block", + "y": 90 + }, + "axis=z": { + "model": "create:block/cardboard_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/chain_conveyor.json b/src/generated/resources/assets/create/blockstates/chain_conveyor.json new file mode 100644 index 0000000000..164b69102f --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/chain_conveyor.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/chain_conveyor/block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/cherry_window.json b/src/generated/resources/assets/create/blockstates/cherry_window.json new file mode 100644 index 0000000000..c842e75dbc --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/cherry_window.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/cherry_window" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/cherry_window_pane.json b/src/generated/resources/assets/create/blockstates/cherry_window_pane.json new file mode 100644 index 0000000000..4232dc3a56 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/cherry_window_pane.json @@ -0,0 +1,77 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/cherry_window_pane_post" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_noside" + }, + "when": { + "north": "false" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_noside_alt", + "y": 90 + }, + "when": { + "south": "false" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_noside", + "y": 270 + }, + "when": { + "west": "false" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/cherry_window_pane_noside_alt" + }, + "when": { + "east": "false" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copper_table_cloth.json b/src/generated/resources/assets/create/blockstates/copper_table_cloth.json new file mode 100644 index 0000000000..6cd6309dd0 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copper_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/copper_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/cyan_postbox.json b/src/generated/resources/assets/create/blockstates/cyan_postbox.json new file mode 100644 index 0000000000..cdd8d6cdbe --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/cyan_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/cyan_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/cyan_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/cyan_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/cyan_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/cyan_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/cyan_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/cyan_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/cyan_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/cyan_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/cyan_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/cyan_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/cyan_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/cyan_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/cyan_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/cyan_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/cyan_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/cyan_table_cloth.json b/src/generated/resources/assets/create/blockstates/cyan_table_cloth.json new file mode 100644 index 0000000000..66a0514db9 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/cyan_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/cyan_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/desk_bell.json b/src/generated/resources/assets/create/blockstates/desk_bell.json new file mode 100644 index 0000000000..6ef28ee2bd --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/desk_bell.json @@ -0,0 +1,108 @@ +{ + "variants": { + "facing=down,powered=false,waterlogged=false": { + "model": "create:block/desk_bell/block", + "x": 180 + }, + "facing=down,powered=false,waterlogged=true": { + "model": "create:block/desk_bell/block", + "x": 180 + }, + "facing=down,powered=true,waterlogged=false": { + "model": "create:block/desk_bell/block_powered", + "x": 180 + }, + "facing=down,powered=true,waterlogged=true": { + "model": "create:block/desk_bell/block_powered", + "x": 180 + }, + "facing=east,powered=false,waterlogged=false": { + "model": "create:block/desk_bell/block", + "x": 90, + "y": 90 + }, + "facing=east,powered=false,waterlogged=true": { + "model": "create:block/desk_bell/block", + "x": 90, + "y": 90 + }, + "facing=east,powered=true,waterlogged=false": { + "model": "create:block/desk_bell/block_powered", + "x": 90, + "y": 90 + }, + "facing=east,powered=true,waterlogged=true": { + "model": "create:block/desk_bell/block_powered", + "x": 90, + "y": 90 + }, + "facing=north,powered=false,waterlogged=false": { + "model": "create:block/desk_bell/block", + "x": 90 + }, + "facing=north,powered=false,waterlogged=true": { + "model": "create:block/desk_bell/block", + "x": 90 + }, + "facing=north,powered=true,waterlogged=false": { + "model": "create:block/desk_bell/block_powered", + "x": 90 + }, + "facing=north,powered=true,waterlogged=true": { + "model": "create:block/desk_bell/block_powered", + "x": 90 + }, + "facing=south,powered=false,waterlogged=false": { + "model": "create:block/desk_bell/block", + "x": 90, + "y": 180 + }, + "facing=south,powered=false,waterlogged=true": { + "model": "create:block/desk_bell/block", + "x": 90, + "y": 180 + }, + "facing=south,powered=true,waterlogged=false": { + "model": "create:block/desk_bell/block_powered", + "x": 90, + "y": 180 + }, + "facing=south,powered=true,waterlogged=true": { + "model": "create:block/desk_bell/block_powered", + "x": 90, + "y": 180 + }, + "facing=up,powered=false,waterlogged=false": { + "model": "create:block/desk_bell/block" + }, + "facing=up,powered=false,waterlogged=true": { + "model": "create:block/desk_bell/block" + }, + "facing=up,powered=true,waterlogged=false": { + "model": "create:block/desk_bell/block_powered" + }, + "facing=up,powered=true,waterlogged=true": { + "model": "create:block/desk_bell/block_powered" + }, + "facing=west,powered=false,waterlogged=false": { + "model": "create:block/desk_bell/block", + "x": 90, + "y": 270 + }, + "facing=west,powered=false,waterlogged=true": { + "model": "create:block/desk_bell/block", + "x": 90, + "y": 270 + }, + "facing=west,powered=true,waterlogged=false": { + "model": "create:block/desk_bell/block_powered", + "x": 90, + "y": 270 + }, + "facing=west,powered=true,waterlogged=true": { + "model": "create:block/desk_bell/block_powered", + "x": 90, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/factory_gauge.json b/src/generated/resources/assets/create/blockstates/factory_gauge.json new file mode 100644 index 0000000000..d4f7371962 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/factory_gauge.json @@ -0,0 +1,216 @@ +{ + "variants": { + "face=ceiling,facing=east,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=north,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=south,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180 + }, + "face=ceiling,facing=south,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180 + }, + "face=ceiling,facing=south,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180 + }, + "face=ceiling,facing=south,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180 + }, + "face=ceiling,facing=west,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 180, + "y": 90 + }, + "face=floor,facing=east,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "y": 90 + }, + "face=floor,facing=east,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "y": 90 + }, + "face=floor,facing=east,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "y": 90 + }, + "face=floor,facing=east,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "y": 90 + }, + "face=floor,facing=north,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block" + }, + "face=floor,facing=north,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block" + }, + "face=floor,facing=north,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block" + }, + "face=floor,facing=north,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block" + }, + "face=floor,facing=south,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "y": 180 + }, + "face=floor,facing=south,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "y": 180 + }, + "face=floor,facing=south,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "y": 180 + }, + "face=floor,facing=south,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "y": 180 + }, + "face=floor,facing=west,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "y": 270 + }, + "face=floor,facing=west,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "y": 270 + }, + "face=floor,facing=west,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "y": 270 + }, + "face=floor,facing=west,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "y": 270 + }, + "face=wall,facing=east,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 90 + }, + "face=wall,facing=east,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 90 + }, + "face=wall,facing=east,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 90 + }, + "face=wall,facing=east,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 90 + }, + "face=wall,facing=north,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90 + }, + "face=wall,facing=north,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90 + }, + "face=wall,facing=north,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90 + }, + "face=wall,facing=north,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90 + }, + "face=wall,facing=south,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 180 + }, + "face=wall,facing=south,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 180 + }, + "face=wall,facing=south,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 180 + }, + "face=wall,facing=south,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 180 + }, + "face=wall,facing=west,powered=false,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 270 + }, + "face=wall,facing=west,powered=false,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 270 + }, + "face=wall,facing=west,powered=true,waterlogged=false": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 270 + }, + "face=wall,facing=west,powered=true,waterlogged=true": { + "model": "create:block/factory_gauge/block", + "x": 90, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/gray_postbox.json b/src/generated/resources/assets/create/blockstates/gray_postbox.json new file mode 100644 index 0000000000..57cccf10f3 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/gray_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/gray_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/gray_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/gray_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/gray_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/gray_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/gray_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/gray_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/gray_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/gray_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/gray_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/gray_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/gray_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/gray_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/gray_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/gray_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/gray_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/gray_table_cloth.json b/src/generated/resources/assets/create/blockstates/gray_table_cloth.json new file mode 100644 index 0000000000..1e5e2e933e --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/gray_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/gray_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/green_postbox.json b/src/generated/resources/assets/create/blockstates/green_postbox.json new file mode 100644 index 0000000000..eca9b46cbe --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/green_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/green_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/green_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/green_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/green_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/green_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/green_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/green_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/green_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/green_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/green_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/green_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/green_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/green_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/green_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/green_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/green_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/green_table_cloth.json b/src/generated/resources/assets/create/blockstates/green_table_cloth.json new file mode 100644 index 0000000000..4ccbf5efee --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/green_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/green_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/industrial_iron_window.json b/src/generated/resources/assets/create/blockstates/industrial_iron_window.json new file mode 100644 index 0000000000..d8645c1c56 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/industrial_iron_window.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/industrial_iron_window" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/industrial_iron_window_pane.json b/src/generated/resources/assets/create/blockstates/industrial_iron_window_pane.json new file mode 100644 index 0000000000..4f32186a04 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/industrial_iron_window_pane.json @@ -0,0 +1,77 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/industrial_iron_window_pane_post" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_noside" + }, + "when": { + "north": "false" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_noside_alt", + "y": 90 + }, + "when": { + "south": "false" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_noside", + "y": 270 + }, + "when": { + "west": "false" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/industrial_iron_window_pane_noside_alt" + }, + "when": { + "east": "false" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/item_hatch.json b/src/generated/resources/assets/create/blockstates/item_hatch.json new file mode 100644 index 0000000000..24bcd00bca --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/item_hatch.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/item_hatch/block_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/item_hatch/block_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/item_hatch/block_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/item_hatch/block_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/item_hatch/block_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/item_hatch/block_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/item_hatch/block_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/item_hatch/block_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/item_hatch/block_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/item_hatch/block_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/item_hatch/block_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/item_hatch/block_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/item_hatch/block_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/item_hatch/block_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/item_hatch/block_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/item_hatch/block_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_blue_postbox.json b/src/generated/resources/assets/create/blockstates/light_blue_postbox.json new file mode 100644 index 0000000000..c173112b4a --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_blue_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/light_blue_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/light_blue_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/light_blue_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/light_blue_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/light_blue_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/light_blue_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/light_blue_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/light_blue_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/light_blue_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/light_blue_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/light_blue_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/light_blue_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/light_blue_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/light_blue_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/light_blue_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/light_blue_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_blue_table_cloth.json b/src/generated/resources/assets/create/blockstates/light_blue_table_cloth.json new file mode 100644 index 0000000000..8159350160 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_blue_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/light_blue_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_gray_postbox.json b/src/generated/resources/assets/create/blockstates/light_gray_postbox.json new file mode 100644 index 0000000000..349cdb096d --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_gray_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/light_gray_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/light_gray_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/light_gray_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/light_gray_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/light_gray_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/light_gray_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/light_gray_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/light_gray_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/light_gray_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/light_gray_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/light_gray_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/light_gray_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/light_gray_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/light_gray_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/light_gray_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/light_gray_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/light_gray_table_cloth.json b/src/generated/resources/assets/create/blockstates/light_gray_table_cloth.json new file mode 100644 index 0000000000..78cfebd35b --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/light_gray_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/light_gray_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/lime_postbox.json b/src/generated/resources/assets/create/blockstates/lime_postbox.json new file mode 100644 index 0000000000..fa172a8a21 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/lime_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/lime_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/lime_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/lime_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/lime_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/lime_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/lime_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/lime_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/lime_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/lime_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/lime_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/lime_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/lime_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/lime_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/lime_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/lime_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/lime_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/lime_table_cloth.json b/src/generated/resources/assets/create/blockstates/lime_table_cloth.json new file mode 100644 index 0000000000..f289b982f0 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/lime_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/lime_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/magenta_postbox.json b/src/generated/resources/assets/create/blockstates/magenta_postbox.json new file mode 100644 index 0000000000..cfcf86db84 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/magenta_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/magenta_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/magenta_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/magenta_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/magenta_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/magenta_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/magenta_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/magenta_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/magenta_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/magenta_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/magenta_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/magenta_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/magenta_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/magenta_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/magenta_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/magenta_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/magenta_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/magenta_table_cloth.json b/src/generated/resources/assets/create/blockstates/magenta_table_cloth.json new file mode 100644 index 0000000000..723a59f08c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/magenta_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/magenta_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/orange_postbox.json b/src/generated/resources/assets/create/blockstates/orange_postbox.json new file mode 100644 index 0000000000..d55bdc68e5 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/orange_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/orange_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/orange_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/orange_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/orange_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/orange_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/orange_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/orange_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/orange_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/orange_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/orange_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/orange_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/orange_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/orange_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/orange_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/orange_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/orange_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/orange_table_cloth.json b/src/generated/resources/assets/create/blockstates/orange_table_cloth.json new file mode 100644 index 0000000000..2bfe470433 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/orange_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/orange_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/package_frogport.json b/src/generated/resources/assets/create/blockstates/package_frogport.json new file mode 100644 index 0000000000..36509ad6ed --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/package_frogport.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/package_frogport/block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/packager.json b/src/generated/resources/assets/create/blockstates/packager.json new file mode 100644 index 0000000000..fc7a5a9466 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/packager.json @@ -0,0 +1,88 @@ +{ + "variants": { + "facing=down,linked=false,powered=false": { + "model": "create:block/packager/block_vertical" + }, + "facing=down,linked=false,powered=true": { + "model": "create:block/packager/block_vertical_powered" + }, + "facing=down,linked=true,powered=false": { + "model": "create:block/packager/block_vertical_linked" + }, + "facing=down,linked=true,powered=true": { + "model": "create:block/packager/block_vertical_linked" + }, + "facing=east,linked=false,powered=false": { + "model": "create:block/packager/block", + "y": 270 + }, + "facing=east,linked=false,powered=true": { + "model": "create:block/packager/block_powered", + "y": 270 + }, + "facing=east,linked=true,powered=false": { + "model": "create:block/packager/block_linked", + "y": 270 + }, + "facing=east,linked=true,powered=true": { + "model": "create:block/packager/block_linked", + "y": 270 + }, + "facing=north,linked=false,powered=false": { + "model": "create:block/packager/block", + "y": 180 + }, + "facing=north,linked=false,powered=true": { + "model": "create:block/packager/block_powered", + "y": 180 + }, + "facing=north,linked=true,powered=false": { + "model": "create:block/packager/block_linked", + "y": 180 + }, + "facing=north,linked=true,powered=true": { + "model": "create:block/packager/block_linked", + "y": 180 + }, + "facing=south,linked=false,powered=false": { + "model": "create:block/packager/block" + }, + "facing=south,linked=false,powered=true": { + "model": "create:block/packager/block_powered" + }, + "facing=south,linked=true,powered=false": { + "model": "create:block/packager/block_linked" + }, + "facing=south,linked=true,powered=true": { + "model": "create:block/packager/block_linked" + }, + "facing=up,linked=false,powered=false": { + "model": "create:block/packager/block_vertical" + }, + "facing=up,linked=false,powered=true": { + "model": "create:block/packager/block_vertical_powered" + }, + "facing=up,linked=true,powered=false": { + "model": "create:block/packager/block_vertical_linked" + }, + "facing=up,linked=true,powered=true": { + "model": "create:block/packager/block_vertical_linked" + }, + "facing=west,linked=false,powered=false": { + "model": "create:block/packager/block", + "y": 90 + }, + "facing=west,linked=false,powered=true": { + "model": "create:block/packager/block_powered", + "y": 90 + }, + "facing=west,linked=true,powered=false": { + "model": "create:block/packager/block_linked", + "y": 90 + }, + "facing=west,linked=true,powered=true": { + "model": "create:block/packager/block_linked", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/pink_postbox.json b/src/generated/resources/assets/create/blockstates/pink_postbox.json new file mode 100644 index 0000000000..6f81984689 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/pink_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/pink_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/pink_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/pink_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/pink_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/pink_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/pink_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/pink_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/pink_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/pink_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/pink_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/pink_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/pink_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/pink_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/pink_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/pink_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/pink_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/pink_table_cloth.json b/src/generated/resources/assets/create/blockstates/pink_table_cloth.json new file mode 100644 index 0000000000..1d3cb73684 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/pink_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/pink_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/pulse_timer.json b/src/generated/resources/assets/create/blockstates/pulse_timer.json new file mode 100644 index 0000000000..9bafc697fe --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/pulse_timer.json @@ -0,0 +1,124 @@ +{ + "variants": { + "facing=east,inverted=false,powered=false,powering=false": { + "model": "create:block/diodes/pulse_timer", + "y": 270 + }, + "facing=east,inverted=false,powered=false,powering=true": { + "model": "create:block/pulse_timer_powering", + "y": 270 + }, + "facing=east,inverted=false,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered", + "y": 270 + }, + "facing=east,inverted=false,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered_powering", + "y": 270 + }, + "facing=east,inverted=true,powered=false,powering=false": { + "model": "create:block/pulse_timer_powering", + "y": 270 + }, + "facing=east,inverted=true,powered=false,powering=true": { + "model": "create:block/diodes/pulse_timer", + "y": 270 + }, + "facing=east,inverted=true,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered_powering", + "y": 270 + }, + "facing=east,inverted=true,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered", + "y": 270 + }, + "facing=north,inverted=false,powered=false,powering=false": { + "model": "create:block/diodes/pulse_timer", + "y": 180 + }, + "facing=north,inverted=false,powered=false,powering=true": { + "model": "create:block/pulse_timer_powering", + "y": 180 + }, + "facing=north,inverted=false,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered", + "y": 180 + }, + "facing=north,inverted=false,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered_powering", + "y": 180 + }, + "facing=north,inverted=true,powered=false,powering=false": { + "model": "create:block/pulse_timer_powering", + "y": 180 + }, + "facing=north,inverted=true,powered=false,powering=true": { + "model": "create:block/diodes/pulse_timer", + "y": 180 + }, + "facing=north,inverted=true,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered_powering", + "y": 180 + }, + "facing=north,inverted=true,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered", + "y": 180 + }, + "facing=south,inverted=false,powered=false,powering=false": { + "model": "create:block/diodes/pulse_timer" + }, + "facing=south,inverted=false,powered=false,powering=true": { + "model": "create:block/pulse_timer_powering" + }, + "facing=south,inverted=false,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered" + }, + "facing=south,inverted=false,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered_powering" + }, + "facing=south,inverted=true,powered=false,powering=false": { + "model": "create:block/pulse_timer_powering" + }, + "facing=south,inverted=true,powered=false,powering=true": { + "model": "create:block/diodes/pulse_timer" + }, + "facing=south,inverted=true,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered_powering" + }, + "facing=south,inverted=true,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered" + }, + "facing=west,inverted=false,powered=false,powering=false": { + "model": "create:block/diodes/pulse_timer", + "y": 90 + }, + "facing=west,inverted=false,powered=false,powering=true": { + "model": "create:block/pulse_timer_powering", + "y": 90 + }, + "facing=west,inverted=false,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered", + "y": 90 + }, + "facing=west,inverted=false,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered_powering", + "y": 90 + }, + "facing=west,inverted=true,powered=false,powering=false": { + "model": "create:block/pulse_timer_powering", + "y": 90 + }, + "facing=west,inverted=true,powered=false,powering=true": { + "model": "create:block/diodes/pulse_timer", + "y": 90 + }, + "facing=west,inverted=true,powered=true,powering=false": { + "model": "create:block/pulse_timer_powered_powering", + "y": 90 + }, + "facing=west,inverted=true,powered=true,powering=true": { + "model": "create:block/pulse_timer_powered", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/purple_postbox.json b/src/generated/resources/assets/create/blockstates/purple_postbox.json new file mode 100644 index 0000000000..63b5e90a41 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/purple_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/purple_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/purple_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/purple_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/purple_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/purple_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/purple_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/purple_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/purple_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/purple_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/purple_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/purple_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/purple_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/purple_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/purple_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/purple_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/purple_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/purple_table_cloth.json b/src/generated/resources/assets/create/blockstates/purple_table_cloth.json new file mode 100644 index 0000000000..2e1621cac0 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/purple_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/purple_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/red_postbox.json b/src/generated/resources/assets/create/blockstates/red_postbox.json new file mode 100644 index 0000000000..932b9a2520 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/red_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/red_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/red_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/red_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/red_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/red_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/red_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/red_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/red_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/red_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/red_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/red_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/red_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/red_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/red_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/red_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/red_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/red_table_cloth.json b/src/generated/resources/assets/create/blockstates/red_table_cloth.json new file mode 100644 index 0000000000..bb9720b06c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/red_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/red_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/redstone_requester.json b/src/generated/resources/assets/create/blockstates/redstone_requester.json new file mode 100644 index 0000000000..2dad3ceb28 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/redstone_requester.json @@ -0,0 +1,18 @@ +{ + "variants": { + "axis=x,powered=false": { + "model": "create:block/redstone_requester/block", + "y": 90 + }, + "axis=x,powered=true": { + "model": "create:block/redstone_requester/block_powered", + "y": 90 + }, + "axis=z,powered=false": { + "model": "create:block/redstone_requester/block" + }, + "axis=z,powered=true": { + "model": "create:block/redstone_requester/block_powered" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/repackager.json b/src/generated/resources/assets/create/blockstates/repackager.json new file mode 100644 index 0000000000..dcd004db3c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/repackager.json @@ -0,0 +1,46 @@ +{ + "variants": { + "facing=down,powered=false": { + "model": "create:block/repackager/block_vertical" + }, + "facing=down,powered=true": { + "model": "create:block/repackager/block_vertical_powered" + }, + "facing=east,powered=false": { + "model": "create:block/repackager/block", + "y": 270 + }, + "facing=east,powered=true": { + "model": "create:block/repackager/block_powered", + "y": 270 + }, + "facing=north,powered=false": { + "model": "create:block/repackager/block", + "y": 180 + }, + "facing=north,powered=true": { + "model": "create:block/repackager/block_powered", + "y": 180 + }, + "facing=south,powered=false": { + "model": "create:block/repackager/block" + }, + "facing=south,powered=true": { + "model": "create:block/repackager/block_powered" + }, + "facing=up,powered=false": { + "model": "create:block/repackager/block_vertical" + }, + "facing=up,powered=true": { + "model": "create:block/repackager/block_vertical_powered" + }, + "facing=west,powered=false": { + "model": "create:block/repackager/block", + "y": 90 + }, + "facing=west,powered=true": { + "model": "create:block/repackager/block_powered", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/stock_link.json b/src/generated/resources/assets/create/blockstates/stock_link.json new file mode 100644 index 0000000000..d256e0a8f1 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/stock_link.json @@ -0,0 +1,200 @@ +{ + "variants": { + "face=ceiling,facing=east,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=north,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=south,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical", + "x": 180 + }, + "face=ceiling,facing=south,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical", + "x": 180 + }, + "face=ceiling,facing=south,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180 + }, + "face=ceiling,facing=south,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180 + }, + "face=ceiling,facing=west,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered", + "x": 180, + "y": 90 + }, + "face=floor,facing=east,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical", + "y": 270 + }, + "face=floor,facing=east,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical", + "y": 270 + }, + "face=floor,facing=east,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered", + "y": 270 + }, + "face=floor,facing=east,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered", + "y": 270 + }, + "face=floor,facing=north,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical", + "y": 180 + }, + "face=floor,facing=north,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical", + "y": 180 + }, + "face=floor,facing=north,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered", + "y": 180 + }, + "face=floor,facing=north,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered", + "y": 180 + }, + "face=floor,facing=south,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical" + }, + "face=floor,facing=south,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical" + }, + "face=floor,facing=south,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered" + }, + "face=floor,facing=south,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered" + }, + "face=floor,facing=west,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_vertical", + "y": 90 + }, + "face=floor,facing=west,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_vertical", + "y": 90 + }, + "face=floor,facing=west,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_vertical_powered", + "y": 90 + }, + "face=floor,facing=west,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_vertical_powered", + "y": 90 + }, + "face=wall,facing=east,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal", + "y": 270 + }, + "face=wall,facing=east,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal", + "y": 270 + }, + "face=wall,facing=east,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal_powered", + "y": 270 + }, + "face=wall,facing=east,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal_powered", + "y": 270 + }, + "face=wall,facing=north,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal", + "y": 180 + }, + "face=wall,facing=north,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal", + "y": 180 + }, + "face=wall,facing=north,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal_powered", + "y": 180 + }, + "face=wall,facing=north,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal_powered", + "y": 180 + }, + "face=wall,facing=south,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal" + }, + "face=wall,facing=south,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal" + }, + "face=wall,facing=south,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal_powered" + }, + "face=wall,facing=south,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal_powered" + }, + "face=wall,facing=west,powered=false,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal", + "y": 90 + }, + "face=wall,facing=west,powered=false,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal", + "y": 90 + }, + "face=wall,facing=west,powered=true,waterlogged=false": { + "model": "create:block/stock_link/block_horizontal_powered", + "y": 90 + }, + "face=wall,facing=west,powered=true,waterlogged=true": { + "model": "create:block/stock_link/block_horizontal_powered", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/stock_ticker.json b/src/generated/resources/assets/create/blockstates/stock_ticker.json new file mode 100644 index 0000000000..5e7770d38f --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/stock_ticker.json @@ -0,0 +1,19 @@ +{ + "variants": { + "facing=east": { + "model": "create:block/stock_ticker", + "y": 90 + }, + "facing=north": { + "model": "create:block/stock_ticker" + }, + "facing=south": { + "model": "create:block/stock_ticker", + "y": 180 + }, + "facing=west": { + "model": "create:block/stock_ticker", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/stockpile_switch.json b/src/generated/resources/assets/create/blockstates/stockpile_switch.json index 10e03d9c43..85016aac51 100644 --- a/src/generated/resources/assets/create/blockstates/stockpile_switch.json +++ b/src/generated/resources/assets/create/blockstates/stockpile_switch.json @@ -1,273 +1,273 @@ { "variants": { "facing=east,level=0,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_0", + "model": "create:block/threshold_switch/block_ceiling_0", "y": 90 }, "facing=east,level=0,target=floor": { - "model": "create:threshold_switch/block_floor_0", + "model": "create:block/threshold_switch/block_floor_0", "y": 90 }, "facing=east,level=0,target=wall": { - "model": "create:threshold_switch/block_wall_0", + "model": "create:block/threshold_switch/block_wall_0", "y": 90 }, "facing=east,level=1,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_1", + "model": "create:block/threshold_switch/block_ceiling_1", "y": 90 }, "facing=east,level=1,target=floor": { - "model": "create:threshold_switch/block_floor_1", + "model": "create:block/threshold_switch/block_floor_1", "y": 90 }, "facing=east,level=1,target=wall": { - "model": "create:threshold_switch/block_wall_1", + "model": "create:block/threshold_switch/block_wall_1", "y": 90 }, "facing=east,level=2,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_2", + "model": "create:block/threshold_switch/block_ceiling_2", "y": 90 }, "facing=east,level=2,target=floor": { - "model": "create:threshold_switch/block_floor_2", + "model": "create:block/threshold_switch/block_floor_2", "y": 90 }, "facing=east,level=2,target=wall": { - "model": "create:threshold_switch/block_wall_2", + "model": "create:block/threshold_switch/block_wall_2", "y": 90 }, "facing=east,level=3,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_3", + "model": "create:block/threshold_switch/block_ceiling_3", "y": 90 }, "facing=east,level=3,target=floor": { - "model": "create:threshold_switch/block_floor_3", + "model": "create:block/threshold_switch/block_floor_3", "y": 90 }, "facing=east,level=3,target=wall": { - "model": "create:threshold_switch/block_wall_3", + "model": "create:block/threshold_switch/block_wall_3", "y": 90 }, "facing=east,level=4,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_4", + "model": "create:block/threshold_switch/block_ceiling_4", "y": 90 }, "facing=east,level=4,target=floor": { - "model": "create:threshold_switch/block_floor_4", + "model": "create:block/threshold_switch/block_floor_4", "y": 90 }, "facing=east,level=4,target=wall": { - "model": "create:threshold_switch/block_wall_4", + "model": "create:block/threshold_switch/block_wall_4", "y": 90 }, "facing=east,level=5,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_5", + "model": "create:block/threshold_switch/block_ceiling_5", "y": 90 }, "facing=east,level=5,target=floor": { - "model": "create:threshold_switch/block_floor_5", + "model": "create:block/threshold_switch/block_floor_5", "y": 90 }, "facing=east,level=5,target=wall": { - "model": "create:threshold_switch/block_wall_5", + "model": "create:block/threshold_switch/block_wall_5", "y": 90 }, "facing=north,level=0,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_0" + "model": "create:block/threshold_switch/block_ceiling_0" }, "facing=north,level=0,target=floor": { - "model": "create:threshold_switch/block_floor_0" + "model": "create:block/threshold_switch/block_floor_0" }, "facing=north,level=0,target=wall": { - "model": "create:threshold_switch/block_wall_0" + "model": "create:block/threshold_switch/block_wall_0" }, "facing=north,level=1,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_1" + "model": "create:block/threshold_switch/block_ceiling_1" }, "facing=north,level=1,target=floor": { - "model": "create:threshold_switch/block_floor_1" + "model": "create:block/threshold_switch/block_floor_1" }, "facing=north,level=1,target=wall": { - "model": "create:threshold_switch/block_wall_1" + "model": "create:block/threshold_switch/block_wall_1" }, "facing=north,level=2,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_2" + "model": "create:block/threshold_switch/block_ceiling_2" }, "facing=north,level=2,target=floor": { - "model": "create:threshold_switch/block_floor_2" + "model": "create:block/threshold_switch/block_floor_2" }, "facing=north,level=2,target=wall": { - "model": "create:threshold_switch/block_wall_2" + "model": "create:block/threshold_switch/block_wall_2" }, "facing=north,level=3,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_3" + "model": "create:block/threshold_switch/block_ceiling_3" }, "facing=north,level=3,target=floor": { - "model": "create:threshold_switch/block_floor_3" + "model": "create:block/threshold_switch/block_floor_3" }, "facing=north,level=3,target=wall": { - "model": "create:threshold_switch/block_wall_3" + "model": "create:block/threshold_switch/block_wall_3" }, "facing=north,level=4,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_4" + "model": "create:block/threshold_switch/block_ceiling_4" }, "facing=north,level=4,target=floor": { - "model": "create:threshold_switch/block_floor_4" + "model": "create:block/threshold_switch/block_floor_4" }, "facing=north,level=4,target=wall": { - "model": "create:threshold_switch/block_wall_4" + "model": "create:block/threshold_switch/block_wall_4" }, "facing=north,level=5,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_5" + "model": "create:block/threshold_switch/block_ceiling_5" }, "facing=north,level=5,target=floor": { - "model": "create:threshold_switch/block_floor_5" + "model": "create:block/threshold_switch/block_floor_5" }, "facing=north,level=5,target=wall": { - "model": "create:threshold_switch/block_wall_5" + "model": "create:block/threshold_switch/block_wall_5" }, "facing=south,level=0,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_0", + "model": "create:block/threshold_switch/block_ceiling_0", "y": 180 }, "facing=south,level=0,target=floor": { - "model": "create:threshold_switch/block_floor_0", + "model": "create:block/threshold_switch/block_floor_0", "y": 180 }, "facing=south,level=0,target=wall": { - "model": "create:threshold_switch/block_wall_0", + "model": "create:block/threshold_switch/block_wall_0", "y": 180 }, "facing=south,level=1,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_1", + "model": "create:block/threshold_switch/block_ceiling_1", "y": 180 }, "facing=south,level=1,target=floor": { - "model": "create:threshold_switch/block_floor_1", + "model": "create:block/threshold_switch/block_floor_1", "y": 180 }, "facing=south,level=1,target=wall": { - "model": "create:threshold_switch/block_wall_1", + "model": "create:block/threshold_switch/block_wall_1", "y": 180 }, "facing=south,level=2,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_2", + "model": "create:block/threshold_switch/block_ceiling_2", "y": 180 }, "facing=south,level=2,target=floor": { - "model": "create:threshold_switch/block_floor_2", + "model": "create:block/threshold_switch/block_floor_2", "y": 180 }, "facing=south,level=2,target=wall": { - "model": "create:threshold_switch/block_wall_2", + "model": "create:block/threshold_switch/block_wall_2", "y": 180 }, "facing=south,level=3,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_3", + "model": "create:block/threshold_switch/block_ceiling_3", "y": 180 }, "facing=south,level=3,target=floor": { - "model": "create:threshold_switch/block_floor_3", + "model": "create:block/threshold_switch/block_floor_3", "y": 180 }, "facing=south,level=3,target=wall": { - "model": "create:threshold_switch/block_wall_3", + "model": "create:block/threshold_switch/block_wall_3", "y": 180 }, "facing=south,level=4,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_4", + "model": "create:block/threshold_switch/block_ceiling_4", "y": 180 }, "facing=south,level=4,target=floor": { - "model": "create:threshold_switch/block_floor_4", + "model": "create:block/threshold_switch/block_floor_4", "y": 180 }, "facing=south,level=4,target=wall": { - "model": "create:threshold_switch/block_wall_4", + "model": "create:block/threshold_switch/block_wall_4", "y": 180 }, "facing=south,level=5,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_5", + "model": "create:block/threshold_switch/block_ceiling_5", "y": 180 }, "facing=south,level=5,target=floor": { - "model": "create:threshold_switch/block_floor_5", + "model": "create:block/threshold_switch/block_floor_5", "y": 180 }, "facing=south,level=5,target=wall": { - "model": "create:threshold_switch/block_wall_5", + "model": "create:block/threshold_switch/block_wall_5", "y": 180 }, "facing=west,level=0,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_0", + "model": "create:block/threshold_switch/block_ceiling_0", "y": 270 }, "facing=west,level=0,target=floor": { - "model": "create:threshold_switch/block_floor_0", + "model": "create:block/threshold_switch/block_floor_0", "y": 270 }, "facing=west,level=0,target=wall": { - "model": "create:threshold_switch/block_wall_0", + "model": "create:block/threshold_switch/block_wall_0", "y": 270 }, "facing=west,level=1,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_1", + "model": "create:block/threshold_switch/block_ceiling_1", "y": 270 }, "facing=west,level=1,target=floor": { - "model": "create:threshold_switch/block_floor_1", + "model": "create:block/threshold_switch/block_floor_1", "y": 270 }, "facing=west,level=1,target=wall": { - "model": "create:threshold_switch/block_wall_1", + "model": "create:block/threshold_switch/block_wall_1", "y": 270 }, "facing=west,level=2,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_2", + "model": "create:block/threshold_switch/block_ceiling_2", "y": 270 }, "facing=west,level=2,target=floor": { - "model": "create:threshold_switch/block_floor_2", + "model": "create:block/threshold_switch/block_floor_2", "y": 270 }, "facing=west,level=2,target=wall": { - "model": "create:threshold_switch/block_wall_2", + "model": "create:block/threshold_switch/block_wall_2", "y": 270 }, "facing=west,level=3,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_3", + "model": "create:block/threshold_switch/block_ceiling_3", "y": 270 }, "facing=west,level=3,target=floor": { - "model": "create:threshold_switch/block_floor_3", + "model": "create:block/threshold_switch/block_floor_3", "y": 270 }, "facing=west,level=3,target=wall": { - "model": "create:threshold_switch/block_wall_3", + "model": "create:block/threshold_switch/block_wall_3", "y": 270 }, "facing=west,level=4,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_4", + "model": "create:block/threshold_switch/block_ceiling_4", "y": 270 }, "facing=west,level=4,target=floor": { - "model": "create:threshold_switch/block_floor_4", + "model": "create:block/threshold_switch/block_floor_4", "y": 270 }, "facing=west,level=4,target=wall": { - "model": "create:threshold_switch/block_wall_4", + "model": "create:block/threshold_switch/block_wall_4", "y": 270 }, "facing=west,level=5,target=ceiling": { - "model": "create:threshold_switch/block_ceiling_5", + "model": "create:block/threshold_switch/block_ceiling_5", "y": 270 }, "facing=west,level=5,target=floor": { - "model": "create:threshold_switch/block_floor_5", + "model": "create:block/threshold_switch/block_floor_5", "y": 270 }, "facing=west,level=5,target=wall": { - "model": "create:threshold_switch/block_wall_5", + "model": "create:block/threshold_switch/block_wall_5", "y": 270 } } diff --git a/src/generated/resources/assets/create/blockstates/weathered_iron_block.json b/src/generated/resources/assets/create/blockstates/weathered_iron_block.json new file mode 100644 index 0000000000..e16d717b98 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/weathered_iron_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/weathered_iron_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/weathered_iron_window.json b/src/generated/resources/assets/create/blockstates/weathered_iron_window.json new file mode 100644 index 0000000000..95b1ba318a --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/weathered_iron_window.json @@ -0,0 +1,18 @@ +{ + "variants": { + "": [ + { + "model": "create:block/weathered_iron_window_1" + }, + { + "model": "create:block/weathered_iron_window_2" + }, + { + "model": "create:block/weathered_iron_window_3" + }, + { + "model": "create:block/weathered_iron_window_4" + } + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/weathered_iron_window_pane.json b/src/generated/resources/assets/create/blockstates/weathered_iron_window_pane.json new file mode 100644 index 0000000000..7fa9fb0536 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/weathered_iron_window_pane.json @@ -0,0 +1,77 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/weathered_iron_window_pane_post" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_noside" + }, + "when": { + "north": "false" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_noside_alt", + "y": 90 + }, + "when": { + "south": "false" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_noside", + "y": 270 + }, + "when": { + "west": "false" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/weathered_iron_window_pane_noside_alt" + }, + "when": { + "east": "false" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/white_postbox.json b/src/generated/resources/assets/create/blockstates/white_postbox.json new file mode 100644 index 0000000000..4bdaba7cb8 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/white_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/white_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/white_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/white_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/white_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/white_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/white_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/white_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/white_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/white_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/white_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/white_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/white_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/white_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/white_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/white_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/white_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/white_table_cloth.json b/src/generated/resources/assets/create/blockstates/white_table_cloth.json new file mode 100644 index 0000000000..235e7d8443 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/white_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/white_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/yellow_postbox.json b/src/generated/resources/assets/create/blockstates/yellow_postbox.json new file mode 100644 index 0000000000..850b13511c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/yellow_postbox.json @@ -0,0 +1,64 @@ +{ + "variants": { + "facing=east,open=false,waterlogged=false": { + "model": "create:block/yellow_postbox_closed", + "y": 90 + }, + "facing=east,open=false,waterlogged=true": { + "model": "create:block/yellow_postbox_closed", + "y": 90 + }, + "facing=east,open=true,waterlogged=false": { + "model": "create:block/yellow_postbox_open", + "y": 90 + }, + "facing=east,open=true,waterlogged=true": { + "model": "create:block/yellow_postbox_open", + "y": 90 + }, + "facing=north,open=false,waterlogged=false": { + "model": "create:block/yellow_postbox_closed" + }, + "facing=north,open=false,waterlogged=true": { + "model": "create:block/yellow_postbox_closed" + }, + "facing=north,open=true,waterlogged=false": { + "model": "create:block/yellow_postbox_open" + }, + "facing=north,open=true,waterlogged=true": { + "model": "create:block/yellow_postbox_open" + }, + "facing=south,open=false,waterlogged=false": { + "model": "create:block/yellow_postbox_closed", + "y": 180 + }, + "facing=south,open=false,waterlogged=true": { + "model": "create:block/yellow_postbox_closed", + "y": 180 + }, + "facing=south,open=true,waterlogged=false": { + "model": "create:block/yellow_postbox_open", + "y": 180 + }, + "facing=south,open=true,waterlogged=true": { + "model": "create:block/yellow_postbox_open", + "y": 180 + }, + "facing=west,open=false,waterlogged=false": { + "model": "create:block/yellow_postbox_closed", + "y": 270 + }, + "facing=west,open=false,waterlogged=true": { + "model": "create:block/yellow_postbox_closed", + "y": 270 + }, + "facing=west,open=true,waterlogged=false": { + "model": "create:block/yellow_postbox_open", + "y": 270 + }, + "facing=west,open=true,waterlogged=true": { + "model": "create:block/yellow_postbox_open", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/yellow_table_cloth.json b/src/generated/resources/assets/create/blockstates/yellow_table_cloth.json new file mode 100644 index 0000000000..1ba52c6649 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/yellow_table_cloth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/yellow_table_cloth" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/lang/en_ud.json b/src/generated/resources/assets/create/lang/en_ud.json index 3c1a15489a..a0f5b82a3d 100644 --- a/src/generated/resources/assets/create/lang/en_ud.json +++ b/src/generated/resources/assets/create/lang/en_ud.json @@ -21,6 +21,12 @@ "advancement.create.brass_casing.desc": "sǝuıɥɔɐɯ pǝʇɐɔıʇsıɥdos ǝɹoɯ ɹoɟ buısɐɔ ɐ buıʇɐǝɹɔ 'pooʍ pǝddıɹʇs oʇ sʇobuI ssɐɹᗺ ʎןddⱯ", "advancement.create.burner": "ǝɔɐןdǝɹıℲ ʇuǝıʇuǝS", "advancement.create.burner.desc": "ɹǝuɹnᗺ ǝzɐןᗺ ɐ uıɐʇqO", + "advancement.create.cardboard": "ןǝɔɹɐԀ puɐ ʇɹɐԀ", + "advancement.create.cardboard.desc": "pɹɐoqpɹɐƆ ʇsɹıɟ ɹnoʎ uıɐʇqo ɹo ǝɔnpoɹԀ", + "advancement.create.cardboard_armor": "ɥʇןɐǝʇS ןןnℲ", + "advancement.create.cardboard_armor.desc": "ɹoɯɹⱯ pɹɐoqpɹɐƆ ןןnɟ uı punoɹɐ ʞɐǝuS", + "advancement.create.cardboard_armor_trim": "sʇɟɐɹƆ puɐ sʇɹⱯ", + "advancement.create.cardboard_armor_trim.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nsɯıɹʇ ɹoɯɹɐ ɥʇıʍ ʇuǝɯdınbǝ pɹɐoqpɹɐɔ ɹnoʎ ǝʇɐɹoɔǝᗡ", "advancement.create.cart_pickup": "sɯɹⱯ buoɹʇS", "advancement.create.cart_pickup.desc": "sʞɔoןq pǝɥɔɐʇʇɐ 00ᄅ ʇsɐǝן ʇɐ ɥʇıʍ uoıʇdɐɹʇuoƆ ʇɹɐɔǝuıW ɐ dn ʞɔıԀ", "advancement.create.chained_drain": "ןןoᴚ ɐ uO", @@ -29,7 +35,7 @@ "advancement.create.chocolate_bucket.desc": "ǝʇɐןoɔoɥɔ uǝʇןoɯ ɟo ʇǝʞɔnq ɐ uıɐʇqO", "advancement.create.chute": "sɔıʇsıboꞀ ןɐɔıʇɹǝΛ", "advancement.create.chute.desc": "ǝʇnɥƆ ʎq sɯǝʇı ǝɯos ʇɹodsuɐɹ⟘", - "advancement.create.clockwork_bearing": "ʞɔoןƆ,O uoıʇdɐɹʇuoƆ", + "advancement.create.clockwork_bearing": "ʞɔoןƆ,o uoıʇdɐɹʇuoƆ", "advancement.create.clockwork_bearing.desc": "buıɹɐǝᗺ ʞɹoʍʞɔoןƆ ɐ uo pǝʇunoɯ ǝɹnʇɔnɹʇs ɐ ǝןqɯǝssⱯ", "advancement.create.compacting": "uoıʇɐɔıɟıʇɔɐdɯoƆ", "advancement.create.compacting.desc": "ǝɹoɯ ɯoɹɟ sɯǝʇı ɹǝʍǝɟ ǝʇɐǝɹɔ oʇ uısɐᗺ ɐ puɐ ssǝɹԀ ןɐɔıuɐɥɔǝW ɐ ǝs∩", @@ -47,9 +53,9 @@ "advancement.create.cross_streams.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nʞɹoʍʇǝu ǝdıd ɹnoʎ uı ʇǝǝɯ spınןɟ oʍʇ ɥɔʇɐM", "advancement.create.crusher_maxed_0000": "ʇI buıɥsnɹƆ", "advancement.create.crusher_maxed_0000.desc": "pǝǝds ɯnɯıxɐɯ ʇɐ sןǝǝɥM buıɥsnɹƆ ɟo ɹıɐd ɐ ǝʇɐɹǝdO", - "advancement.create.crushing_wheel": "sʇuɐı⅁ ɟo ɹıɐԀ Ɐ", + "advancement.create.crushing_wheel": "uoıʇɔnɹʇsǝᗡ ɟo sןǝǝɥM", "advancement.create.crushing_wheel.desc": "sןǝǝɥM buıɥsnɹƆ ɟo ʇǝs ɐ ɹǝʍod puɐ ǝɔɐןԀ", - "advancement.create.cuckoo_clock": "¿ǝɯı⟘ ʇI sI", + "advancement.create.cuckoo_clock": "¿ǝɯı⟘ ʇı sI", "advancement.create.cuckoo_clock.desc": "ǝɯıʇpǝq ǝɔunouuɐ ʞɔoןƆ ooʞɔnƆ ɹnoʎ ssǝuʇıM", "advancement.create.deployer": "ǝɔuǝbıןןǝʇuI ןɐıɔıɟıʇɹⱯ", "advancement.create.deployer.desc": "ɟןǝsɹnoʎ ɟo uoıʇɔǝןɟǝɹ ʇɔǝɟɹǝd ǝɥʇ 'ɹǝʎoןdǝᗡ ɐ ɹǝʍod puɐ ǝɔɐןԀ", @@ -71,12 +77,16 @@ "advancement.create.extendo_grip.desc": "dıɹ⅁ opuǝʇxƎ uɐ ɟo pןoɥ ʇǝ⅁", "advancement.create.extendo_grip_dual": "ʇuǝʇxƎ ןןnℲ o⟘", "advancement.create.extendo_grip_dual.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nɥɔɐǝɹ uɐɯnɥɹǝdns ɹoɟ sdıɹ⅁ opuǝʇxƎ pןǝıʍ-ןɐnᗡ", + "advancement.create.factory_gauge": "sɔıʇsıboꞀ ɥbıH", + "advancement.create.factory_gauge.desc": "sǝbnɐ⅁ ʎɹoʇɔɐℲ buısn ʇsǝnbǝɹ ǝbɐʞɔɐd ɔıʇɐɯoʇnɐ uɐ ɹǝbbıɹ⟘", "advancement.create.fan_processing": "ǝןɔıʇɹɐԀ ʎq buıssǝɔoɹԀ", "advancement.create.fan_processing.desc": "sןɐıɹǝʇɐɯ ssǝɔoɹd oʇ uɐℲ pǝsɐɔuƎ uɐ ǝs∩", "advancement.create.fist_bump": "¡oɹᗺ 'ʇI punoԀ", "advancement.create.fist_bump.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\ndɯnq-ʇsıɟ sɹǝʎoןdǝᗡ oʍʇ ǝʞɐW", "advancement.create.foods": "ʇǝıᗡ pǝɔuɐןɐᗺ", "advancement.create.foods.desc": "ʇnodS ǝɯɐs ǝɥʇ ɯoɹɟ ןןɐ ןןoᴚ ʇǝǝʍS ɐ puɐ 'ǝןddⱯ pǝʎǝuoH ɐ 'sǝıɹɹǝᗺ pǝzɐן⅁ ǝʇɐןoɔoɥƆ ǝʇɐǝɹƆ", + "advancement.create.frogport": "sɹǝddoɥ ʎɹbunH", + "advancement.create.frogport.desc": "ʇɹodboɹℲ ɐ buısn ɹoʎǝʌuoƆ uıɐɥƆ ɹnoʎ ɯoɹɟ sǝbɐʞɔɐd ɥɔʇɐƆ", "advancement.create.funnel": "ɔıʇǝɥʇsǝⱯ ʇɹodɹıⱯ", "advancement.create.funnel.desc": "ןǝuunℲ ɐ buısn ɹǝuıɐʇuoɔ ɐ oʇuı sɯǝʇı ʇɹǝsuı ɹo ʇɔɐɹʇxƎ", "advancement.create.glass_pipe": "ʎɹǝʌoɔsıᗡ ʍoןℲ", @@ -113,9 +123,13 @@ "advancement.create.millstone.desc": "sןɐıɹǝʇɐɯ ǝsıɹǝʌןnd oʇ ǝuoʇsןןıW ɐ ǝs∩", "advancement.create.musical_arm": "oɔıuɐɥɔǝW ſᗡ", "advancement.create.musical_arm.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nxoqǝʞnſ ɹnoʎ ǝʇɐɹǝdo ɯɹⱯ ןɐɔıuɐɥɔǝW ɐ ɥɔʇɐM", + "advancement.create.package_chute_throw": "ʇǝu ʇnq buıɥʇoN", + "advancement.create.package_chute_throw.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nǝʇnɥɔ ɯǝʇı uɐ uı ʍoɹɥʇ ǝbɐʞɔɐd pɹɐoqpɹɐɔ ɹnoʎ puɐꞀ", + "advancement.create.packager": "uoıʇɔnpoɹԀ ʇsoԀ", + "advancement.create.packager.desc": "ɹǝbɐʞɔɐԀ ǝɥʇ buısn ʎɹoʇuǝʌuı uɐ ɯoɹɟ sɯǝʇı ǝbɐʞɔɐԀ", "advancement.create.pipe_organ": "uɐbɹO ǝdıԀ ǝɥ⟘", "advancement.create.pipe_organ.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nʞuɐ⟘ pınןℲ ǝןbuıs ɐ oʇ sǝןʇsıɥM ɯɐǝʇS pǝɥɔʇıd ʎןǝnbıun ᄅƖ ɥɔɐʇʇⱯ", - "advancement.create.portable_storage_interface": "ǝbuɐɥɔxƎ ʎᗺ-ǝʌıɹᗡ", + "advancement.create.portable_storage_interface": "ǝbuɐɥɔxƎ ʎq-ǝʌıɹᗡ", "advancement.create.portable_storage_interface.desc": "uoıʇdɐɹʇuoƆ ɐ oʇuı sɯǝʇı ʇɹǝsuı ɹo ǝʞɐʇ oʇ ǝɔɐɟɹǝʇuI ǝbɐɹoʇS ǝןqɐʇɹoԀ ɐ ǝs∩", "advancement.create.potato_cannon": "¡dɯooʍℲ", "advancement.create.potato_cannon.desc": "uouuɐƆ oʇɐʇoԀ ɹnoʎ ɥʇıʍ ʎɯǝuǝ uɐ ʇɐǝɟǝᗡ", @@ -129,7 +143,7 @@ "advancement.create.red_signal.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nןɐubıS uıɐɹ⟘ pǝɹ ɐ unᴚ", "advancement.create.root": "ǝʇɐǝɹƆ oʇ ǝɯoɔןǝM", "advancement.create.root.desc": "suoıʇdɐɹʇuoƆ ǝᗺ ǝɹǝH", - "advancement.create.rose_quartz": "spuoɯɐıᗡ ʞuıԀ", + "advancement.create.rose_quartz": "pǝbɹɐɥɔɹǝdnS", "advancement.create.rose_quartz.desc": "zʇɹɐnὉ ǝsoᴚ ǝɯos ɥsıןoԀ", "advancement.create.saw_processing": "pǝɹɐǝℲ ʇsoW s,doɥsʞɹoM", "advancement.create.saw_processing.desc": "sןɐıɹǝʇɐɯ ssǝɔoɹd oʇ ʍɐS ןɐɔıuɐɥɔǝW ʇɥbıɹdn uɐ ǝs∩", @@ -147,6 +161,8 @@ "advancement.create.steam_engine_maxed.desc": "ɹǝʍod ɟo ןǝʌǝן ɯnɯıxɐɯ ǝɥʇ ʇɐ ɹǝןıoq ɐ unᴚ", "advancement.create.steam_whistle": "ןǝbuⱯ uɐ ɟo ǝɔıoΛ", "advancement.create.steam_whistle.desc": "ǝןʇsıɥM ɯɐǝʇS ɐ ǝʇɐʌıʇɔⱯ", + "advancement.create.stock_ticker": "¡d∩ ɹǝpɹO", + "advancement.create.stock_ticker.desc": "sʇsǝnbǝɹ ʇsɹıɟ ɹnoʎ ǝʞɐɯ puɐ ɹǝʞɔıʇ ʞɔoʇs ɹnoʎ ʇɐ qoɯ ɐ ʎoןdɯƎ", "advancement.create.stressometer": "spɹǝN ɹoɟ ssǝɹʇS", "advancement.create.stressometer.desc": "ɹǝʇǝɯossǝɹʇS ɐ puɐ sǝןbbo⅁ s,ɹǝǝuıbuƎ ɟo dןǝɥ ǝɥʇ ɥʇıʍ ʇnopɐǝɹ ʇɔɐxǝ uɐ ʇǝ⅁", "advancement.create.stressometer_maxed": "pǝssǝɹʇS ʎןʇɔǝɟɹǝԀ", @@ -155,6 +171,8 @@ "advancement.create.sturdy_sheet.desc": "uɐıpısqO pǝɹǝpʍoԀ buıuıɟǝɹ ʎq ʇǝǝɥS ʎpɹnʇS ɐ ǝןqɯǝssⱯ", "advancement.create.super_glue": "ʇɔǝuuoƆ ɟo ɐǝɹⱯ", "advancement.create.super_glue.desc": "dnoɹb ɐ oʇuı sʞɔoןq ǝɯos ǝnן⅁ ɹǝdnS", + "advancement.create.table_cloth_shop": "ssǝuısnq ɹoɟ uǝdO", + "advancement.create.table_cloth_shop.desc": "ɥʇoןƆ ǝןqɐ⟘ ɐ buısn ǝןɐs ɹoɟ dn sɯǝʇı ʇnԀ", "advancement.create.track_0": "ǝbnɐ⅁ ʍǝN Ɐ", "advancement.create.track_0.desc": "sʞɔɐɹ⟘ uıɐɹ⟘ ǝɯos uıɐʇqO", "advancement.create.track_crafting_factory": "ʎɹoʇɔɐℲ ʞɔɐɹ⟘", @@ -163,7 +181,7 @@ "advancement.create.track_signal.desc": "ןɐubıS uıɐɹ⟘ ɐ ǝɔɐןԀ", "advancement.create.train": "¡pɹɐoqⱯ ןןⱯ", "advancement.create.train.desc": "uıɐɹ⟘ ʇsɹıɟ ɹnoʎ ǝןqɯǝssⱯ", - "advancement.create.train_casing_00": "ǝbⱯ ןɐɔıʇsıboꞀ ǝɥ⟘", + "advancement.create.train_casing_00": "ǝbⱯ ǝʌıʇoɯoɔoꞀ ǝɥ⟘", "advancement.create.train_casing_00.desc": "sʇuǝuodɯoɔ ʎɐʍןıɐɹ ɹoɟ buısɐɔ ɐ ǝʇɐǝɹɔ oʇ sʇǝǝɥS ʎpɹnʇS ǝs∩", "advancement.create.train_crash": "ǝɔıʌɹǝS ǝןqıɹɹǝ⟘", "advancement.create.train_crash.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nɹǝbuǝssɐd ɐ sɐ ɥsɐɹɔ uıɐɹ⟘ ɐ ssǝuʇıM", @@ -179,9 +197,9 @@ "advancement.create.water_supply.desc": "ɹǝʇɐʍ ʇɔǝןןoɔ oʇ dɯnԀ ןɐɔıuɐɥɔǝW ɹo ǝdıԀ pınןℲ ɐ ɟo puǝ buıןןnd ǝɥʇ ǝs∩", "advancement.create.water_wheel": "sɔıןnɐɹpʎH pǝssǝuɹɐH", "advancement.create.water_wheel.desc": "ǝnbɹoʇ ǝʇɐɹǝuǝb oʇ ʇı ǝsn puɐ ןǝǝɥM ɹǝʇɐM ɐ ǝɔɐןԀ", - "advancement.create.windmill": "ǝzǝǝɹᗺ pןıW Ɐ", + "advancement.create.windmill": "ǝzǝǝɹᗺ pןıɯ Ɐ", "advancement.create.windmill.desc": "ǝnbɹoʇ ǝʇɐɹǝuǝb oʇ ʇı ǝsn puɐ ןןıɯpuıʍ ɐ ǝןqɯǝssⱯ", - "advancement.create.windmill_maxed": "ǝzǝǝɹᗺ buoɹʇS Ɐ", + "advancement.create.windmill_maxed": "ǝzǝǝɹᗺ buoɹʇs Ɐ", "advancement.create.windmill_maxed.desc": "ɥʇbuǝɹʇs ɯnɯıxɐɯ ɟo ןןıɯpuıʍ ɐ ǝןqɯǝssⱯ", "advancement.create.wrench_goggles": "ʇnO pǝʇʇıʞ", "advancement.create.wrench_goggles.desc": "ɥɔuǝɹM ɐ puɐ sǝןbbo⅁ s,ɹǝǝuıbuƎ dınbƎ", @@ -201,24 +219,32 @@ "block.create.andesite_ladder": "ɹǝppɐꞀ ǝʇısǝpuⱯ", "block.create.andesite_pillar": "ɹɐןןıԀ ǝʇısǝpuⱯ", "block.create.andesite_scaffolding": "buıpןoɟɟɐɔS ǝʇısǝpuⱯ", + "block.create.andesite_table_cloth": "ɹǝʌoƆ ǝןqɐ⟘ ǝʇısǝpuⱯ", "block.create.andesite_tunnel": "ןǝuun⟘ ǝʇısǝpuⱯ", "block.create.asurine": "ǝuıɹnsⱯ", "block.create.asurine_pillar": "ɹɐןןıԀ ǝuıɹnsⱯ", + "block.create.bamboo_window": "ʍopuıM ooqɯɐᗺ", + "block.create.bamboo_window_pane": "ǝuɐԀ ʍopuıM ooqɯɐᗺ", "block.create.basin": "uısɐᗺ", "block.create.belt": "ʇןǝᗺ", "block.create.birch_window": "ʍopuıM ɥɔɹıᗺ", "block.create.birch_window_pane": "ǝuɐԀ ʍopuıM ɥɔɹıᗺ", "block.create.black_nixie_tube": "ǝqn⟘ ǝıxıN ʞɔɐןᗺ", + "block.create.black_postbox": "xoqʇsoԀ ʞɔɐןᗺ", "block.create.black_sail": "ןıɐS ʞɔɐןᗺ", "block.create.black_seat": "ʇɐǝS ʞɔɐןᗺ", + "block.create.black_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ʞɔɐןᗺ", "block.create.black_toolbox": "xoqןoo⟘ ʞɔɐןᗺ", "block.create.black_valve_handle": "ǝןpuɐH ǝʌןɐΛ ʞɔɐןᗺ", "block.create.blaze_burner": "ɹǝuɹnᗺ ǝzɐןᗺ", "block.create.blue_nixie_tube": "ǝqn⟘ ǝıxıN ǝnןᗺ", + "block.create.blue_postbox": "xoqʇsoԀ ǝnןᗺ", "block.create.blue_sail": "ןıɐS ǝnןᗺ", "block.create.blue_seat": "ʇɐǝS ǝnןᗺ", + "block.create.blue_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ǝnןᗺ", "block.create.blue_toolbox": "xoqןoo⟘ ǝnןᗺ", "block.create.blue_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝnןᗺ", + "block.create.bound_cardboard_block": "pɹɐoqpɹɐƆ ɟo ʞɔoןᗺ punoᗺ", "block.create.brass_bars": "sɹɐᗺ ssɐɹᗺ", "block.create.brass_belt_funnel": "ןǝuunℲ ʇןǝᗺ ssɐɹᗺ", "block.create.brass_block": "ssɐɹᗺ ɟo ʞɔoןᗺ", @@ -230,14 +256,21 @@ "block.create.brass_funnel": "ןǝuunℲ ssɐɹᗺ", "block.create.brass_ladder": "ɹǝppɐꞀ ssɐɹᗺ", "block.create.brass_scaffolding": "buıpןoɟɟɐɔS ssɐɹᗺ", + "block.create.brass_table_cloth": "ɹǝʌoƆ ǝןqɐ⟘ ssɐɹᗺ", "block.create.brass_tunnel": "ןǝuun⟘ ssɐɹᗺ", "block.create.brown_nixie_tube": "ǝqn⟘ ǝıxıN uʍoɹᗺ", + "block.create.brown_postbox": "xoqʇsoԀ uʍoɹᗺ", "block.create.brown_sail": "ןıɐS uʍoɹᗺ", "block.create.brown_seat": "ʇɐǝS uʍoɹᗺ", + "block.create.brown_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ uʍoɹᗺ", "block.create.brown_toolbox": "xoqןoo⟘ uʍoɹᗺ", "block.create.brown_valve_handle": "ǝןpuɐH ǝʌןɐΛ uʍoɹᗺ", "block.create.calcite_pillar": "ɹɐןןıԀ ǝʇıɔןɐƆ", + "block.create.cardboard_block": "pɹɐoqpɹɐƆ ɟo ʞɔoןᗺ", "block.create.cart_assembler": "ɹǝןqɯǝssⱯ ʇɹɐƆ", + "block.create.chain_conveyor": "ɹoʎǝʌuoƆ uıɐɥƆ", + "block.create.cherry_window": "ʍopuıM ʎɹɹǝɥƆ", + "block.create.cherry_window_pane": "ǝuɐԀ ʍopuıM ʎɹɹǝɥƆ", "block.create.chocolate": "ǝʇɐןoɔoɥƆ", "block.create.chute": "ǝʇnɥƆ", "block.create.clipboard": "pɹɐoqdıןƆ", @@ -263,6 +296,7 @@ "block.create.copper_shingle_slab": "qɐןS ǝןbuıɥS ɹǝddoƆ", "block.create.copper_shingle_stairs": "sɹıɐʇS ǝןbuıɥS ɹǝddoƆ", "block.create.copper_shingles": "sǝןbuıɥS ɹǝddoƆ", + "block.create.copper_table_cloth": "ɹǝʌoƆ ǝןqɐ⟘ ɹǝddoƆ", "block.create.copper_tile_slab": "qɐןS ǝןı⟘ ɹǝddoƆ", "block.create.copper_tile_stairs": "sɹıɐʇS ǝןı⟘ ɹǝddoƆ", "block.create.copper_tiles": "sǝןı⟘ ɹǝddoƆ", @@ -408,8 +442,10 @@ "block.create.cut_veridium_stairs": "sɹıɐʇS ɯnıpıɹǝΛ ʇnƆ", "block.create.cut_veridium_wall": "ןןɐM ɯnıpıɹǝΛ ʇnƆ", "block.create.cyan_nixie_tube": "ǝqn⟘ ǝıxıN uɐʎƆ", + "block.create.cyan_postbox": "xoqʇsoԀ uɐʎƆ", "block.create.cyan_sail": "ןıɐS uɐʎƆ", "block.create.cyan_seat": "ʇɐǝS uɐʎƆ", + "block.create.cyan_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ uɐʎƆ", "block.create.cyan_toolbox": "xoqןoo⟘ uɐʎƆ", "block.create.cyan_valve_handle": "ǝןpuɐH ǝʌןɐΛ uɐʎƆ", "block.create.dark_oak_window": "ʍopuıM ʞɐO ʞɹɐᗡ", @@ -418,6 +454,10 @@ "block.create.deepslate_zinc_ore": "ǝɹO ɔuıZ ǝʇɐןsdǝǝᗡ", "block.create.deployer": "ɹǝʎoןdǝᗡ", "block.create.depot": "ʇodǝᗡ", + "block.create.desk_bell": "ןןǝᗺ ʞsǝᗡ", + "block.create.desk_bell.tooltip.behaviour1": "˙‾ɹooןɟ ʇǝbɹɐʇ‾ ǝɥʇ ʇɐ buıʌıɹɹɐ uǝɥʍ ‾punos ɐ sʎɐןԀ‾", + "block.create.desk_bell.tooltip.condition1": "uoıʇdɐɹʇuoƆ ɹoʇɐʌǝןƎ oʇ pǝɥɔɐʇʇɐ uǝɥM", + "block.create.desk_bell.tooltip.summary": "˙pǝʇɐʌıʇɔɐ uǝɥʍ ‾ןɐubıs ǝuoʇspǝɹ‾ ɐ sʇıɯƎ ¡ǝɔıʌɹǝS ɹoɟ buıᴚ", "block.create.diorite_pillar": "ɹɐןןıԀ ǝʇıɹoıᗡ", "block.create.display_board": "pɹɐoᗺ ʎɐןdsıᗡ", "block.create.display_link": "ʞuıꞀ ʎɐןdsıᗡ", @@ -434,6 +474,7 @@ "block.create.exposed_copper_tile_slab": "qɐןS ǝןı⟘ ɹǝddoƆ pǝsodxƎ", "block.create.exposed_copper_tile_stairs": "sɹıɐʇS ǝןı⟘ ɹǝddoƆ pǝsodxƎ", "block.create.exposed_copper_tiles": "sǝןı⟘ ɹǝddoƆ pǝsodxƎ", + "block.create.factory_gauge": "ǝbnɐ⅁ ʎɹoʇɔɐℲ", "block.create.fake_track": "sdɐW ɹoɟ ɹǝʞɹɐW ʞɔɐɹ⟘", "block.create.fluid_pipe": "ǝdıԀ pınןℲ", "block.create.fluid_tank": "ʞuɐ⟘ pınןℲ", @@ -453,13 +494,17 @@ "block.create.glass_fluid_pipe": "ǝdıԀ pınןℲ ssɐן⅁", "block.create.granite_pillar": "ɹɐןןıԀ ǝʇıuɐɹ⅁", "block.create.gray_nixie_tube": "ǝqn⟘ ǝıxıN ʎɐɹ⅁", + "block.create.gray_postbox": "xoqʇsoԀ ʎɐɹ⅁", "block.create.gray_sail": "ןıɐS ʎɐɹ⅁", "block.create.gray_seat": "ʇɐǝS ʎɐɹ⅁", + "block.create.gray_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ʎɐɹ⅁", "block.create.gray_toolbox": "xoqןoo⟘ ʎɐɹ⅁", "block.create.gray_valve_handle": "ǝןpuɐH ǝʌןɐΛ ʎɐɹ⅁", "block.create.green_nixie_tube": "ǝqn⟘ ǝıxıN uǝǝɹ⅁", + "block.create.green_postbox": "xoqʇsoԀ uǝǝɹ⅁", "block.create.green_sail": "ןıɐS uǝǝɹ⅁", "block.create.green_seat": "ʇɐǝS uǝǝɹ⅁", + "block.create.green_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ uǝǝɹ⅁", "block.create.green_toolbox": "xoqןoo⟘ uǝǝɹ⅁", "block.create.green_valve_handle": "ǝןpuɐH ǝʌןɐΛ uǝǝɹ⅁", "block.create.hand_crank": "ʞuɐɹƆ puɐH", @@ -472,7 +517,13 @@ "block.create.horizontal_framed_glass_pane": "ǝuɐԀ ssɐן⅁ pǝɯɐɹℲ ןɐʇuozıɹoH", "block.create.hose_pulley": "ʎǝןןnԀ ǝsoH", "block.create.industrial_iron_block": "uoɹI ןɐıɹʇsnpuI ɟo ʞɔoןᗺ", + "block.create.industrial_iron_window": "ʍopuıM uoɹI ןɐıɹʇsnpuI", + "block.create.industrial_iron_window_pane": "ǝuɐԀ ʍopuıM uoɹI ןɐıɹʇsnpuI", "block.create.item_drain": "uıɐɹᗡ ɯǝʇI", + "block.create.item_hatch": "ɥɔʇɐH ɯǝʇI", + "block.create.item_hatch.tooltip.behaviour1": "˙sɯǝʇı ɹɐqʇoH ʇdǝɔxǝ ‾buıɥʇʎɹǝʌǝ‾ ‾ʇısodǝp‾ oʇ ‾ʞɔıןɔ-ʞɐǝuS‾ ˙uo pǝɔɐןd sı ʇı ‾ɹǝuıɐʇuoɔ‾ ǝɥʇ oʇuı ‾ɯǝʇı pןǝɥ‾ ɹnoʎ ‾sʇısodǝᗡ‾", + "block.create.item_hatch.tooltip.condition1": "pǝʞɔıןƆ-ᴚ uǝɥM", + "block.create.item_hatch.tooltip.summary": "˙ɯǝןqoɹd s,ǝsןǝ ǝuoǝɯos ʇı sǝʞɐɯ puɐ ɹǝʇʇnןɔ ‾ʎɹoʇuǝʌuı‾ ɹnoʎ ‾sǝʌןos ʎןʞɔınὉ‾", "block.create.item_vault": "ʇןnɐΛ ɯǝʇI", "block.create.jungle_window": "ʍopuıM ǝןbunſ", "block.create.jungle_window_pane": "ǝuɐԀ ʍopuıM ǝןbunſ", @@ -495,18 +546,24 @@ "block.create.layered_veridium": "ɯnıpıɹǝΛ pǝɹǝʎɐꞀ", "block.create.lectern_controller": "ɹǝןןoɹʇuoƆ uɹǝʇɔǝꞀ", "block.create.light_blue_nixie_tube": "ǝqn⟘ ǝıxıN ǝnןᗺ ʇɥbıꞀ", + "block.create.light_blue_postbox": "xoqʇsoԀ ǝnןᗺ ʇɥbıꞀ", "block.create.light_blue_sail": "ןıɐS ǝnןᗺ ʇɥbıꞀ", "block.create.light_blue_seat": "ʇɐǝS ǝnןᗺ ʇɥbıꞀ", + "block.create.light_blue_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ǝnןᗺ ʇɥbıꞀ", "block.create.light_blue_toolbox": "xoqןoo⟘ ǝnןᗺ ʇɥbıꞀ", "block.create.light_blue_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝnןᗺ ʇɥbıꞀ", "block.create.light_gray_nixie_tube": "ǝqn⟘ ǝıxıN ʎɐɹ⅁ ʇɥbıꞀ", + "block.create.light_gray_postbox": "xoqʇsoԀ ʎɐɹ⅁ ʇɥbıꞀ", "block.create.light_gray_sail": "ןıɐS ʎɐɹ⅁ ʇɥbıꞀ", "block.create.light_gray_seat": "ʇɐǝS ʎɐɹ⅁ ʇɥbıꞀ", + "block.create.light_gray_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ʎɐɹ⅁ ʇɥbıꞀ", "block.create.light_gray_toolbox": "xoqןoo⟘ ʎɐɹ⅁ ʇɥbıꞀ", "block.create.light_gray_valve_handle": "ǝןpuɐH ǝʌןɐΛ ʎɐɹ⅁ ʇɥbıꞀ", "block.create.lime_nixie_tube": "ǝqn⟘ ǝıxıN ǝɯıꞀ", + "block.create.lime_postbox": "xoqʇsoԀ ǝɯıꞀ", "block.create.lime_sail": "ןıɐS ǝɯıꞀ", "block.create.lime_seat": "ʇɐǝS ǝɯıꞀ", + "block.create.lime_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ǝɯıꞀ", "block.create.lime_toolbox": "xoqןoo⟘ ǝɯıꞀ", "block.create.lime_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝɯıꞀ", "block.create.limestone": "ǝuoʇsǝɯıꞀ", @@ -514,8 +571,10 @@ "block.create.linear_chassis": "sıssɐɥƆ ɹɐǝuıꞀ", "block.create.lit_blaze_burner": "ɹǝuɹnᗺ ǝzɐןᗺ ʇıꞀ", "block.create.magenta_nixie_tube": "ǝqn⟘ ǝıxıN ɐʇuǝbɐW", + "block.create.magenta_postbox": "xoqʇsoԀ ɐʇuǝbɐW", "block.create.magenta_sail": "ןıɐS ɐʇuǝbɐW", "block.create.magenta_seat": "ʇɐǝS ɐʇuǝbɐW", + "block.create.magenta_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ɐʇuǝbɐW", "block.create.magenta_toolbox": "xoqןoo⟘ ɐʇuǝbɐW", "block.create.magenta_valve_handle": "ǝןpuɐH ǝʌןɐΛ ɐʇuǝbɐW", "block.create.mangrove_window": "ʍopuıM ǝʌoɹbuɐW", @@ -548,8 +607,10 @@ "block.create.oak_window_pane": "ǝuɐԀ ʍopuıM ʞɐO", "block.create.ochrum": "ɯnɹɥɔO", "block.create.ochrum_pillar": "ɹɐןןıԀ ɯnɹɥɔO", + "block.create.orange_postbox": "xoqʇsoԀ ǝbuɐɹO", "block.create.orange_sail": "ןıɐS ǝbuɐɹO", "block.create.orange_seat": "ʇɐǝS ǝbuɐɹO", + "block.create.orange_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ǝbuɐɹO", "block.create.orange_toolbox": "xoqןoo⟘ ǝbuɐɹO", "block.create.orange_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝbuɐɹO", "block.create.ornate_iron_window": "ʍopuıM uoɹI ǝʇɐuɹO", @@ -560,11 +621,15 @@ "block.create.oxidized_copper_tile_slab": "qɐןS ǝןı⟘ ɹǝddoƆ pǝzıpıxO", "block.create.oxidized_copper_tile_stairs": "sɹıɐʇS ǝןı⟘ ɹǝddoƆ pǝzıpıxO", "block.create.oxidized_copper_tiles": "sǝןı⟘ ɹǝddoƆ pǝzıpıxO", + "block.create.package_frogport": "ʇɹodboɹℲ ǝbɐʞɔɐԀ", + "block.create.packager": "ɹǝbɐʞɔɐԀ", "block.create.peculiar_bell": "ןןǝᗺ ɹɐıןnɔǝԀ", "block.create.peculiar_bell.tooltip.summary": "˙˙˙sʇɔǝɟɟǝ-ǝpıs ǝʌɐɥ ʎɐɯ ‾ǝɹıℲ ןnoS‾ uǝdo ǝʌoqɐ ʇɥbıɹ ʇı buıɔɐןԀ ˙‾ןןǝᗺ ssɐɹᗺ‾ ǝʌıʇɐɹoɔǝp Ɐ", "block.create.pink_nixie_tube": "ǝqn⟘ ǝıxıN ʞuıԀ", + "block.create.pink_postbox": "xoqʇsoԀ ʞuıԀ", "block.create.pink_sail": "ןıɐS ʞuıԀ", "block.create.pink_seat": "ʇɐǝS ʞuıԀ", + "block.create.pink_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ʞuıԀ", "block.create.pink_toolbox": "xoqןoo⟘ ʞuıԀ", "block.create.pink_valve_handle": "ǝןpuɐH ǝʌןɐΛ ʞuıԀ", "block.create.piston_extension_pole": "ǝןoԀ uoısuǝʇxƎ uoʇsıԀ", @@ -638,22 +703,29 @@ "block.create.pulley_magnet": "ʇǝubɐW ʎǝןןnԀ", "block.create.pulse_extender": "ɹǝpuǝʇxƎ ǝsןnԀ", "block.create.pulse_repeater": "ɹǝʇɐǝdǝᴚ ǝsןnԀ", + "block.create.pulse_timer": "ɹǝɯı⟘ ǝsןnԀ", "block.create.purple_nixie_tube": "ǝqn⟘ ǝıxıN ǝןdɹnԀ", + "block.create.purple_postbox": "xoqʇsoԀ ǝןdɹnԀ", "block.create.purple_sail": "ןıɐS ǝןdɹnԀ", "block.create.purple_seat": "ʇɐǝS ǝןdɹnԀ", + "block.create.purple_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ǝןdɹnԀ", "block.create.purple_toolbox": "xoqןoo⟘ ǝןdɹnԀ", "block.create.purple_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝןdɹnԀ", "block.create.radial_chassis": "sıssɐɥƆ ןɐıpɐᴚ", "block.create.railway_casing": "buısɐƆ uıɐɹ⟘", "block.create.raw_zinc_block": "ɔuıZ ʍɐᴚ ɟo ʞɔoןᗺ", "block.create.red_nixie_tube": "ǝqn⟘ ǝıxıN pǝᴚ", + "block.create.red_postbox": "xoqʇsoԀ pǝᴚ", "block.create.red_sail": "ןıɐS pǝᴚ", "block.create.red_seat": "ʇɐǝS pǝᴚ", + "block.create.red_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ pǝᴚ", "block.create.red_toolbox": "xoqןoo⟘ pǝᴚ", "block.create.red_valve_handle": "ǝןpuɐH ǝʌןɐΛ pǝᴚ", "block.create.redstone_contact": "ʇɔɐʇuoƆ ǝuoʇspǝᴚ", "block.create.redstone_link": "ʞuıꞀ ǝuoʇspǝᴚ", + "block.create.redstone_requester": "ɹǝʇsǝnbǝᴚ ǝuoʇspǝᴚ", "block.create.refined_radiance_casing": "buısɐƆ ʇuɐıpɐᴚ", + "block.create.repackager": "ɹǝbɐʞɔɐԀ-ǝᴚ", "block.create.rope": "ǝdoᴚ", "block.create.rope_pulley": "ʎǝןןnԀ ǝdoᴚ", "block.create.rose_quartz_block": "zʇɹɐnὉ ǝsoᴚ ɟo ʞɔoןᗺ", @@ -749,6 +821,8 @@ "block.create.steam_whistle_extension": "uoısuǝʇxƎ ǝןʇsıɥM ɯɐǝʇS", "block.create.sticker": "ɹǝʞɔıʇS", "block.create.sticky_mechanical_piston": "uoʇsıԀ ןɐɔıuɐɥɔǝW ʎʞɔıʇS", + "block.create.stock_link": "ʞuıꞀ ʞɔoʇS", + "block.create.stock_ticker": "ɹǝʞɔı⟘ ʞɔoʇS", "block.create.stockpile_switch": "ɥɔʇıʍS pןoɥsǝɹɥ⟘", "block.create.stressometer": "ɹǝʇǝɯossǝɹʇS", "block.create.tiled_glass": "ssɐן⅁ pǝןı⟘", @@ -807,18 +881,25 @@ "block.create.weathered_copper_tile_slab": "qɐןS ǝןı⟘ ɹǝddoƆ pǝɹǝɥʇɐǝM", "block.create.weathered_copper_tile_stairs": "sɹıɐʇS ǝןı⟘ ɹǝddoƆ pǝɹǝɥʇɐǝM", "block.create.weathered_copper_tiles": "sǝןı⟘ ɹǝddoƆ pǝɹǝɥʇɐǝM", + "block.create.weathered_iron_block": "uoɹI pǝɹǝɥʇɐǝM ɟo ʞɔoןᗺ", + "block.create.weathered_iron_window": "ʍopuıM uoɹI pǝɹǝɥʇɐǝM", + "block.create.weathered_iron_window_pane": "ǝuɐԀ ʍopuıM uoɹI pǝɹǝɥʇɐǝM", "block.create.weighted_ejector": "ɹoʇɔǝظƎ pǝʇɥbıǝM", "block.create.white_nixie_tube": "ǝqn⟘ ǝıxıN ǝʇıɥM", + "block.create.white_postbox": "xoqʇsoԀ ǝʇıɥM", "block.create.white_sail": "ןıɐS ןןıɯpuıM", "block.create.white_seat": "ʇɐǝS ǝʇıɥM", + "block.create.white_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ǝʇıɥM", "block.create.white_toolbox": "xoqןoo⟘ ǝʇıɥM", "block.create.white_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝʇıɥM", "block.create.windmill_bearing": "buıɹɐǝᗺ ןןıɯpuıM", "block.create.wooden_bracket": "ʇǝʞɔɐɹᗺ uǝpooM", "block.create.wooden_bracket.tooltip.summary": "˙ʇuǝɯǝɔɹoɟuıǝɹ ɟo ʇıq uǝpooʍ puɐ ʎzoɔ ɐ ɥʇıʍ ‾sǝdıԀ‾ puɐ ‾sןǝǝɥʍboƆ 'sʇɟɐɥS‾ ɹnoʎ ‾ǝʇɐɹoɔǝᗡ‾", "block.create.yellow_nixie_tube": "ǝqn⟘ ǝıxıN ʍoןןǝʎ", + "block.create.yellow_postbox": "xoqʇsoԀ ʍoןןǝʎ", "block.create.yellow_sail": "ןıɐS ʍoןןǝʎ", "block.create.yellow_seat": "ʇɐǝS ʍoןןǝʎ", + "block.create.yellow_table_cloth": "ɥʇoןƆ ǝןqɐ⟘ ʍoןןǝʎ", "block.create.yellow_toolbox": "xoqןoo⟘ ʍoןןǝʎ", "block.create.yellow_valve_handle": "ǝןpuɐH ǝʌןɐΛ ʍoןןǝʎ", "block.create.zinc_block": "ɔuıZ ɟo ʞɔoןᗺ", @@ -853,8 +934,22 @@ "create.boiler.water": "ɹǝʇɐM", "create.boiler.water_dots": " ˙˙˙", "create.boiler.water_input_rate": "ǝʇɐɹ ʇnduı ɹǝʇɐM", + "create.chain_conveyor.already_connected": "pǝʇɔǝuuoɔ ʎpɐǝɹןɐ ǝɹɐ sɹoʎǝʌuoƆ", + "create.chain_conveyor.blocks_invalid": "ʇǝsǝɹ oʇ ʞɔıןɔ-ʞɐǝuS 'pıןɐʌuı sʞɔoןq ɹoʎǝʌuoƆ", + "create.chain_conveyor.cannot_add_more_connections": "ɹoʎǝʌuoƆ sıɥʇ oʇ suoıʇɔǝuuoɔ ǝɹoɯ ppɐ ʇouuɐƆ", + "create.chain_conveyor.cannot_connect_vertically": "ʎןןɐɔıʇɹǝʌ ʇɔǝuuoɔ ʇouuɐƆ", + "create.chain_conveyor.not_enough_chains": "suıɐɥɔ ɥbnouǝ buıpןoɥ ʇoN", + "create.chain_conveyor.select_second": "ʇɔǝuuoɔ oʇ ɹoʎǝʌuoɔ puoɔǝs ɐ ʇɔǝןǝS", + "create.chain_conveyor.selection_cleared": "pǝɹɐǝןƆ uoıʇɔǝןǝS", + "create.chain_conveyor.too_close": "ɹǝɥʇǝboʇ ǝsoןɔ oo⟘", + "create.chain_conveyor.too_far": "ʇɹɐdɐ ɹɐɟ oo⟘", + "create.chain_conveyor.too_steep": "dǝǝʇs ooʇ ǝdoןS", + "create.chain_conveyor.valid_connection": "✔ ʇɔǝuuoƆ uɐƆ", "create.clipboard.actions": "suoıʇɔⱯ pɹɐoqdıןƆ", + "create.clipboard.address_added": "pɹɐoqdıןƆ oʇ pǝppɐ ,%1$s,", "create.clipboard.copied_from": "%1$s ɯoɹɟ sbuıʇʇǝs buıʎdoƆ", + "create.clipboard.copied_from_clipboard": "pɹɐoqdıןƆ ɯoɹɟ sǝıɹʇuǝ pǝppⱯ", + "create.clipboard.copy_other_clipboard": "pɹɐoqdıןƆ sıɥʇ ɯoɹɟ sǝıɹʇuǝ ʎdoƆ oʇ %1$s", "create.clipboard.pasted_to": "%1$s oʇ sbuıʇʇǝs pǝıןddⱯ", "create.clipboard.to_copy": "sbuıʇʇǝs ʎdoƆ oʇ %1$s", "create.clipboard.to_paste": "sbuıʇʇǝs ǝʇsɐԀ oʇ %1$s", @@ -954,6 +1049,7 @@ "create.display_source.fill_level.percent": "ʇuǝɔɹǝԀ", "create.display_source.fill_level.progress_bar": "ɹɐᗺ ssǝɹboɹԀ", "create.display_source.fluid_amount": "spınןℲ buıɥɔʇɐɯ ɟo ʇunoɯⱯ", + "create.display_source.gauge_status": "snʇɐʇs ǝbnɐb ʎɹoʇɔɐℲ", "create.display_source.item_throughput": "ʇndɥbnoɹɥ⟘ ɯǝʇI", "create.display_source.item_throughput.interval": "ןɐʌɹǝʇuI", "create.display_source.item_throughput.interval.hour": "ɹnoH ɹǝd", @@ -976,6 +1072,7 @@ "create.display_source.nixie_tube": "sǝqn⟘ ǝıxıN ʎdoƆ", "create.display_source.observed_train_name": "ǝɯɐN uıɐɹ⟘ pǝʇɔǝʇǝᗡ", "create.display_source.player_deaths": "sɥʇɐǝᗡ ɹǝʎɐןԀ", + "create.display_source.read_package_address": "ssǝɹppⱯ ǝbɐʞɔɐԀ pɐǝᴚ", "create.display_source.redstone_power": "ɹǝʍoԀ ǝuoʇspǝᴚ", "create.display_source.redstone_power.display": "ʇɐɯɹoℲ ʎɐןdsıᗡ", "create.display_source.redstone_power.number": "ɹǝqɯnN", @@ -1008,6 +1105,29 @@ "create.elevator_contact.floor_description": "uoıʇdıɹɔsǝᗡ ɹooןℲ", "create.elevator_contact.floor_identifier": "ɹǝıɟıʇuǝpI ɹooןℲ", "create.elevator_contact.title": "ʇɔɐʇuoƆ ɹoʇɐʌǝןƎ", + "create.factory_panel.already_connected": "pǝʇɔǝuuoɔ ʎpɐǝɹןɐ ǝɹɐ sǝbnɐ⅁", + "create.factory_panel.cannot_add_more_inputs": "ǝbnɐb sıɥʇ oʇ sʇnduı ǝɹoɯ ppɐ ʇouuɐƆ", + "create.factory_panel.click_second_panel": "˙˙˙ʇɔǝuuoɔ oʇ ǝbnɐb puoɔǝs ɐ ʞɔıןƆ", + "create.factory_panel.click_to_configure": "ǝɹnbıɟuoɔ oʇ ʞɔıןƆ", + "create.factory_panel.click_to_relocate": "˙˙˙oʇ ןǝuɐd sıɥʇ ǝʇɐɔoןǝɹ oʇ ʇods ɐ ʞɔıןƆ", + "create.factory_panel.connection_aborted": "pǝʇɹoqɐ uoıʇɔǝuuoɔ ʇnduI", + "create.factory_panel.cycled_arrow_path": "%1$s ǝpoɯ buıɥʇɐd ʍoɹɹɐ pǝןɔʎƆ", + "create.factory_panel.hold_to_set_amount": "ʇunoɯɐ ʇǝbɹɐʇ ɹoɟ pןoɥ puɐ ʞɔıןƆ", + "create.factory_panel.in_progress": ")ssǝɹboɹԀ uI(", + "create.factory_panel.input_in_restock_mode": "ǝpoɯ ʞɔoʇsǝɹ uı ǝq ʇouuɐɔ ǝbnɐb ʇnduI", + "create.factory_panel.link_connected": "%1$s oʇ pǝʇɔǝuuoɔ ǝbnɐ⅁", + "create.factory_panel.new_factory_task": "ʞsɐʇ ʎɹoʇɔɐɟ ʍǝN", + "create.factory_panel.no_item": "ʇsɹıɟ ɯǝʇı uɐ ǝʌɐɥ ʇsnɯ ǝbnɐb ʇnduI", + "create.factory_panel.panels_connected": "%2$s ǝʇɐǝɹɔ oʇ %1$s buısn ʍoN", + "create.factory_panel.redstone_paused": ")pǝsnɐԀ ǝuoʇspǝᴚ(", + "create.factory_panel.relocated": "uoıʇısod ʍǝu oʇ pǝʌoɯ ǝbnɐ⅁", + "create.factory_panel.relocation_aborted": "pǝʇɹoqɐ uoıʇɐɔoןǝɹ ǝbnɐ⅁", + "create.factory_panel.same_orientation": "uoıʇɐʇuǝıɹo ǝɯɐs ǝɥʇ ǝʌɐɥ ʇsnɯ sʞɔoןᗺ", + "create.factory_panel.same_surface": "ǝɔɐɟɹns ǝɯɐs ǝɥʇ uo ǝq ʇsnɯ sʞɔoןᗺ", + "create.factory_panel.some_links_unloaded": "pǝpɐoן ʇou ǝɹɐ sʞuıן ǝɯoS", + "create.factory_panel.target_amount": "ǝbɐɹoʇS uı ʇunoɯⱯ ʇǝbɹɐ⟘", + "create.factory_panel.too_far_apart": "ɹǝɥʇo ɥɔɐǝ ɯoɹɟ ʎɐʍɐ ɹɐɟ ooʇ ǝɹɐ sʞɔoןᗺ", + "create.factory_panel.tune_before_placing": "buıɔɐןd ǝɹoɟǝq ʞuıן ʞɔoʇs ɐ oʇ ǝun⟘", "create.flap_display.cycles.alphabet": "Z؛ʎ؛X؛Λ؛∩؛⟘؛S؛ᴚ؛Ὁ؛Ԁ؛O؛N؛W؛Ꞁ؛ʞ؛ſ؛I؛H؛⅁؛Ⅎ؛Ǝ؛ᗡ؛Ɔ؛ᗺ؛Ɐ؛ ", "create.flap_display.cycles.arrival_time": "sϛㄣ؛s0Ɛ؛sϛƖ؛ʍou؛uıɯ ؛ ", "create.flap_display.cycles.fluid_units": " ᗺ؛ᗺɯ", @@ -1043,6 +1163,11 @@ "create.generic.unit.stress": "ns", "create.generic.unit.ticks": "sʞɔı⟘", "create.generic.width": "ɥʇpıM", + "create.gui.address_box.clipboard_tip": "ʞɔɐɹ⟘ buıdǝǝʞ", + "create.gui.address_box.clipboard_tip_1": "uo ,#, ɥʇıʍ buıʇɹɐʇs sǝıɹʇuƎ", + "create.gui.address_box.clipboard_tip_2": "ןןıʍ spɹɐoqdıןɔ ʎqɹɐǝu ɹo pןǝɥ", + "create.gui.address_box.clipboard_tip_3": "˙ʇnduı sıɥʇ ǝʇǝןdɯoɔ-oʇnɐ dןǝɥ", + "create.gui.address_box.clipboard_tip_4": ")ʎɹoʇɔɐɟ# 'ǝbɐɹoʇs# ˙b˙ǝ(", "create.gui.adjustable_crate.storageSpace": "ǝɔɐdS ǝbɐɹoʇS", "create.gui.adjustable_crate.title": "ǝʇɐɹƆ ǝןqɐʇsnظpⱯ", "create.gui.assembly.exception": ":ǝןqɯǝssɐ oʇ ǝןqɐun sɐʍ uoıʇdɐɹʇuoƆ sıɥ⟘", @@ -1079,6 +1204,53 @@ "create.gui.config.overlay8": "uoıʇısod ʇןnɐɟǝp ǝɥʇ oʇ ʇǝsǝɹ oʇ", "create.gui.contraptions.network_overstressed": "˙‾ʇɔɐdɯı‾ ‾ssǝɹʇs‾ ɥbıɥ ɐ ɥʇıʍ sʇuǝuodɯoɔ ǝɥʇ ‾uʍop‾ ‾ʍoןs‾ ɹo sǝɔɹnos ǝɹoɯ ppⱯ ˙‾pǝssǝɹʇsɹǝʌo‾ sı uoıʇdɐɹʇuoɔ sıɥʇ ʇɐɥʇ sɹɐǝddɐ ʇI", "create.gui.contraptions.not_fast_enough": "˙‾pǝǝds‾ ‾ɥbnouǝ‾ ɥʇıʍ buıʇɐʇoɹ ‾ʇou‾ sı %1$s sıɥʇ ʇɐɥʇ sɹɐǝddɐ ʇI", + "create.gui.factory_panel.activate_crafting": "buıʇɟɐɹƆ ןɐɔıuɐɥɔǝW ǝs∩", + "create.gui.factory_panel.address_missing": "ssǝɹppɐ ʇǝbɹɐʇ ɐ buıssıɯ :ǝʌıʇɔɐuI", + "create.gui.factory_panel.connect_input": "uoıʇɔǝuuoɔ ʍǝu ppⱯ", + "create.gui.factory_panel.crafting_input": "sʇuǝıpǝɹbuI pǝbɐʞɔɐԀ", + "create.gui.factory_panel.crafting_input_tip": "pǝʇɔǝuuoɔ oʇuı ǝbɐʞɔɐdu∩", + "create.gui.factory_panel.crafting_input_tip_1": ")ƐxƐ( sɹǝʇɟɐɹɔ ןɐɔıuɐɥɔǝɯ", + "create.gui.factory_panel.empty_panel": "ןǝuɐd ʎʇdɯƎ", + "create.gui.factory_panel.expected_output": "%1$s buıʇɔǝdxƎ", + "create.gui.factory_panel.expected_output_tip": "buıuɹnʇǝɹ ʇndʇno ɟo ʇunoɯɐ ǝɥ⟘", + "create.gui.factory_panel.expected_output_tip_1": "ʇsǝnbǝɹ ןnɟssǝɔɔns ɥɔɐǝ ɹǝʇɟɐ", + "create.gui.factory_panel.expected_output_tip_2": "ǝbuɐɥɔ oʇ ןןoɹɔS", + "create.gui.factory_panel.has_link_connections": "sʞuıן pǝʇɔǝuuoɔ sɐɥ ǝbnɐ⅁", + "create.gui.factory_panel.inactive": " ǝʌıʇɔɐuI ", + "create.gui.factory_panel.left_click_disconnect": "ʇɔǝuuoɔsıp oʇ ʞɔıןƆ-ʇɟǝꞀ", + "create.gui.factory_panel.left_click_reset": "ʇǝsǝɹ oʇ ʞɔıןƆ-ʇɟǝꞀ", + "create.gui.factory_panel.no_open_promises": "sǝsıɯoɹd uǝdo oN", + "create.gui.factory_panel.no_target_amount_set": "ʇǝs ʇunoɯɐ ʇǝbɹɐʇ ou :ǝʌıʇɔɐuI", + "create.gui.factory_panel.place_item_to_monitor": "ɹoʇıuoW oʇ ɯǝʇI ǝɔɐןԀ", + "create.gui.factory_panel.promise_prevents_oversending": "˙buıpuǝs-ɹǝʌo sʇuǝʌǝɹd sıɥ⟘", + "create.gui.factory_panel.promised_items": "sɯǝʇı pǝsıɯoɹԀ", + "create.gui.factory_panel.promises_do_not_expire": "ǝɹıdxǝ ʇou op sǝsıɯoɹԀ", + "create.gui.factory_panel.promises_expire_title": "ɹǝʇɟɐ ǝɹıdxǝ sǝsıɯoɹԀ", + "create.gui.factory_panel.recipe_address": "˙˙˙oʇ sʇnduı puǝS", + "create.gui.factory_panel.recipe_address_given": "oʇ sʇnduı buıpuǝS", + "create.gui.factory_panel.recipe_address_tip": "ǝɹǝɥʍ ssǝɹppɐ ǝɥʇ ɹǝʇuƎ", + "create.gui.factory_panel.recipe_address_tip_1": "˙pǝʇɟɐɹɔ sı ǝdıɔǝɹ sıɥʇ", + "create.gui.factory_panel.recipe_promises_tip": "ǝsıɯoɹd ɐ 'ʇuǝs ǝɹɐ sʇnduı uǝɥM", + "create.gui.factory_panel.recipe_promises_tip_1": "˙ǝʌıɹɹɐ sʇndʇno ןıʇun pןǝɥ sı", + "create.gui.factory_panel.relocate": "ǝbnɐb sıɥʇ ǝʌoW", + "create.gui.factory_panel.reset": "sbuıʇʇǝs ןןɐ ʇǝsǝᴚ", + "create.gui.factory_panel.restocker_address": "˙˙˙oʇ sɯǝʇı puǝS", + "create.gui.factory_panel.restocker_address_given": "oʇ buıpuǝS", + "create.gui.factory_panel.restocker_address_tip": "ןןıʍ ʇɐɥʇ ssǝɹppɐ ǝɥʇ ɹǝʇuƎ", + "create.gui.factory_panel.restocker_address_tip_1": "˙ǝɹǝɥ ǝʌıɹɹɐ oʇ sǝbɐʞɔɐd ǝsnɐɔ", + "create.gui.factory_panel.restocker_promises_tip": "ǝsıɯoɹd ɐ 'ʇuǝs ǝɹɐ sɯǝʇı uǝɥM", + "create.gui.factory_panel.restocker_promises_tip_1": "˙ǝʌıɹɹɐ ʎǝɥʇ ןıʇun pןǝɥ sı", + "create.gui.factory_panel.save_and_close": "ǝsoןɔ puɐ ǝʌɐS", + "create.gui.factory_panel.scroll_to_change_amount": "ʇunoɯɐ ǝbuɐɥɔ oʇ ןןoɹɔS", + "create.gui.factory_panel.send_item": "%1$s puǝS", + "create.gui.factory_panel.sending_item": "%1$s buıpuǝS", + "create.gui.factory_panel.sending_item_tip": "ןǝʌǝן ʞɔoʇs ןɐɔoן ɹǝʌǝuǝɥʍ", + "create.gui.factory_panel.sending_item_tip_1": "ʇunoɯɐ ʇǝbɹɐʇ ǝɥʇ ʍoןǝq sı", + "create.gui.factory_panel.title_as_recipe": "sbuıʇʇǝS ǝdıɔǝᴚ", + "create.gui.factory_panel.title_as_restocker": "sbuıʇʇǝS ɹǝʞɔoʇsǝᴚ", + "create.gui.factory_panel.unconfigured_input": "sʇuǝıpǝɹbuı ǝdıɔǝᴚ", + "create.gui.factory_panel.unconfigured_input_tip": "ʎq pǝppɐ ǝq uɐɔ sʇuǝıpǝɹbuI", + "create.gui.factory_panel.unconfigured_input_tip_1": "sǝbnɐb ʎɹoʇɔɐɟ ɹǝɥʇo buıʇɔǝuuoɔ", "create.gui.filter.allow_list": "ʇsıꞀ-ʍoןןⱯ", "create.gui.filter.allow_list.description": "˙buıɥʇʎɹǝʌǝ sʇɔǝظǝɹ ʇsıꞀ-ʍoןןⱯ ʎʇdɯǝ uⱯ ˙ǝʌoqɐ ǝɥʇ ɟo ʎuɐ ɥɔʇɐɯ ʎǝɥʇ ɟı ssɐd sɯǝʇI", "create.gui.filter.deny_list": "ʇsıꞀ-ʎuǝᗡ", @@ -1095,6 +1267,18 @@ "create.gui.goggles.generator_stats": ":sʇɐʇS ɹoʇɐɹǝuǝ⅁", "create.gui.goggles.kinetic_stats": ":sʇɐʇS ɔıʇǝuıʞ", "create.gui.goggles.pole_length": ":ɥʇbuǝꞀ ǝןoԀ", + "create.gui.package_port.catch_packages": "˙˙˙oʇ pǝssǝɹppɐ sǝbɐʞɔɐd ɥɔʇɐƆ", + "create.gui.package_port.catch_packages_empty": "pǝssǝɹppɐ-uou ɥɔʇɐɯ oʇ ʎʇdɯǝ ǝʌɐǝꞀ", + "create.gui.package_port.catch_packages_wildcard": "pɹɐɔpןıʍ ʇxǝʇ ɐ sɐ * ǝs∩", + "create.gui.package_port.not_targeting_anything": "pǝʇɔǝןǝs ʇǝbɹɐʇ oN", + "create.gui.package_port.send_and_receive": "sǝbɐʞɔɐd ǝʌıǝɔǝɹ puɐ puǝS", + "create.gui.package_port.send_only": "sǝbɐʞɔɐd puǝs ʎןuO", + "create.gui.redstone_requester.allow_partial": "sɹǝpɹo ןɐıʇɹɐd ʍoןןⱯ", + "create.gui.redstone_requester.dont_allow_partial": "sɯǝʇı ןןɐ puǝs ʇsnW", + "create.gui.redstone_requester.requester_address": "˙˙˙oʇ ɹǝpɹo puǝS", + "create.gui.redstone_requester.requester_address_given": "oʇ ɹǝpɹo buıpuǝS", + "create.gui.redstone_requester.requester_address_tip": "sıɥʇ ssǝɹppɐ ǝɥʇ ɹǝʇuƎ", + "create.gui.redstone_requester.requester_address_tip_1": "˙oʇ puǝs ǝq pןnoɥs ɹǝpɹo", "create.gui.schedule.add_condition": "uoıʇıpuoƆ ppⱯ", "create.gui.schedule.add_entry": "uoıʇɔⱯ ppⱯ", "create.gui.schedule.alternative_condition": "uoıʇıpuoƆ ǝʌıʇɐuɹǝʇןⱯ", @@ -1160,6 +1344,40 @@ "create.gui.sequenced_gearshift.speed.forward_fast": "spɹɐʍɹoℲ 'pǝǝds ǝןqnoᗡ", "create.gui.sequenced_gearshift.title": "ʇɟıɥsɹɐǝ⅁ pǝɔuǝnbǝS", "create.gui.speedometer.title": "pǝǝdS uoıʇɐʇoᴚ", + "create.gui.stock_keeper.already_ordering_recipe": "ǝdıɔǝɹ sıɥʇ buıɹǝpɹo ʎpɐǝɹןⱯ", + "create.gui.stock_keeper.checking_stocks": "˙˙˙sʞɔoʇs buıʞɔǝɥƆ", + "create.gui.stock_keeper.configure": "ǝɹnbıɟuoƆ", + "create.gui.stock_keeper.confirm_order": "ɹǝpɹO ɯɹıɟuoƆ", + "create.gui.stock_keeper.craft": "%1$s ʇɟɐɹƆ", + "create.gui.stock_keeper.inventories_empty": "ʎʇdɯƎ ǝɹɐ sǝıɹoʇuǝʌuI pǝʞuıꞀ", + "create.gui.stock_keeper.network_lock_tip": "sɹǝʎɐןԀ ɹǝɥʇo sʇuǝʌǝɹd buıʞɔoꞀ", + "create.gui.stock_keeper.network_lock_tip_1": "ʎןʇɔǝɹıp sɯǝʇı buıɹǝpɹo ɯoɹɟ", + "create.gui.stock_keeper.network_lock_tip_2": "ǝןbboʇ oʇ ʞɔıןƆ", + "create.gui.stock_keeper.network_locked": "pǝʞɔoן sı ʞɹoʍʇǝN", + "create.gui.stock_keeper.network_open": "uǝdo sı ʞɹoʍʇǝN", + "create.gui.stock_keeper.no_packagers_linked": "pǝʞuıꞀ sɹǝbɐʞɔɐԀ oN", + "create.gui.stock_keeper.no_search_results": "punoɟ sɯǝʇı buıɥɔʇɐɯ oN", + "create.gui.stock_keeper.not_in_stock": "ʞɔoʇS uı ʇou ǝɹɐ sɯǝʇı pǝɹınbǝᴚ", + "create.gui.stock_keeper.package_adress": "ssǝɹppⱯ ǝbɐʞɔɐԀ", + "create.gui.stock_keeper.program_requester": "ɹǝʇsǝnbǝᴚ ɯɐɹboɹԀ", + "create.gui.stock_keeper.request_sent": "¡ʇuǝS ʇsǝnbǝᴚ", + "create.gui.stock_keeper.schematic_list.no_results": "ʞɔoʇs uı ǝɹɐ ʇsıןʞɔǝɥɔ ɹnoʎ ɯoɹɟ sɯǝʇı oN", + "create.gui.stock_keeper.schematic_list.requesting": "ʇsıןʞɔǝɥɔ ɹnoʎ ɯoɹɟ sɯǝʇı ǝןqɐןıɐʌɐ ןןɐ ʇsǝnbǝɹ oʇ ,puǝS, ʞɔıןƆ", + "create.gui.stock_keeper.search_items": "sɯǝʇI ɥɔɹɐǝS", + "create.gui.stock_keeper.send": "puǝS", + "create.gui.stock_keeper.slots_full": "ןןnɟ ʎpɐǝɹןɐ sʇoןs ɹǝpɹO", + "create.gui.stock_keeper.title": "ɹǝdǝǝʞ ʞɔoʇS", + "create.gui.stock_keeper.unsorted_category": "pǝʇɹosu∩", + "create.gui.stock_ticker.category_editor": "ɹoʇıpƎ ʎɹobǝʇɐƆ", + "create.gui.stock_ticker.category_filter": "ɹǝʇןıℲ ʎɹobǝʇɐƆ", + "create.gui.stock_ticker.category_filter_tip": "ɹǝʇןıℲ ǝʇnqıɹʇʇⱯ ɹo ʇsıꞀ ɐ ǝɔɐןԀ", + "create.gui.stock_ticker.category_filter_tip_1": "pǝpnןɔuı ǝɹɐ sɯǝʇı ɥɔıɥʍ ʎɟıɔǝds oʇ", + "create.gui.stock_ticker.category_name": "ǝɯɐN ʎɹobǝʇɐƆ", + "create.gui.stock_ticker.delete_category": "ʎɹobǝʇɐƆ ǝʇǝןǝᗡ", + "create.gui.stock_ticker.empty_category_name_placeholder": ")ʎʇdɯƎ(", + "create.gui.stock_ticker.new_category": "ʎɹobǝʇɐƆ ʍǝN", + "create.gui.stock_ticker.shift_moves_bottom": "ɯoʇʇoq oʇ sǝʌoɯ ʇɟıɥS", + "create.gui.stock_ticker.shift_moves_top": "doʇ oʇ sǝʌoɯ ʇɟıɥS", "create.gui.stressometer.capacity": "ʎʇıɔɐdɐƆ buıuıɐɯǝᴚ", "create.gui.stressometer.no_rotation": "uoıʇɐʇoᴚ oN", "create.gui.stressometer.overstressed": "pǝssǝɹʇsɹǝʌO", @@ -1193,14 +1411,24 @@ "create.gui.terrainzapper.tool.overlay": "ʎɐןɹǝʌO", "create.gui.terrainzapper.tool.place": "ǝɔɐןԀ", "create.gui.terrainzapper.tool.replace": "ǝɔɐןdǝᴚ", + "create.gui.threshold_switch.currently": "%1$s ʎןʇuǝɹɹnƆ", + "create.gui.threshold_switch.incompatible": "ʞɔoןq ǝןqıʇɐdɯoɔuI", "create.gui.threshold_switch.invert_signal": "ןɐubıS ʇɹǝʌuI", - "create.gui.threshold_switch.move_to_lower_at": "%1$s%% ʇɐ ǝuɐן ɹǝʍoן oʇ ǝʌoW", - "create.gui.threshold_switch.move_to_upper_at": "%1$s%% ʇɐ ǝuɐן ɹǝddn oʇ ǝʌoW", + "create.gui.threshold_switch.lower_threshold": ":ʍoןǝq ɹo ʇɐ˙˙˙", + "create.gui.threshold_switch.not_attached": "ʞɔoןq ɐ oʇ pǝɥɔɐʇʇɐ ʇoN", + "create.gui.threshold_switch.power_off_when": "˙˙˙uǝɥʍ ɟɟo ɹǝʍoԀ", + "create.gui.threshold_switch.power_on_when": "˙˙˙uǝɥʍ uo ɹǝʍoԀ", + "create.gui.threshold_switch.pulley_y_level": "ʎ%1$s", + "create.gui.threshold_switch.range": ")%2$s oʇ %1$s(", + "create.gui.threshold_switch.range_max": ")%1$s ˙xɐɯ(", "create.gui.threshold_switch.title": "ɥɔʇıʍS pןoɥsǝɹɥ⟘", + "create.gui.threshold_switch.upper_threshold": ":ǝʌoqɐ ɹo ʇɐ˙˙˙", "create.gui.toolmenu.cycle": "ǝןɔʎƆ oʇ ]ꞀꞀOᴚƆS[", "create.gui.toolmenu.focusKey": "snɔoℲ oʇ ]%1$s[ pןoH", "create.gui.value_settings.hold_to_edit": "ʇıpǝ oʇ pןoɥ puɐ ʞɔıןƆ", "create.gui.value_settings.release_to_confirm": "ɯɹıɟuoƆ oʇ %1$s ǝsɐǝןǝᴚ", + "create.hint.blocked_frogport": "¿ןןnɟ ǝq ʇı pןnoƆ ‾˙ʍoןǝq‾ ‾ʎɹoʇuǝʌuı‾ ǝɥʇ oʇ pǝɹɹǝɟsuɐɹʇ ǝq ʇou pןnoɔ ‾ʇɹodboɹℲ‾ sıɥʇ ʎq ʇɥbnɐɔ ‾ǝbɐʞɔɐԀ‾ Ɐ", + "create.hint.blocked_frogport.title": "sǝbɐʞɔɐԀ suıɐʇuoƆ", "create.hint.derailed_train": "˙ʞɔɐɹʇ ʎqɹɐǝu ɐ oʇ ʇı ǝʇɐɔoןǝɹ oʇ ɹǝpɹo uı ‾ɥɔuǝɹʍ‾ ɐ buısn ‾ʞɔıןƆ-ʇɥbıᴚ‾ ˙ǝɔǝıd ʞɔɐɹʇ pǝʇɔǝuuoɔ ɐ uo buıʇʇıs ɹǝbuoן ou sı ‾uıɐɹ⟘‾ sıɥʇ sɹɐǝddɐ ʇI", "create.hint.derailed_train.title": "uıɐɹ⟘ pǝןıɐɹǝᗡ", "create.hint.empty_bearing": "˙ʇı ɟo ʇuoɹɟ uı ʇןınq ʇsnظ noʎ ǝɹnʇɔnɹʇs ǝɥʇ ‾ɥɔɐʇʇɐ‾ oʇ ‾puɐɥ‾ ‾ʎʇdɯǝ‾ uɐ ɥʇıʍ buıɹɐǝq ǝɥʇ ‾ʞɔıןɔ-ʇɥbıᴚ‾", @@ -1284,9 +1512,9 @@ "create.item_attributes.smokable.inverted": "pǝʞoɯS ǝq ʇouuɐɔ", "create.item_attributes.washable": "pǝɥsɐM ǝq uɐɔ", "create.item_attributes.washable.inverted": "pǝɥsɐM ǝq ʇouuɐɔ", - "create.keyinfo.ponder": "ɹǝpuoԀ", - "create.keyinfo.scrolldown": ")pןɹoʍuı( uʍoᗡ ןǝǝɥʍǝsnoW ǝʇɐןnɯıS", - "create.keyinfo.scrollup": ")pןɹoʍuı( d∩ ןǝǝɥʍǝsnoW ǝʇɐןnɯıS", + "create.item_hatch.deposit_inventory": "pǝʇısodǝp sɯǝʇı ʎɹoʇuǝʌuI", + "create.item_hatch.deposit_item": "pǝʇısodǝp ɯǝʇı pןǝH", + "create.keyinfo.rotate_menu": "nuǝW uoıʇɐʇoᴚ ʞɔoןᗺ uǝdO", "create.keyinfo.toolbelt": "sǝxoqןoo⟘ ʎqɹɐǝN ssǝɔɔⱯ", "create.keyinfo.toolmenu": "ʎɐןɹǝʌO ɔıʇɐɯǝɥɔS snɔoℲ", "create.kinetics.creative_motor.rotation_speed": "WԀᴚ uı pǝǝdS pǝʇɐɹǝuǝ⅁", @@ -1298,6 +1526,12 @@ "create.linked_controller.frequency_slot_2": "ᄅ# ˙bǝɹℲ '%1$s :puıqʎǝʞ", "create.linked_controller.key_bound": "%1$s oʇ punoq ʎɔuǝnbǝɹℲ", "create.linked_controller.press_keybind": "ʎǝʞ ǝʌıʇɔǝdsǝɹ ǝɥʇ oʇ ʎɔuǝnbǝɹɟ sıɥʇ puıq oʇ '%6$s ɹo %5$s '%4$s '%3$s '%2$s '%1$s ssǝɹԀ", + "create.logistically_linked.connected": "ʎןןnɟssǝɔɔns ʞɹoʍʇǝu buıʇsıxǝ oʇ pǝʇɔǝuuoƆ", + "create.logistically_linked.new_network_started": "pǝʇɹɐʇs ʞɹoʍʇǝu ʞuıן ʍǝN", + "create.logistically_linked.protected": "pǝʇɔǝʇoɹԀ sı ʞɹoʍʇǝN sɔıʇsıboꞀ", + "create.logistically_linked.tooltip": "pǝɹnbıɟuoɔ ʎɔuǝnbǝɹℲ", + "create.logistically_linked.tooltip_clear": "ʇǝsǝɹ oʇ pıɹb buıʇɟɐɹɔ uı ǝɔɐןԀ", + "create.logistically_linked.tuned": "ʞɹoʍʇǝu sıɥʇ oʇ pǝun⟘", "create.logistics.crafter.click_to_merge": "sǝıɹoʇuǝʌuI ǝbɹǝɯ oʇ ʞɔıןƆ", "create.logistics.crafter.click_to_separate": "sǝıɹoʇuǝʌuI ǝʇɐɹɐdǝs oʇ ʞɔıןƆ", "create.logistics.crafter.connected": "sɹǝʇɟɐɹƆ pǝʇɔǝuuoƆ", @@ -1344,6 +1578,13 @@ "create.orientation.diagonal": "ןɐuobɐıᗡ", "create.orientation.horizontal": "ןɐʇuozıɹoH", "create.orientation.orthogonal": "ןɐuoboɥʇɹO", + "create.package_port.cannot_reach_down": "pɹɐʍuʍop ʇɔǝuuoɔ ʇouuɐƆ", + "create.package_port.too_far": "ʎɐʍɐ ɹɐɟ oo⟘", + "create.package_port.valid": "✔ ʇɔǝuuoƆ uɐƆ", + "create.packager.no_portable_storage": "ʎןʇɔǝɹıp ǝbɐɹoʇS ǝןqɐʇɹoԀ ɥʇıʍ ǝɔɐɟɹǝʇuı ʇouuɐɔ sɹǝbɐʞɔɐԀ", + "create.packager_link.clear": "uoıʇɔǝןǝs pǝɹɐǝןƆ", + "create.packager_link.set": "pǝʇɔǝןǝs ʇǝbɹɐ⟘", + "create.packager_link.success": "ʇǝbɹɐʇ oʇ punoq ʎןןnɟssǝɔɔnS", "create.ponder.analog_lever.header": "ɹǝʌǝꞀ boןɐuⱯ ǝɥʇ buısn sןɐubıs buıןןoɹʇuoƆ", "create.ponder.analog_lever.text_1": "ɹǝʍod ǝuoʇspǝɹ ɟo ǝɔɹnos ǝsıɔǝɹd puɐ ʇɔɐdɯoɔ ɐ ɹoɟ ǝʞɐɯ sɹǝʌǝꞀ boןɐuⱯ", "create.ponder.analog_lever.text_2": "ʇndʇno ɹǝʍod boןɐuɐ sʇı ǝsɐǝɹɔuı oʇ ʞɔıןɔ-ʇɥbıᴚ", @@ -1353,7 +1594,6 @@ "create.ponder.andesite_tunnel.text_2": "˙˙˙sǝpıs ǝɥʇ oʇ suoıʇɔǝuuoɔ sɐɥ ןǝuun⟘ ǝʇısǝpuⱯ uɐ ɹǝʌǝuǝɥM", "create.ponder.andesite_tunnel.text_3": "sʞɔɐʇs buıssɐd ʎuɐ ɟo ɟɟo ɯǝʇı ǝuo ʎןʇɔɐxǝ ʇıןds ןןıʍ ʎǝɥʇ˙˙˙", "create.ponder.andesite_tunnel.text_4": "ɥʇɐd sʇı uo ǝnuıʇuoɔ ןןıʍ ɹǝpuıɐɯǝɹ ǝɥ⟘", - "create.ponder.associated": "sǝıɹʇuƎ pǝʇɐıɔossⱯ", "create.ponder.auto_schedule.header": "buıןnpǝɥɔS & suoıʇɐʇS", "create.ponder.auto_schedule.text_1": "uoıʇɐuıʇsǝp ɐ ɥʇıʍ sɹǝʌıɹp ǝpıʌoɹd oʇ pǝsn ǝq uɐɔ sǝןnpǝɥɔS", "create.ponder.auto_schedule.text_2": "ʇuǝsǝɹd sı uıɐɹ⟘ ɐ ɹǝʌǝuǝɥʍ ןɐubıs ɐ ǝʌıǝɔǝɹ ןןıʍ sɹoʇɐɹɐdɯoƆ", @@ -1443,7 +1683,12 @@ "create.ponder.cart_assembler_rails.text_2": "pǝɹǝʍoԀ s,ʇı ןıʇun ǝɔɐןd uı pןǝɥ ǝq ןןıʍ sʇɹɐɔ ǝɥʇ 'ןıɐᴚ ɹǝןןoɹʇuoƆ ɹo pǝɹǝʍoԀ uo uǝɥM", "create.ponder.cart_assembler_rails.text_3": "ɹoɥɔuɐ ǝɥʇ sɐ pǝsn ǝq uɐɔ sʇɹɐɔǝuıW ɟo sǝdʎʇ ɹǝɥʇO", "create.ponder.cart_assembler_rails.text_4": "sǝıɹoʇuǝʌuı pǝɥɔɐʇʇɐ ʎuɐ ɯoɹɟ ןǝnɟ buıןןnd 'pǝɹǝʍod sǝʌןǝsɯǝɥʇ dǝǝʞ ןןıʍ sʇɹɐƆ ǝɔɐuɹnℲ", - "create.ponder.categories": "ǝʇɐǝɹƆ uı sǝıɹobǝʇɐƆ ǝןqɐןıɐʌⱯ", + "create.ponder.chain_conveyor.header": "sɹoʎǝʌuoƆ uıɐɥƆ buısn ǝɔɹoɟ ןɐuoıʇɐʇoɹ buıʎɐןǝᴚ", + "create.ponder.chain_conveyor.text_1": "ɯǝɥʇ ʇɔǝuuoɔ oʇ suıɐɥɔ ɥʇıʍ sɹoʎǝʌuoɔ oʍʇ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.chain_conveyor.text_2": "˙˙ɹǝɥʇo ɥɔɐǝ uǝǝʍʇǝq ɹǝʍod ןɐuoıʇɐʇoɹ ʎɐןǝɹ sɹoʎǝʌuoɔ uıɐɥƆ", + "create.ponder.chain_conveyor.text_3": "ɯǝɥʇ ʍoןǝq ɹo ǝʌoqɐ sʇɟɐɥs oʇ ʇɔǝuuoɔ puɐ˙˙", + "create.ponder.chain_conveyor.text_4": "uıɐɥɔ ǝɥʇ uo buıןןǝʌɐɹʇ ʇɹɐʇs oʇ ɥɔuǝɹʍ ɐ buıpןoɥ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.chain_conveyor.text_5": "ʇı ʍoןןoɟ oʇ uıɐɥɔ ɐ spɹɐʍoʇ ǝɔɐɟ 'uoıʇɔunظ ɐ ʇⱯ", "create.ponder.chain_drive.header": "sǝʌıɹᗡ uıɐɥƆ ɥʇıʍ ǝɔɹoɟ ןɐuoıʇɐʇoɹ buıʎɐןǝᴚ", "create.ponder.chain_drive.text_1": "ʍoɹ ɐ uı ɹǝɥʇo ɥɔɐǝ oʇ uoıʇɐʇoɹ ʎɐןǝɹ sǝʌıɹᗡ uıɐɥƆ", "create.ponder.chain_drive.text_2": "uoıʇɔǝɹıp ǝɯɐs ǝɥʇ uı ǝʇɐʇoɹ ןןıʍ sıɥʇ ǝʞıן pǝʇɔǝuuoɔ sʇɟɐɥs ןןⱯ", @@ -1473,7 +1718,6 @@ "create.ponder.clockwork_bearing.text_6": "pǝppɐ ǝq uɐɔ ǝɹnʇɔnɹʇs puoɔǝs ɐ 'puɐH ɹnoH ǝɥʇ ɟo ʇuoɹɟ uI", "create.ponder.clockwork_bearing.text_7": "ɹǝɥʇo ɥɔɐǝ oʇ pǝnןb ʇou ǝɹɐ sǝɹnʇɔnɹʇS oʍʇ ǝɥʇ ʇɐɥʇ ǝɹnsuƎ", "create.ponder.clockwork_bearing.text_8": "puɐH ǝʇnuıW ǝɥʇ sɐ ǝʇɐʇoɹ ʍou ןןıʍ ǝɹnʇɔnɹʇS puoɔǝS ǝɥ⟘", - "create.ponder.close": "ǝsoןƆ", "create.ponder.clutch.header": "ɥɔʇnןƆ ɐ buısn ǝɔɹoɟ ןɐuoıʇɐʇoɹ buıןןoɹʇuoƆ", "create.ponder.clutch.text_1": "ǝuıן ʇɥbıɐɹʇs ɐ uı uoıʇɐʇoɹ ʎɐןǝɹ ןןıʍ sǝɥɔʇnןƆ", "create.ponder.clutch.text_2": "uoıʇɔǝuuoɔ ǝɥʇ sʞɐǝɹq ʇı 'ǝuoʇspǝᴚ ʎq pǝɹǝʍod uǝɥM", @@ -1600,7 +1844,52 @@ "create.ponder.encased_fluid_pipe.text_1": "sǝdıԀ pınןℲ ǝʇɐɹoɔǝp oʇ pǝsn ǝq uɐɔ buısɐƆ ɹǝddoƆ", "create.ponder.encased_fluid_pipe.text_2": "ǝʇɐʇs ʎʇıʌıʇɔǝuuoɔ ɹıǝɥʇ oʇuı pǝʞɔoן ǝɹɐ sǝdıԀ pǝsɐɔuƎ 'pǝןɐǝɔuoɔ buıǝq ɯoɹɟ ǝpısⱯ", "create.ponder.encased_fluid_pipe.text_3": "pǝʌoɯǝɹ ɹo pǝppɐ buıǝq sʞɔoןq buıɹnoqɥbıǝu ʎuɐ oʇ ʇɔɐǝɹ ɹǝbuoן ou ןןıʍ ʇI", - "create.ponder.exit": "ʇıxƎ", + "create.ponder.factory_gauge_crafting.header": "sǝbnɐ⅁ ʎɹoʇɔɐℲ ɥʇıʍ buıʇɟɐɹƆ ɔıʇɐɯoʇnⱯ", + "create.ponder.factory_gauge_crafting.text_1": "sǝdıɔǝɹ ǝןqɐʇ buıʇɟɐɹɔ ɹoɟ ʇuǝɯǝbuɐɹɹɐ-oʇnɐ ǝpıʌoɹd sǝbnɐb ʎɹoʇɔɐℲ", + "create.ponder.factory_gauge_crafting.text_2": "ǝɹoɟǝq sɐ sʇuǝıpǝɹbuı pǝɹınbǝɹ ǝɥʇ ʇɔǝuuoƆ", + "create.ponder.factory_gauge_crafting.text_3": "I∩ ǝɥʇ uı sɹɐǝddɐ uoʇʇnq ʍǝu ɐ 'pǝʇɔǝʇǝp sı ǝdıɔǝɹ pıןɐʌ ɐ uǝɥM", + "create.ponder.factory_gauge_crafting.text_4": "ʎןʇɔǝɹıp sɹǝʇɟɐɹɔ oʇuı pǝddɐɹʍun ǝq uɐɔ sǝxoq ǝɥʇ 'ǝʌıʇɔɐ ʇuǝɯǝbuɐɹɹɐ-oʇnɐ ɥʇıM", + "create.ponder.factory_gauge_crafting.text_5": "ɥɔuǝɹʍ ɐıʌ pǝʇɔǝuuoɔ ǝq oʇ ǝʌɐɥ sɹǝʇɟɐɹɔ ǝɥʇ puɐ ƐxƐ ǝq ʇsnɯ dnʇǝs ǝɥ⟘", + "create.ponder.factory_gauge_crafting.text_6": "ʇunoɯɐ ʇǝbɹɐʇ ǝɥʇ ʇǝs oʇ ǝbnɐb ǝɥʇ uo ʞɔıןɔ-ʇɥbıᴚ pןoH", + "create.ponder.factory_gauge_crafting.text_7": "sǝdıɔǝɹ ʇuǝɹǝɟɟıp ɥʇıʍ sǝbnɐb ǝɹoɯ ʎq 'ʎןןɐsɹǝʌıun pǝsn ǝq ʍou uɐɔ ɹǝʇɟɐɹɔ sıɥ⟘", + "create.ponder.factory_gauge_crafting.text_8": "dooן ǝɥʇ ǝsoןɔ oʇ ʎɹoʇuǝʌuı pǝʞuıן ɐ oʇ ʞɔɐq ʇuǝs ǝq pןnoɥs sʇndʇnO", + "create.ponder.factory_gauge_crafting.text_9": "sǝbɐʞɔɐd ʇnduı ɟo uoıʇɐʇuǝɯbɐɹɟ ʇuǝʌǝɹd oʇ pǝpuǝɯɯoɔǝɹ sı ɹǝbɐʞɔɐd-ǝᴚ ɐ buıs∩", + "create.ponder.factory_gauge_links.header": "sʞɔoןᗺ ɹǝɥʇo oʇ sǝbnɐ⅁ buıʇɔǝuuoƆ", + "create.ponder.factory_gauge_links.text_1": "˙˙˙I∩ ǝɥʇ ɯoɹɟ uoıʇɔǝuuoɔ ʍǝu ɐ buıppɐ uǝɥM", + "create.ponder.factory_gauge_links.text_2": "sʞuıꞀ ʎɐןdsıᗡ puɐ ǝuoʇspǝᴚ sʇdǝɔɔɐ osןɐ ǝbnɐb ǝɥʇ˙˙˙", + "create.ponder.factory_gauge_links.text_3": "ʇunoɯɐ ʇǝbɹɐʇ ǝɥʇ ǝʌoqɐ ɹo ʇɐ sı ןǝʌǝן ʞɔoʇs ǝɥʇ uǝɥʍ pǝɹǝʍod ǝq ןןıʍ sʞuıן ǝuoʇspǝᴚ", + "create.ponder.factory_gauge_links.text_4": "sʇsǝnbǝɹ buıpuǝs ɯoɹɟ ǝbnɐb ǝɥʇ doʇs uɐɔ sʞuıן 'ǝpoɯ ɹǝʌıǝɔǝɹ uI", + "create.ponder.factory_gauge_links.text_5": "sǝbnɐb pǝʇɔǝuuoɔ ɟo ʍǝıʌɹǝʌo snʇɐʇs ɐ ǝpıʌoɹd uɐɔ sʞuıן ʎɐןdsıᗡ", + "create.ponder.factory_gauge_recipe.header": "sǝbnɐ⅁ ʎɹoʇɔɐℲ ɥʇıʍ sǝdıɔǝᴚ pǝʇɐɯoʇnⱯ", + "create.ponder.factory_gauge_recipe.text_1": "˙˙˙ɹǝbɐʞɔɐd ɐ uo pǝɔɐןd ʇou ǝɹɐ sǝbnɐb ɹǝʌǝuǝɥM", + "create.ponder.factory_gauge_recipe.text_10": "oʇ ʇuǝs ǝq pןnoɥs sʇuǝıpǝɹbuı ʇɐɥʇ ssǝɹppɐ ǝɥʇ ʎɟıɔǝdS", + "create.ponder.factory_gauge_recipe.text_11": "ǝbnɐb ǝɥʇ uo ʞɔıןɔ-ʇɥbıᴚ buıpןoɥ ʎq ʇǝs ǝq ʍou uɐɔ uıɐʇuıɐɯ oʇ ʇunoɯɐ ʇǝbɹɐʇ ǝɥ⟘", + "create.ponder.factory_gauge_recipe.text_12": "˙˙˙ʇunoɯɐ ǝɥʇ uɐɥʇ sɯǝʇı ɹǝʍǝɟ sɐɥ ʞɹoʍʇǝu ǝɥʇ ɹǝʌǝuǝɥM", + "create.ponder.factory_gauge_recipe.text_13": "ssǝɹppɐ pǝıɟıɔǝds ǝɥʇ oʇ sʇuǝıpǝɹbuı ʍǝu puǝs ןןıʍ ʇı˙˙˙", + "create.ponder.factory_gauge_recipe.text_14": "sǝıɹoʇuǝʌuı pǝʞuıן ǝɥʇ ɟo ʎuɐ oʇ uɹnʇǝɹ oʇ pǝǝu uǝɥʇ sʇndʇno ǝɥ⟘", + "create.ponder.factory_gauge_recipe.text_15": "pǝɥɔɐǝɹ uǝǝq sɐɥ ʇunoɯɐ ʇǝbɹɐʇ ǝɥʇ ʇɐɥʇ ǝʇɐɔıpuı suoıʇɔǝuuoɔ uǝǝɹ⅁", + "create.ponder.factory_gauge_recipe.text_16": "sdǝʇs ǝdıɔǝɹ ǝɹoɯ ǝpnןɔuı oʇ puɐdxǝ uɐɔ sǝbnɐb ɟo pɹɐoq ǝɥ⟘", + "create.ponder.factory_gauge_recipe.text_17": "ʎןʇuǝpuǝdǝpuı ɯǝʇı sʇı ɟo ןǝʌǝן ʞɔoʇs ǝɥʇ suıɐʇuıɐɯ ǝbnɐb ɥɔɐƎ", + "create.ponder.factory_gauge_recipe.text_2": "sǝıɹoʇuǝʌuı pǝʞuıן ןןɐ ɟo sןǝʌǝן ʞɔoʇs ɹoʇıuoɯ pɐǝʇsuı ןןıʍ ʎǝɥ⟘", + "create.ponder.factory_gauge_recipe.text_3": "pǝɹoʇıuoɯ ǝq pןnoɥs ʇɐɥʇ ɯǝʇı ǝɥʇ ɥʇıʍ ʇı ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.factory_gauge_recipe.text_4": "ʞɹoʍʇǝu ǝɥʇ uo ʇuǝsǝɹd ʇunoɯɐ ןɐʇoʇ ǝɥʇ ʎɐןdsıp ʍou ןןıʍ ʇI", + "create.ponder.factory_gauge_recipe.text_5": "pǝssǝɔoɹd ǝq oʇ sɯǝʇı ɹǝɥʇo buıpuǝs ʎq sןǝʌǝן ʞɔoʇs ɥsıuǝןdǝɹ uɐɔ ǝbnɐb ǝɥ⟘", + "create.ponder.factory_gauge_recipe.text_6": "sǝbnɐb ʎɹoʇɔɐɟ ʍǝu sɐ sʇuǝıpǝɹbuı pǝɹınbǝɹ ǝɥʇ ppɐ 'ʇsɹıℲ", + "create.ponder.factory_gauge_recipe.text_7": "ǝpɐɯ ǝq uɐɔ suoıʇɔǝuuoɔ ʍǝu 'I∩ s,ʇǝbɹɐʇ ǝɥʇ ɯoɹℲ", + "create.ponder.factory_gauge_recipe.text_8": "buıɥʇɐd ǝɥʇ ǝbuɐɥɔ oʇ pǝɥɔuǝɹʍ ǝq uɐɔ sןǝuɐd ʇnduı 'sɔıʇǝɥʇsǝɐ ɹoℲ", + "create.ponder.factory_gauge_recipe.text_9": "ɥɔʇɐq ɹǝd ǝpɐɯ sʇǝb ʇndʇno ǝɥʇ ɟo ɥɔnɯ ʍoɥ ʎɟıɔǝds puɐ sʇnduı ǝɥʇ ʍǝıʌǝɹ 'I∩ ǝɥʇ uI", + "create.ponder.factory_gauge_restocker.header": "sǝbnɐ⅁ ʎɹoʇɔɐℲ ɥʇıʍ buıʞɔoʇsǝᴚ", + "create.ponder.factory_gauge_restocker.text_1": "ʞɹoʍʇǝu sʇı oʇ ʇɔǝuuoɔ oʇ ʇuǝɯǝɔɐןd ǝɹoɟǝq ʞuıן ʞɔoʇS ɐ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.factory_gauge_restocker.text_10": "ssǝɹppɐ pǝıɟıɔǝds ǝɥʇ ɥʇıʍ 'ǝɹoɯ spuǝs ʞɹoʍʇǝu sɔıʇsıboן ǝɥʇ˙˙˙", + "create.ponder.factory_gauge_restocker.text_11": "ɹǝbɐʞɔɐd ǝɥʇ oʇ pǝʇnoɹ ǝq uɐɔ ʎǝɥʇ 'ǝɹǝɥʇ ɯoɹℲ", + "create.ponder.factory_gauge_restocker.text_2": "ʎɹoʇuǝʌuı ǝɥʇ ǝpısuı sɯǝʇı ɹoʇıuoɯ uɐɔ sǝbnɐb ʎɹoʇɔɐɟ 'ɹǝbɐʞɔɐd ɐ uo pǝɔɐןd uǝɥM", + "create.ponder.factory_gauge_restocker.text_3": "pǝɹoʇıuoɯ ǝq pןnoɥs ʇɐɥʇ ɯǝʇı ǝɥʇ ɥʇıʍ ʇı ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.factory_gauge_restocker.text_4": "ʎɹoʇuǝʌuı ǝɥʇ uı ʇuǝsǝɹd ʇunoɯɐ ǝɥʇ ʎɐןdsıp ʍou ןןıʍ ʇI", + "create.ponder.factory_gauge_restocker.text_5": "ʞɹoʍʇǝu sɔıʇsıboן ǝɥʇ ɯoɹɟ ʎɹoʇuǝʌuı sıɥʇ ןןıɟǝɹ uɐɔ ǝbnɐb ǝɥ⟘", + "create.ponder.factory_gauge_restocker.text_6": "I∩ uoıʇɐɹnbıɟuoɔ sʇı uǝdo oʇ uıɐbɐ ʇı ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.factory_gauge_restocker.text_7": "sɯǝʇı pǝʇsǝnbǝɹ ǝɥʇ ɹoɟ pǝsn ǝq pןnoɥs ʇɐɥʇ ssǝɹppɐ uɐ ʇǝS", + "create.ponder.factory_gauge_restocker.text_8": "ǝbnɐb ǝɥʇ uo ʞɔıןɔ-ʇɥbıᴚ buıpןoɥ ʎq ʇǝs ǝq ʍou uɐɔ uıɐʇuıɐɯ oʇ ʇunoɯɐ ʇǝbɹɐʇ ǝɥ⟘", + "create.ponder.factory_gauge_restocker.text_9": "˙˙˙ʇunoɯɐ sıɥʇ uɐɥʇ sɯǝʇı ɹǝʍǝɟ sɐɥ ʇsǝɥɔ ǝɥʇ ɹǝʌǝuǝɥM", "create.ponder.fan_direction.header": "suɐℲ pǝsɐɔuƎ ɟo ʍoןɟ ɹıⱯ", "create.ponder.fan_direction.text_1": "ʇuǝɹɹnƆ ɹıⱯ uɐ ǝʇɐǝɹɔ oʇ ǝɔɹoℲ ןɐuoıʇɐʇoᴚ ǝsn suɐℲ pǝsɐɔuƎ", "create.ponder.fan_direction.text_2": "ʇnduI ןɐuoıʇɐʇoᴚ ǝɥʇ uo spuǝdǝp ʍoןℲ ɟo uoıʇɔǝɹıᗡ puɐ ɥʇbuǝɹʇS", @@ -1687,7 +1976,6 @@ "create.ponder.hand_crank.text_1": "ʎןןɐnuɐɯ ǝɔɹoɟ ןɐuoıʇɐʇoɹ ʎןddɐ oʇ sɹǝʎɐןd ʎq pǝsn ǝq uɐɔ sʞuɐɹƆ puɐH", "create.ponder.hand_crank.text_2": "ǝsıʍʞɔoןƆ-ɹǝʇunoƆ ʇı ǝʇɐʇoɹ oʇ ʞɔıןƆ-ʇɥbıᴚ pןoH", "create.ponder.hand_crank.text_3": "ǝsıʍʞɔoןƆ ʇı ǝʇɐʇoɹ oʇ ʞɔıןƆ-ʇɥbıᴚ pןoH puɐ ʞɐǝuS", - "create.ponder.hold_to_ponder": "ɹǝpuoԀ oʇ ]%1$s[ pןoH", "create.ponder.hose_pulley.header": "sʎǝןןnԀ ǝsoH buısn buıuıɐɹᗡ puɐ buıןןıℲ ǝɔɹnoS", "create.ponder.hose_pulley.text_1": "pınןℲ ɟo sǝıpoq ǝbɹɐן uıɐɹp ɹo ןןıɟ oʇ pǝsn ǝq uɐɔ sʎǝןןnԀ ǝsoH", "create.ponder.hose_pulley.text_2": "pǝןןoɹʇuoɔ ǝq uɐɔ ǝsoɥ ,sʎǝןןnd ǝɥʇ ɟo ʇɥbıǝɥ ǝɥʇ 'ʇnduI ɔıʇǝuıʞ ǝɥʇ ɥʇıM", @@ -1706,10 +1994,6 @@ "create.ponder.hose_pulley_level.text_3": "spuǝ ǝsoɥ ǝɥʇ ǝɹǝɥʍ ʍoןǝq ʇsnظ dn puǝ ןןıʍ ןǝʌǝן ǝɔɐɟɹns ǝɥ⟘", "create.ponder.hose_pulley_level.text_4": "doʇ oʇ ɯoʇʇoq ɯoɹɟ sunɹ buıןןıℲ", "create.ponder.hose_pulley_level.text_5": "puǝ ǝsoɥ ǝɥʇ ǝʌoqɐ ɹǝʎɐן ǝɥʇ puoʎǝq ʍoɹb ʇou ןןıʍ ןood pǝןןıɟ ǝɥ⟘", - "create.ponder.identify": "ʎɟıʇuǝpI", - "create.ponder.identify_mode": "]%1$s[ ɥʇıʍ ǝsnɐdu∩\n˙ǝʌıʇɔɐ ǝpoɯ ʎɟıʇuǝpI", - "create.ponder.index_description": "sʞɔoןᗺ puɐ sɯǝʇI pǝʇɐıɔossɐ sʇı ʇnoqɐ uɹɐǝן oʇ suoɔı ǝɥʇ ɟo ǝuo ʞɔıןƆ", - "create.ponder.index_title": "xǝpuI ɹǝpuoԀ", "create.ponder.item_drain.header": "suıɐɹᗡ ɯǝʇI buısn sɹǝuıɐʇuoƆ pınןℲ buıʎʇdɯƎ", "create.ponder.item_drain.text_1": "sɯǝʇı ɯoɹɟ spınןɟ ʇɔɐɹʇxǝ uɐɔ suıɐɹᗡ ɯǝʇI", "create.ponder.item_drain.text_2": "ʇı oʇuı ɯǝʇı pןǝɥ ɹnoʎ ɯoɹɟ spınןɟ ɹnod oʇ ʇı ʞɔıןɔ-ʇɥbıᴚ", @@ -1878,16 +2162,54 @@ "create.ponder.millstone.text_3": "doʇ ǝɥʇ ʇɐ sɯǝʇı ʇɹǝsuI ɹo ʍoɹɥ⟘", "create.ponder.millstone.text_4": "ʞɔıןɔ-ʇɥbıᴚ ɐıʌ pǝuıɐʇqo ǝq uɐɔ ʇןnsǝɹ ǝɥʇ 'ǝɯıʇ ǝɯos ɹǝʇɟⱯ", "create.ponder.millstone.text_5": "uoıʇɐɯoʇnɐ ʎq pǝʇɔɐɹʇxǝ ǝq osןɐ uɐɔ sʇndʇno ǝɥ⟘", - "create.ponder.next": "ǝuǝɔS ʇxǝN", - "create.ponder.next_up": ":ʇxǝN d∩", + "create.ponder.mod_name": "ǝʇɐǝɹƆ", "create.ponder.nixie_tube.header": "sǝqn⟘ ǝıxıN buıs∩", "create.ponder.nixie_tube.text_1": "ɥʇbuǝɹʇs ןɐubıs ǝɥʇ ʎɐןdsıp ןןıʍ sǝqn⟘ ǝıxıN 'ǝuoʇspǝᴚ ʎq pǝɹǝʍod uǝɥM", "create.ponder.nixie_tube.text_2": "pǝʎɐןdsıp ǝq uɐɔ ʇxǝʇ ɯoʇsnɔ 'spɹɐoqdıןƆ uǝʇʇıɹʍ buıs∩", "create.ponder.nixie_tube.text_3": "ɹnoןoɔ ʎɐןdsıp ɹıǝɥʇ ǝbuɐɥɔ oʇ ǝʎᗡ ɥʇıʍ ʞɔıןƆ-ʇɥbıᴚ", + "create.ponder.package_frogport.header": "sʇɹodboɹℲ uǝǝʍʇǝq sǝbɐʞɔɐd buıʇɹodsuɐɹ⟘", + "create.ponder.package_frogport.text_1": "ʎqɹɐǝu ʇɹodboɹℲ ǝɥʇ ǝɔɐןd puɐ ɹoʎǝʌuoƆ uıɐɥƆ ɐ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.package_frogport.text_10": "ʞɹoʍʇǝu uıɐɥɔ ǝɥʇ uo boɹɟ buıɥɔʇɐɯ ɐ oʇ ɥʇɐd ɹıǝɥʇ puıɟ sǝbɐʞɔɐԀ", + "create.ponder.package_frogport.text_11": "ɹǝʇǝԀ", + "create.ponder.package_frogport.text_12": "ɹǝʇǝԀ →", + "create.ponder.package_frogport.text_13": "ɯǝɥʇ ʍoןǝq sǝıɹoʇuǝʌuı ɥʇıʍ ǝɔɐɟɹǝʇuı ʎןʇɔǝɹıp uɐɔ sʇɹodboɹℲ", + "create.ponder.package_frogport.text_14": "ʎןʇɔǝɹıp pǝddıɥs puɐ pǝʞɔɐd ǝq uɐɔ sɯǝʇI ˙sɹǝbɐʞɔɐd ɥʇıʍ sʞɹoʍ osןɐ sıɥ⟘", + "create.ponder.package_frogport.text_15": "ʇɹǝqןⱯ", + "create.ponder.package_frogport.text_16": "ɹǝʇǝԀ", + "create.ponder.package_frogport.text_17": ",ɹǝʇǝԀ, oʇ sǝbɐʞɔɐd sǝssǝɹppⱯ", + "create.ponder.package_frogport.text_18": "ssǝɹppɐ ɹıǝɥʇ ʇɔǝןןoɔ oʇ pɹɐoqdıןɔ ɐ ɥʇıʍ sʇɹodboɹℲ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.package_frogport.text_19": "sI∩ ɹǝɥʇo uı sʇnduı ssǝɹppɐ ǝʇǝןdɯoɔ-oʇnɐ dןǝɥ uɐɔ sǝɯɐu pǝʇɔǝןןoɔ ɥʇıʍ spɹɐoqdıןƆ", + "create.ponder.package_frogport.text_2": "I∩ ʎɹoʇuǝʌuı ǝɥʇ uı ssǝɹppɐ uɐ ʇı ubıssⱯ", + "create.ponder.package_frogport.text_3": "˙˙ʇı ɥɔʇɐɯ ʇou sǝop ǝbɐʞɔɐd pǝʇɹǝsuı uɐ ɟo ssǝɹppɐ ǝɥʇ ɟI", + "create.ponder.package_frogport.text_4": "ʇɹǝqןⱯ", + "create.ponder.package_frogport.text_5": "ɹǝʇǝԀ →", + "create.ponder.package_frogport.text_6": "ɹoʎǝʌuoɔ ǝɥʇ uo ǝbɐʞɔɐd ǝɥʇ ǝɔɐןd ןןıʍ ʇɹodboɹℲ ǝɥʇ˙˙", + "create.ponder.package_frogport.text_7": "uoıʇɐuıʇsǝp pıןɐʌ ou ǝʌɐɥ ʎǝɥʇ ɟı ǝɔɐןd uı uıds sǝbɐʞɔɐԀ", + "create.ponder.package_frogport.text_8": "ʞɹoʍʇǝu uıɐɥɔ ǝɥʇ uo ǝɹǝɥʍʎuɐ pǝppɐ ǝq uɐɔ sʇɹodboɹℲ ǝɹoW", + "create.ponder.package_frogport.text_9": "ɹǝʇǝԀ", + "create.ponder.packager.header": "sǝbɐʞɔɐd buıddɐɹʍun puɐ buıʇɐǝɹƆ", + "create.ponder.packager.text_1": "ʇǝbɹɐʇ pןnoɥs ʎǝɥʇ ʎɹoʇuǝʌuı ǝɥʇ oʇ sɹǝbɐʞɔɐd ɥɔɐʇʇⱯ", + "create.ponder.packager.text_2": "ǝbɐʞɔɐd ɐ oʇuı ʎɹoʇuǝʌuı ǝɥʇ ɯoɹɟ sɯǝʇı ʞɔɐd ןןıʍ ʇı 'ɹǝʍod ǝuoʇspǝɹ uǝʌı⅁", + "create.ponder.packager.text_3": "ɯǝʇı ɹǝɥʇo ʎuɐ ǝʞıן pǝʇɹodsuɐɹʇ puɐ dn pǝʞɔıd ǝq uɐɔ ǝsǝɥ⟘", + "create.ponder.packager.text_4": "ʎɹoʇuǝʌuı ǝɥʇ oʇuı sʇuǝʇuoɔ ǝɥʇ buıʞɔɐdun 'pǝʎoɹʇsǝp ǝq ןןıʍ pǝʇɹǝsuı sǝbɐʞɔɐԀ", + "create.ponder.packager.text_5": "ןןnℲ", + "create.ponder.packager.text_6": "ʞɔɐdun ʎןןnɟ ʇouuɐɔ ʎǝɥʇ sǝbɐʞɔɐd ʇdǝɔɔɐ ʇou ןןıʍ sɹǝbɐʞɔɐԀ", + "create.ponder.packager_address.header": "ssǝɹppɐ uɐ ɥʇıʍ sǝbɐʞɔɐd buıʇnoᴚ", + "create.ponder.packager_address.text_1": "ǝsnoɥǝɹɐM", + "create.ponder.packager_address.text_10": "ʇןǝq ɐ oʇuo ʇɥbıɐɹʇs ʞɔɐdun uɐɔ sʍɐs ןɐɔıuɐɥɔǝɯ 'ssǝuʇɔɐdɯoɔ ɹoℲ", + "create.ponder.packager_address.text_11": "sǝıʇıןıqɐ buıʇnoɹ ǝbɐʞɔɐd ǝʌɐɥ sǝxoqʇsoԀ puɐ sʇɹodboɹℲ 'sɹǝʇןıɟ ɯoɹɟ ǝpısⱯ", + "create.ponder.packager_address.text_12": "ɹnoıʌɐɥǝq ɹıǝɥʇ ʇnoqɐ ǝɹoɯ ʇno puıɟ oʇ ɯǝɥʇ ʇɔǝdsuI", + "create.ponder.packager_address.text_2": "˙˙ɹǝbɐʞɔɐd ɐ uo pǝɔɐןd sı ubıs ɐ uǝɥM", + "create.ponder.packager_address.text_3": "ǝsnoɥǝɹɐM →", + "create.ponder.packager_address.text_4": "ssǝɹppɐ ɹıǝɥʇ sɐ ʇxǝʇ ɟo ǝuıן uǝʇʇıɹʍ ǝɥʇ ʎɹɹɐɔ ןןıʍ sǝbɐʞɔɐd pǝʇɐǝɹƆ", + "create.ponder.packager_address.text_5": "ssǝɹppɐ ɹıǝɥʇ uo pǝsɐq sǝbɐʞɔɐd ǝʇnoɹ sɹǝʇןıɟ ǝbɐʞɔɐԀ", + "create.ponder.packager_address.text_6": "ǝsnoɥǝɹɐM →", + "create.ponder.packager_address.text_7": "ʎɹoʇɔɐℲ", + "create.ponder.packager_address.text_8": "ʎɹoʇɔɐℲ →", + "create.ponder.packager_address.text_9": "ʎɹoʇɔɐℲ", "create.ponder.piston_pole.header": "sǝןoԀ uoısuǝʇxƎ uoʇsıԀ", "create.ponder.piston_pole.text_1": "ǝʌoɯ ʇouuɐɔ uoʇsıԀ ןɐɔıuɐɥɔǝW ɐ 'sǝןoԀ pǝɥɔɐʇʇɐ ʇnoɥʇıM", "create.ponder.piston_pole.text_2": "ǝbuɐᴚ uoısuǝʇxƎ ǝɥʇ sǝuıɯɹǝʇǝp ʞɔɐq sʇı ʇɐ pǝppɐ ǝןod ɟo ɥʇbuǝꞀ ǝɥ⟘", - "create.ponder.pondering": "˙˙˙ʇnoqɐ buıɹǝpuoԀ", "create.ponder.portable_fluid_interface.header": "ǝbuɐɥɔxƎ pınןℲ uoıʇdɐɹʇuoƆ", "create.ponder.portable_fluid_interface.text_1": "sǝdıd ʎuɐ ʎq pǝssǝɔɔɐ ǝq ʇouuɐɔ suoıʇdɐɹʇuoɔ buıʌoɯ uo sʞuɐ⟘ pınןℲ", "create.ponder.portable_fluid_interface.text_2": "uoıʇdɐɹʇuoɔ ǝɥʇ doʇs oʇ pǝǝu ǝɥʇ ʇnoɥʇıʍ sʞuɐʇ pınןɟ ɥʇıʍ ʇɔɐɹǝʇuı uɐɔ ʇuǝuodɯoɔ sıɥ⟘", @@ -1908,6 +2230,19 @@ "create.ponder.portable_storage_interface.text_8": "ʎɐʍ sʇı uo ǝnuıʇuoɔ ןןıʍ uoıʇdɐɹʇuoɔ ǝɥʇ 'ǝןıɥʍ ɐ ɹoɟ pǝbuɐɥɔxǝ uǝǝq ǝʌɐɥ sɯǝʇı ou ɹǝʇɟⱯ", "create.ponder.portable_storage_interface_redstone.header": "ןoɹʇuoƆ ǝuoʇspǝᴚ", "create.ponder.portable_storage_interface_redstone.text_1": "buıbɐbuǝ ɯoɹɟ ǝɔɐɟɹǝʇuı ʎɹɐuoıʇɐʇs ǝɥʇ ʇuǝʌǝɹd ןןıʍ ɹǝʍod ǝuoʇspǝᴚ", + "create.ponder.postbox.header": "sǝxoqʇsoԀ uǝǝʍʇǝq sǝbɐʞɔɐd buıʇɹodsuɐɹ⟘", + "create.ponder.postbox.text_1": "ʎqɹɐǝu xoqʇsoԀ ǝɥʇ ǝɔɐןd puɐ uoıʇɐʇS uıɐɹ⟘ ɐ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.postbox.text_10": "ǝsnoɥǝɹɐM →", + "create.ponder.postbox.text_11": "sʞunɥɔ pǝpɐoןun uı ɹnoıʌɐɥǝq ɹıǝɥʇ uıɐʇuıɐɯ sǝxoqʇsoԀ 'suıɐɹʇ ǝʞıן ʇsnſ", + "create.ponder.postbox.text_12": "ʎɹoʇuǝʌuı ɹıǝɥʇ oʇ ɹo ɯoɹɟ pǝɹǝʌıןǝp ǝq ןןıʇs uɐɔ sǝbɐʞɔɐԀ", + "create.ponder.postbox.text_2": "I∩ ʎɹoʇuǝʌuı ǝɥʇ uı ssǝɹppɐ uɐ ʇı ubıssⱯ", + "create.ponder.postbox.text_3": "˙˙ʇı ɥɔʇɐɯ ʇou sǝop ǝbɐʞɔɐd pǝʇɹǝsuı uɐ ɟo ssǝɹppɐ ǝɥʇ ɟI", + "create.ponder.postbox.text_4": "ǝsnoɥǝɹɐM", + "create.ponder.postbox.text_5": "ʇsodʇnO →", + "create.ponder.postbox.text_6": "obɹɐɔ sɐ ʇı ʇɔǝןןoɔ ןןıʍ uoıʇɐʇs ǝɥʇ ʇɐ buıddoʇs suıɐɹʇ˙˙", + "create.ponder.postbox.text_7": "ɟɟo pǝddoɹp ǝq ןןıʍ ssǝɹppɐ ǝɥʇ buıɥɔʇɐɯ sǝbɐʞɔɐd 'ʎןǝsɹǝʌuoƆ", + "create.ponder.postbox.text_8": "xoqʇsoԀ ǝɥʇ ɯoɹɟ pǝʇɔɐɹʇxǝ ǝq uɐɔ uıɐɹʇ ʎq pǝʌıɹɹɐ ʇɐɥʇ sǝbɐʞɔɐԀ", + "create.ponder.postbox.text_9": "ǝsnoɥǝɹɐM", "create.ponder.powered_latch.header": "ɥɔʇɐꞀ pǝɹǝʍoԀ ǝɥʇ buısn sןɐubıs buıןןoɹʇuoƆ", "create.ponder.powered_latch.text_1": "sɹǝʌǝꞀ ǝןqɐןןoɹʇuoɔ ǝuoʇspǝɹ ǝɹɐ sǝɥɔʇɐꞀ pǝɹǝʍoԀ", "create.ponder.powered_latch.text_2": "uo ʇı ɥɔʇıʍs ʞɔɐq ǝɥʇ ʇɐ sןɐubıS", @@ -1918,7 +2253,6 @@ "create.ponder.powered_toggle_latch.text_2": "ǝʇɐʇs sʇı ǝןbboʇ ןןıʍ ʞɔɐq ǝɥʇ ʇɐ sןɐubıS", "create.ponder.powered_toggle_latch.text_3": "ɟɟo ʞɔɐq puɐ uo˙˙˙", "create.ponder.powered_toggle_latch.text_4": "ʎןןɐnuɐɯ pǝןbboʇ ǝq osןɐ uɐɔ sǝɥɔʇɐן ǝןbboʇ pǝɹǝʍoԀ", - "create.ponder.previous": "ǝuǝɔS snoıʌǝɹԀ", "create.ponder.pulse_extender.header": "sɹǝpuǝʇxƎ ǝsןnԀ buısn sןɐubıs buıןןoɹʇuoƆ", "create.ponder.pulse_extender.text_1": "ɥbnoɹɥʇ buıssɐd ןɐubıs ɐ uǝɥʇbuǝן uɐɔ sɹǝpuǝʇxƎ ǝsןnԀ", "create.ponder.pulse_extender.text_2": "˙˙˙ʎɐןǝp ʇɹoɥs ɐ ɹǝʇɟɐ ǝʇɐʌıʇɔɐ ʎǝɥ⟘", @@ -1929,6 +2263,12 @@ "create.ponder.pulse_repeater.text_1": "ʎɐןǝp ɐ ɹǝʇɟɐ ǝsןnd ʇɹoɥs ɐ ʇıɯǝ sɹǝʇɐǝdǝᴚ ǝsןnԀ", "create.ponder.pulse_repeater.text_2": "pǝɹnbıɟuoɔ ǝq uɐɔ ǝɯıʇ ǝbɹɐɥɔ ǝɥʇ 'ןǝuɐd ǝnןɐʌ ǝɥʇ buıs∩", "create.ponder.pulse_repeater.text_3": "ɹnoɥ uɐ oʇ dn ǝbuɐɹ uɐɔ sʎɐןǝp pǝɹnbıɟuoƆ", + "create.ponder.pulse_timer.header": "ɹǝɯı⟘ ǝsןnԀ ǝɥʇ ɟo ʇndʇno ǝuoʇspǝᴚ", + "create.ponder.pulse_timer.text_1": "sǝsןnd ʇɹoɥs ʇıɯǝ ʎןpǝʇɐǝdǝɹ sɹǝɯı⟘ ǝsןnԀ", + "create.ponder.pulse_timer.text_2": "pǝɹnbıɟuoɔ ǝq uɐɔ ןɐʌɹǝʇuı ǝɯıʇ ǝɥʇ 'ןǝuɐd ǝnןɐʌ ǝɥʇ buıs∩", + "create.ponder.pulse_timer.text_3": "ɯǝɥʇ ʇǝsǝɹ puɐ ǝsnɐd ןןıʍ ǝpıs ʇnduı ǝɥʇ buıɹǝʍoԀ", + "create.ponder.pulse_timer.text_4": "ʇndʇno ǝɥʇ ʇɹǝʌuı oʇ ǝsɐq ʇınɔɹıɔ ǝɥʇ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.pulse_timer.text_5": "ןɐubıs ǝuoʇspǝɹ ɐ ʇnoɥʇıʍ ʎןuo ǝʇɐʌıʇɔɐ ʇɐɥʇ sɯsıuɐɥɔǝɯ ɹǝbbıɹʇ sdןǝɥ sıɥ⟘", "create.ponder.radial_chassis.header": "sıssɐɥƆ ןɐıpɐᴚ buısn sʞɔoןq buıɥɔɐʇʇⱯ", "create.ponder.radial_chassis.text_1": "ʍoɹ ɐ uı sʞɔoןq sıssɐɥƆ ןɐɔıʇuǝpı oʇ ʇɔǝuuoɔ sıssɐɥƆ ןɐıpɐᴚ", "create.ponder.radial_chassis.text_2": "ʇı ɥʇıʍ pǝbbɐɹp ǝɹɐ sɹǝɥʇo ǝɥʇ 'uoıʇdɐɹʇuoƆ ɐ ʎq pǝʌoɯ sı ǝuo uǝɥM", @@ -1949,7 +2289,22 @@ "create.ponder.redstone_link.text_4": "sʞɔoןq 9ϛᄅ uıɥʇıʍ sɹǝʇʇıɯsuɐɹʇ ɟo ɹǝʍod ǝuoʇspǝɹ ǝɥʇ ʇıɯǝ sɹǝʌıǝɔǝᴚ", "create.ponder.redstone_link.text_5": "ʎɔuǝnbǝɹℲ ɐ ʎɟıɔǝds uɐɔ sʇoןs oʍʇ ǝɥʇ uı sɯǝʇı buıɔɐןԀ", "create.ponder.redstone_link.text_6": "ǝʇɐɔıunɯɯoɔ ןןıʍ sǝıɔuǝnbǝɹℲ buıɥɔʇɐɯ ɥʇıʍ sʞuıן ǝɥʇ ʎןuO", - "create.ponder.replay": "ʎɐןdǝᴚ", + "create.ponder.redstone_requester.header": "sɹǝʇsǝnbǝᴚ ǝuoʇspǝᴚ ɥʇıʍ sɹǝpɹo pǝʇɐɯoʇnⱯ", + "create.ponder.redstone_requester.text_1": "ʞɹoʍʇǝu sʇı oʇ ʇɔǝuuoɔ oʇ ʇuǝɯǝɔɐןd ǝɹoɟǝq ʞuıן ʞɔoʇS ɐ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.redstone_requester.text_2": "ʞɹoʍʇǝu sɔıʇsıboן ǝɥʇ ɯoɹɟ sɯǝʇı ɹǝpɹo uɐɔ sɹǝʇsǝnbǝɹ ǝuoʇspǝᴚ 'sɹǝʞɔıʇ ʞɔoʇS ǝʞıן ʇsnſ", + "create.ponder.redstone_requester.text_3": "I∩ uoıʇɐɹnbıɟuoɔ sʇı uǝdo oʇ ɹǝʇsǝnbǝɹ ǝɥʇ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.redstone_requester.text_4": "ǝsןnd ǝuoʇspǝɹ ʎɹǝʌǝ uo pǝʇsǝnbǝɹ ǝq ןןıʍ I∩ ǝɥʇ uı ʇǝs ɹǝpɹo ǝɥ⟘", + "create.ponder.redstone_requester.text_5": "ʇuǝɯǝɔɐןd ǝɹoɟǝq pǝɹnbıɟuoɔ ʎןןnɟ ǝq uɐɔ ɹǝʇsǝnbǝɹ ǝɥʇ 'ʎןǝʌıʇɐuɹǝʇןⱯ", + "create.ponder.redstone_requester.text_6": "ǝɹǝɥʇ ɹǝpɹo pǝɹısǝp ǝɥʇ ʇǝs puɐ ʇı ɥʇıʍ ɹǝdǝǝʞ ʞɔoʇS ɐ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.repackager.header": "ʇsǝnbǝɹ ɐ ɯoɹɟ sǝbɐʞɔɐd buıbɹǝW", + "create.ponder.repackager.text_1": "ǝbɐʞɔɐd ǝןbuıs ɐ sɐ ǝʌıɹɹɐ oʇ sʇsǝnbǝɹ ןɐɔıʇsıboן ɹoɟ ןɐıɔnɹɔ sı ʇı 'sǝɯıʇǝɯoS", + "create.ponder.repackager.text_2": "Ɐ ɹǝpɹO", + "create.ponder.repackager.text_3": "ᗺ ɹǝpɹO", + "create.ponder.repackager.text_4": "uǝǝʍʇǝquı ǝʌıɹɹɐ pןnoɔ sǝbɐʞɔɐd ɹǝɥʇo 'ǝsıʍɹǝɥʇO", + "create.ponder.repackager.text_5": "ʎɹoʇuǝʌuı uɐ oʇ sǝbɐʞɔɐd ʇɔǝɹıpǝɹ 'ǝsɐɔ ǝɥʇ sı sıɥʇ uǝɥM", + "create.ponder.repackager.text_6": "ǝuoʇspǝɹ ɥʇıʍ ʇı ɹǝʍod puɐ 'ɹǝbɐʞɔɐd-ǝɹ ɐ ɥɔɐʇʇⱯ", + "create.ponder.repackager.text_7": "ǝbɐʞɔɐd ʍǝu ɐ sɐ pǝʇɹodxǝ ǝq ןןıʍ ʎǝɥʇ 'pǝʌıɹɹɐ sʇuǝɯbɐɹɟ ןןɐ ǝɔuO", + "create.ponder.repackager.text_8": "ɹǝpɹo ǝןqɐʇɔıpǝɹd ɐ uı puɐ ɹǝɥʇǝboʇ ǝʌıɹɹɐ sɯǝʇı pǝʇsǝnbǝɹ 'ʍoN", "create.ponder.rope_pulley.header": "sʎǝןןnԀ ǝdoᴚ buısn sǝɹnʇɔnɹʇS buıʌoW", "create.ponder.rope_pulley.text_1": "ǝɔɹoℲ ןɐuoıʇɐʇoᴚ uǝʌıb uǝɥʍ ʎןןɐɔıʇɹǝʌ sʞɔoןq ǝʌoɯ uɐɔ sʎǝןןnԀ ǝdoᴚ", "create.ponder.rope_pulley.text_2": "ʇnduI ןɐuoıʇɐʇoᴚ ǝɥʇ uo puǝdǝp ʇuǝɯǝʌoɯ ɟo pǝǝdS puɐ uoıʇɔǝɹıᗡ", @@ -1993,15 +2348,12 @@ "create.ponder.shaft_casing.header": "sʇɟɐɥS buısɐɔuƎ", "create.ponder.shaft_casing.text_1": "sʇɟɐɥS ǝʇɐɹoɔǝp oʇ pǝsn ǝq uɐɔ buısɐƆ ǝʇısǝpuⱯ ɹo ssɐɹᗺ", "create.ponder.shared.behaviour_modify_value_panel": "ןǝuɐd ǝnןɐʌ ǝɥʇ buısn pǝıɟıpoɯ ǝq uɐɔ ɹnoıʌɐɥǝq sıɥ⟘", - "create.ponder.shared.ctrl_and": "+ ןɹʇƆ", - "create.ponder.shared.movement_anchors": "pǝʌoɯ ǝq uɐɔ sǝɹnʇɔnɹʇs ɹǝbɹɐן 'ǝnן⅁ ɹǝdnS ɟo dןǝɥ ǝɥʇ ɥʇıM", + "create.ponder.shared.movement_anchors": "˙pǝʌoɯ ǝq uɐɔ sǝɹnʇɔnɹʇs ɹǝbɹɐן 'ǝnן⅁ ɹǝdnS ɟo dןǝɥ ǝɥʇ ɥʇıM", "create.ponder.shared.rpm16": "WԀᴚ 9Ɩ", "create.ponder.shared.rpm16_source": "WԀᴚ 9Ɩ :ǝɔɹnoS", "create.ponder.shared.rpm32": "WԀᴚ ᄅƐ", "create.ponder.shared.rpm8": "WԀᴚ 8", - "create.ponder.shared.sneak_and": "+ ʞɐǝuS", "create.ponder.shared.storage_on_contraption": "ʎןןɐɔıʇɐɯoʇnɐ sdoɹp ɹıǝɥʇ dn ʞɔıd ןןıʍ uoıʇdɐɹʇuoƆ ǝɥʇ oʇ pǝɥɔɐʇʇɐ sǝıɹoʇuǝʌuI", - "create.ponder.slow_text": "buıpɐǝᴚ ʎɟɯoƆ", "create.ponder.smart_chute.header": "sǝʇnɥƆ ʇɹɐɯS buısn sɯǝʇI buıɹǝʇןıℲ", "create.ponder.smart_chute.text_1": "ןoɹʇuoɔ ןɐuoıʇıppɐ ɥʇıʍ sǝʇnɥɔ ןɐɔıʇɹǝʌ ǝɹɐ sǝʇnɥƆ ʇɹɐɯS", "create.ponder.smart_chute.text_2": "ɹǝɟsuɐɹʇ ɹo ʇɔɐɹʇxǝ oʇ ʇɐɥʍ ʎɟıɔǝds ʇoןs ɹǝʇןıɟ ǝɥʇ uı sɯǝʇI", @@ -2061,11 +2413,43 @@ "create.ponder.sticker.text_2": "ǝʇɐʇs sʇı ǝןbboʇ ןןıʍ ʇı 'ןɐubıs ɐ buıʌıǝɔǝɹ uod∩", "create.ponder.sticker.text_3": "ʇı ɥʇıʍ ǝʌoɯ ןןıʍ ʞɔoןq ǝɥʇ 'uoıʇdɐɹʇuoɔ ɐ uı pǝʌoɯ ʍou sı ʇı ɟI", "create.ponder.sticker.text_4": "pǝɥɔɐʇʇɐ ɹǝbuoן ou sı ʞɔoןq ǝɥʇ 'uıɐbɐ ǝɔuo pǝןbbo⟘", + "create.ponder.stock_link.header": "ʞuıꞀ ʞɔoʇS ǝɥʇ puɐ sʞɹoʍʇǝN sɔıʇsıboꞀ", + "create.ponder.stock_link.text_1": "ʞɹoʍʇǝu ʞɔoʇs ʍǝu ɐ ǝʇɐǝɹɔ sʞuıꞀ ʞɔoʇS 'pǝɔɐןd uǝɥM", + "create.ponder.stock_link.text_2": "ɯǝɥʇ puıq oʇ ʇı buıɔɐןd ǝɹoɟǝq ʞuıן buıʇsıxǝ uɐ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.stock_link.text_3": "ʞɹoʍʇǝu ǝɥʇ oʇ ǝןqɐןıɐʌɐ ʎɹoʇuǝʌuı ɹıǝɥʇ ǝʞɐɯ sɹǝbɐʞɔɐd pǝʞuıן-ʞɔoʇS", + "create.ponder.stock_link.text_4": "sɯǝʇı ɹıǝɥʇ ʇsǝnbǝɹ puɐ puıɟ ʍou uɐɔ ʞɹoʍʇǝu ǝɥʇ uo sʇuǝuodɯoɔ ɹǝɥʇO", + "create.ponder.stock_link.text_5": "sǝbɐʞɔɐd oʇuı pǝɔɐןd ǝq ןןıʍ sǝıɹoʇuǝʌuı ǝɥʇ ɯoɹɟ sɯǝʇı 'ʇsǝnbǝɹ uO", + "create.ponder.stock_link.text_6": "uoıʇɐʇɹodsuɐɹʇ ǝɹınbǝɹ sǝbɐʞɔɐd ʇnq 'ǝbuɐɹ pǝʇıɯıןun ǝʌɐɥ sןɐubıs ʞuıꞀ ʞɔoʇS", + "create.ponder.stock_link.text_7": "buıʇsɐɔpɐoɹq ɯoɹɟ ʞuıן ɐ doʇs ןןıʍ ɹǝʍod ǝuoʇspǝɹ ןןnℲ", + "create.ponder.stock_link.text_8": "ʇsɹıɟ ʇɔɐ oʇ sɹǝɥʇo buısnɐɔ 'ʞuıן ɐ ɟo ʎʇıɹoıɹd ǝɥʇ sɹǝʍoן ɹǝʍod boןɐuⱯ", + "create.ponder.stock_ticker.header": "sɹǝʞɔıʇ ʞɔoʇS ɥʇıʍ sɯǝʇı buıɹǝpɹO", + "create.ponder.stock_ticker.text_1": "ʞɹoʍʇǝu sʇı oʇ ʇɔǝuuoɔ oʇ ʇuǝɯǝɔɐןd ǝɹoɟǝq ʞuıן ʞɔoʇS ɐ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.stock_ticker.text_10": "uouuɐɔıʇɐɯǝɥɔs ǝɥʇ ɹoɟ pǝɹınbǝɹ sʞɔoןq ɹǝpɹo osןɐ uɐɔ sɹǝʞɔıʇ ʞɔoʇS", + "create.ponder.stock_ticker.text_11": "ɹǝdǝǝʞ ʞɔoʇS ǝɥʇ oʇ pǝʇɐɹǝuǝb ʇı pɹɐoqdıןɔ pǝʇuıɹd ǝɥʇ puɐɥ ʎןdɯıS", + "create.ponder.stock_ticker.text_2": "ʞɹoʍʇǝu ǝɥʇ oʇ ǝןqɐןıɐʌɐ ʎɹoʇuǝʌuı pǝɥɔɐʇʇɐ ɹıǝɥʇ ǝʞɐɯ sɹǝbɐʞɔɐd pǝʞuıן-ʞɔoʇS", + "create.ponder.stock_ticker.text_3": "sǝıɹoʇuǝʌuı ǝsǝɥʇ ɯoɹɟ sɯǝʇı ɹǝpɹo uɐɔ sɹǝʞɔıʇ ʞɔoʇS", + "create.ponder.stock_ticker.text_4": "ɹǝdǝǝʞ ʞɔoʇS ǝɥʇ sɐ ʇɔɐ ʇı ɟo ʇuoɹɟ uı sɹǝuɹnq ǝzɐןq ɹo sqoɯ pǝʇɐǝS", + "create.ponder.stock_ticker.text_5": "sɯǝʇı buıɹǝpɹo ʇɹɐʇs oʇ ɹǝdǝǝʞ ǝɥʇ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.stock_ticker.text_6": "sǝbɐʞɔɐd oʇuı pǝɔɐןd ǝq ןןıʍ sɯǝʇı ǝɥʇ 'pǝʇʇıɯqns sı ɹǝpɹo uɐ uǝɥM", + "create.ponder.stock_ticker.text_7": "ʇuıod ʇsǝnbǝɹ ǝɥʇ oʇ pǝʇɹodsuɐɹʇ ǝq uɐɔ ʎǝɥʇ 'ǝɹǝɥʇ ɯoɹℲ", + "create.ponder.stock_ticker.text_8": "sbuıʇsıן ɯǝʇı ǝɥʇ oʇ pǝppɐ ǝq uɐɔ sǝıɹobǝʇɐɔ 'sɹǝʇןıɟ ʇsıן ɹo ǝʇnqıɹʇʇɐ buıs∩", + "create.ponder.stock_ticker.text_9": "ɹoʇıpǝ ʎɹobǝʇɐɔ ǝɥʇ uǝdo oʇ ɹǝʞɔıʇ ʞɔoʇS ǝɥʇ ʞɔıןɔ-ʇɥbıᴚ", + "create.ponder.stock_ticker_address.header": "ɹǝpɹo ɹǝʞɔıʇ ʞɔoʇS ɐ buıssǝɹppⱯ", + "create.ponder.stock_ticker_address.text_1": "ʇsǝnbǝɹ ǝɥʇ uı ʇǝs ǝq uɐɔ ssǝɹppɐ ʇǝbɹɐʇ ɐ 'sɯǝʇı buıɹǝpɹo uǝɥM", + "create.ponder.stock_ticker_address.text_10": "sǝıʇıןıqɐ buıʇnoɹ ǝbɐʞɔɐd ǝʌɐɥ sǝxoqʇsoԀ puɐ sʇɹodboɹℲ 'sɹǝʇןıɟ ɯoɹɟ ǝpısⱯ", + "create.ponder.stock_ticker_address.text_11": "ɹnoıʌɐɥǝq ɹıǝɥʇ ʇnoqɐ ǝɹoɯ ʇno puıɟ oʇ ɯǝɥʇ ʇɔǝdsuI", + "create.ponder.stock_ticker_address.text_2": "doɥsʞɹoM →", + "create.ponder.stock_ticker_address.text_3": "ʇsǝnbǝɹ ǝɥʇ ɹoɟ pǝʇɐǝɹɔ sǝbɐʞɔɐd ןןɐ uo ǝq ןןıʍ ssǝɹppɐ sıɥ⟘", + "create.ponder.stock_ticker_address.text_4": "ob ןןıʍ sǝbɐʞɔɐd ǝɥʇ ǝɹǝɥʍ ןoɹʇuoɔ uɐɔ sıɥʇ 'sɹǝʇןıɟ ǝbɐʞɔɐd buıs∩", + "create.ponder.stock_ticker_address.text_5": "doɥsʞɹoM →", + "create.ponder.stock_ticker_address.text_6": "doɥsʞɹoM", + "create.ponder.stock_ticker_address.text_7": "ʎɹoʇɔɐℲ →", + "create.ponder.stock_ticker_address.text_8": "ʎɹoʇɔɐℲ →", + "create.ponder.stock_ticker_address.text_9": "doɥsʞɹoM", "create.ponder.stressometer.header": "ɹǝʇǝɯossǝɹʇS ǝɥʇ buısn uoıʇɐɯɹoɟuı ɔıʇǝuıʞ buıɹoʇıuoW", "create.ponder.stressometer.text_1": "ʞɹoʍʇǝu ɔıʇǝuıʞ pǝɥɔɐʇʇɐ ǝɥʇ ɟo ʎʇıɔɐdɐƆ ssǝɹʇS ʇuǝɹɹnɔ ǝɥʇ sʎɐןdsıp ɹǝʇǝɯossǝɹʇS ǝɥ⟘", "create.ponder.stressometer.text_2": "ǝbnɐ⅁ ǝɥʇ ɯoɹɟ uoıʇɐɯɹoɟuı pǝןıɐʇǝp ǝɹoɯ ʇǝb uɐɔ ɹǝʎɐןd ǝɥʇ 'sǝןbbo⅁ ,sɹǝǝuıbuƎ buıɹɐǝʍ uǝɥM", "create.ponder.stressometer.text_3": "sʇuǝɯǝɹnsɐǝɯ s,ɹǝʇǝɯossǝɹʇS ǝɥʇ oʇ ǝʌıʇɐןǝɹ sןɐubıS ǝuoʇsǝᴚ boןɐuɐ ʇıɯǝ uɐɔ sɹoʇɐɹɐdɯoƆ", - "create.ponder.subject": "ǝuǝɔs sıɥʇ ɟo ʇɔǝظqnS", "create.ponder.super_glue.header": "ǝnן⅁ ɹǝdnS buısn sʞɔoןq buıɥɔɐʇʇⱯ", "create.ponder.super_glue.text_1": "suoıʇdɐɹʇuoɔ buıʌoɯ oʇuı ɹǝɥʇǝboʇ sʞɔoןq sdnoɹb ǝnן⅁ ɹǝdnS", "create.ponder.super_glue.text_2": "ɐǝɹɐ ,pǝnןb, ʍǝu ɐ sǝʇɐǝɹɔ sʇuıodpuǝ oʍʇ buıʞɔıןƆ", @@ -2073,6 +2457,19 @@ "create.ponder.super_glue.text_4": "buoןɐ ɹǝɥʇo ɥɔɐǝ ןןnd ןןıʍ ɐǝɹɐ uɐ buıɹɐɥs sʞɔoןq ʇuǝɔɐظpⱯ", "create.ponder.super_glue.text_5": "ɹǝɥʇǝboʇ ǝʌoɯ ןןıʍ sǝɯnןoʌ ǝnןb buıddɐןɹǝʌO", "create.ponder.super_glue.text_6": "ǝnןb ǝɹınbǝɹ ʇou op ʎןןɐnsn sɹǝɥʇo uo buıbuɐɥ sʞɔoןᗺ", + "create.ponder.table_cloth.header": "sɥʇoןƆ ǝןqɐ⟘ ɥʇıʍ sɯǝʇı buıןןǝS", + "create.ponder.table_cloth.text_1": "sɯǝʇı ʎɐןdsıp oʇ pǝsn ǝq uɐɔ sɥʇoןɔ ǝןqɐ⟘", + "create.ponder.table_cloth.text_10": "ǝbɐʞɔɐd ɐ oʇuı pǝɔɐןd ǝq ןןıʍ sɯǝʇı ʇɥbnoq ǝɥʇ 'ɹǝıɥsɐɔ ǝɥʇ ʇɐ ʇno buıʞɔǝɥɔ uǝɥM", + "create.ponder.table_cloth.text_11": "ʇuoɹɟ doɥs ǝɥʇ oʇ pǝʇɹodsuɐɹʇ ǝq uɐɔ ʎǝɥʇ 'ǝɹǝɥʇ ɯoɹℲ", + "create.ponder.table_cloth.text_12": "ʞɔoןq ɹǝʞɔıʇ ʞɔoʇs ǝɥʇ ǝpısuı pǝɹoʇs ǝq ןןıʍ sʇuǝɯʎɐd ǝɥ⟘", + "create.ponder.table_cloth.text_2": "sɯǝʇı ןןǝs oʇ pǝsn ǝq osןɐ uɐɔ ʎǝɥʇ 'ɯǝʇsʎs sɔıʇsıboן ɐ ɟo dןǝɥ ǝɥʇ ɥʇıM", + "create.ponder.table_cloth.text_3": "ʞuıן ʞɔoʇS puɐ ɹǝbɐʞɔɐԀ ɐ 'ʎɹoʇuǝʌuı s,doɥs ǝɥʇ ɥʇıʍ ʇɹɐʇS", + "create.ponder.table_cloth.text_4": "doɥs ǝɥʇ uı ʇı ǝɔɐןd puɐ ʞuıן ǝɥʇ oʇ ɹǝʞɔıʇ ʞɔoʇS ɐ puıᗺ", + "create.ponder.table_cloth.text_5": "ɹǝdǝǝʞ doɥs ǝɥʇ sɐ ɹǝuɹnq ǝzɐןq ɹo qoɯ ɐ ʎoןdɯƎ", + "create.ponder.table_cloth.text_6": "pןos ǝq oʇ sɯǝʇı ɥʇıʍ ʎɹoʇuǝʌuı doɥs ǝɥʇ ןןıℲ", + "create.ponder.table_cloth.text_7": "ɥʇoןɔ ǝןqɐʇ ɐ buıpןoɥ ǝןıɥʍ ɹǝdǝǝʞ doɥs ǝɥʇ ɥʇıʍ ʇɔɐɹǝʇuı 'ǝpɐɹʇ ʍǝu ɐ ǝʇɐǝɹɔ o⟘", + "create.ponder.table_cloth.text_8": "ǝpıs ǝɥʇ uo ʇoןs ɯǝʇı ǝɥʇ uı ǝɔıɹd ɐ ʇǝs 'pǝɔɐןd ǝɔuO", + "create.ponder.table_cloth.text_9": "doɥs ǝɥʇ ɥʇıʍ ʇɔɐɹǝʇuı ʍou uɐɔ sɹǝʎɐןd ɹǝɥʇO", "create.ponder.tag.arm_targets": "sɯɹⱯ ןɐɔıuɐɥɔǝW ɹoɟ sʇǝbɹɐ⟘", "create.ponder.tag.arm_targets.description": "ɯɹⱯ ןɐɔıuɐɥɔǝW ǝɥʇ oʇ sʇndʇno ɹo sʇnduı sɐ pǝʇɔǝןǝs ǝq uɐɔ ɥɔıɥʍ sʇuǝuodɯoƆ", "create.ponder.tag.contraption_actor": "sɹoʇɔⱯ uoıʇdɐɹʇuoƆ", @@ -2089,6 +2486,8 @@ "create.ponder.tag.display_targets.description": "ʞuıꞀ ʎɐןdsıᗡ ɐ ɯoɹɟ pǝʌıǝɔǝɹ ɐʇɐp ǝɥʇ ʎɐןdsıp puɐ ssǝɔoɹd uɐɔ ɥɔıɥʍ sʞɔoןᗺ ɹo sʇuǝuodɯoƆ", "create.ponder.tag.fluids": "sɹoʇɐןndıuɐW pınןℲ", "create.ponder.tag.fluids.description": "spınןℲ ɟo ǝsn buıʞɐɯ puɐ buıʎɐןǝɹ dןǝɥ ɥɔıɥʍ sʇuǝuodɯoƆ", + "create.ponder.tag.high_logistics": "sɔıʇsıboꞀ ɥbıH", + "create.ponder.tag.high_logistics.description": "ʎɹoʇɔɐɟ ɹnoʎ punoɹɐ sʇsǝnbǝɹ pǝʇɐɯoʇnɐ puɐ ǝbɐɹoʇs ɯǝʇı pǝʇnqıɹʇsıp ǝbɐuɐɯ dןǝɥ ɥɔıɥʍ sʇuǝuodɯoƆ", "create.ponder.tag.kinetic_appliances": "sǝɔuɐıןddⱯ ɔıʇǝuıʞ", "create.ponder.tag.kinetic_appliances.description": "ǝɔɹoℲ ןɐuoıʇɐʇoᴚ ɟo ǝsn ǝʞɐɯ ɥɔıɥʍ sʇuǝuodɯoƆ", "create.ponder.tag.kinetic_relays": "sʞɔoןᗺ ɔıʇǝuıʞ", @@ -2099,15 +2498,14 @@ "create.ponder.tag.logistics.description": "punoɹɐ sɯǝʇı buıʌoɯ dןǝɥ ɥɔıɥʍ sʇuǝuodɯoƆ", "create.ponder.tag.movement_anchor": "sɹoɥɔuⱯ ʇuǝɯǝʌoW", "create.ponder.tag.movement_anchor.description": "sʎɐʍ ɟo ʎʇǝıɹɐʌ ɐ uı ǝɹnʇɔnɹʇs pǝɥɔɐʇʇɐ uɐ buıʇɐɯıuɐ 'suoıʇdɐɹʇuoɔ buıʌoɯ ɟo uoıʇɐǝɹɔ ǝɥʇ ʍoןןɐ ɥɔıɥʍ sʇuǝuodɯoƆ", - "create.ponder.tag.recently_updated": "sǝbuɐɥƆ ʇuǝɔǝᴚ", - "create.ponder.tag.recently_updated.description": "ǝʇɐǝɹƆ ɟo suoısɹǝʌ ʇsǝʇɐן ǝɥʇ uı ʎןʇuɐɔıɟıubıs pǝbuɐɥɔ ɹo pǝppɐ uǝǝq ǝʌɐɥ ʇɐɥʇ sʇuǝuodɯoƆ", "create.ponder.tag.redstone": "sʇuǝuodɯoƆ ɔıboꞀ", "create.ponder.tag.redstone.description": "buıɹǝǝuıbuǝ ǝuoʇspǝɹ ɥʇıʍ dןǝɥ ɥɔıɥʍ sʇuǝuodɯoƆ", + "create.ponder.tag.threshold_switch_targets": "sǝɥɔʇıʍS pןoɥsǝɹɥ⟘ ɹoɟ sʇǝbɹɐ⟘", + "create.ponder.tag.threshold_switch_targets.description": "˙sɹǝuıɐʇuoɔ pınןɟ puɐ ɯǝʇı ʇsoɯ sɐ ןןǝʍ sɐ 'sʞɔoןq ǝsǝɥʇ ɯoɹɟ pɐǝɹ uɐɔ sǝɥɔʇıʍS pןoɥsǝɹɥ⟘", "create.ponder.tag.train_related": "ʇuǝɯdınbƎ ʎɐʍןıɐᴚ", "create.ponder.tag.train_related.description": "suoıʇdɐɹʇuoƆ uıɐɹ⟘ ɟo ʇuǝɯǝbɐuɐɯ ɹo uoıʇɔnɹʇsuoɔ ǝɥʇ uı pǝsn sʇuǝuodɯoƆ", "create.ponder.tag.windmill_sails": "sbuıɹɐǝᗺ ןןıɯpuıM ɹoɟ sןıɐS", "create.ponder.tag.windmill_sails.description": "˙os buıop uı ʎɔuǝıɔıɟɟǝ ןɐnbǝ ǝʌɐɥ ǝsǝɥʇ ɟo ɥɔɐƎ ˙pǝןqɯǝssɐ uǝɥʍ uoıʇdɐɹʇuoƆ ןןıɯpuıM ɐ ɟo ɥʇbuǝɹʇs ǝɥʇ spɹɐʍoʇ ʇunoɔ ʇɐɥʇ sʞɔoןᗺ", - "create.ponder.think_back": "ʞɔɐᗺ ʞuıɥ⟘", "create.ponder.threshold_switch.header": "ɥɔʇıʍS pןoɥsǝɹɥ⟘ ǝɥʇ ɥʇıʍ buıɹoʇıuoW", "create.ponder.threshold_switch.text_1": "sɹǝuıɐʇuoɔ ɟo ןǝʌǝן ןןıɟ ǝɥʇ ɹoʇıuoɯ sǝɥɔʇıʍS pןoɥsǝɹɥ⟘", "create.ponder.threshold_switch.text_2": "˙˙˙pןoɥsǝɹɥʇ ɹǝddn ǝɥʇ spǝǝɔxǝ ʇuǝʇuoɔ ʎɹoʇuǝʌuı ǝɥʇ uǝɥM", @@ -2229,7 +2627,6 @@ "create.ponder.weighted_ejector_tunnel.text_3": "ɟɟo ʇıןds ǝq oʇ ʇunoɯɐ ǝɥʇ sǝuıɯɹǝʇǝp ʍou ɹoʇɔǝظƎ ǝɥʇ uo ʇǝs ǝzıS ʞɔɐʇS ǝɥ⟘", "create.ponder.weighted_ejector_tunnel.text_4": "˙˙˙ʇndʇno ǝpıs ǝɥʇ sʇıxǝ ǝzıs pǝɹnbıɟuoɔ ǝɥʇ ɟo ʞɔɐʇs ʍǝu ɐ ǝןıɥM", "create.ponder.weighted_ejector_tunnel.text_5": "ɥʇɐd sʇı uo ǝnuıʇuoɔ ןןıʍ ɹǝpuıɐɯǝɹ ǝɥʇ˙˙˙", - "create.ponder.welcome": "ɹǝpuoԀ oʇ ǝɯoɔןǝM", "create.ponder.windmill_source.header": "sbuıɹɐǝᗺ ןןıɯpuıM buısn ǝɔɹoℲ ןɐuoıʇɐʇoᴚ buıʇɐɹǝuǝ⅁", "create.ponder.windmill_source.text_1": "ɯǝɥʇ ɟo ʇuoɹɟ uı ʞɔoןq ǝɥʇ oʇ ɥɔɐʇʇɐ sbuıɹɐǝᗺ ןןıɯpuıM", "create.ponder.windmill_source.text_2": "ǝnן⅁ ɹǝdnS ɟo dןǝɥ ǝɥʇ ɥʇıʍ ǝɹnʇɔnɹʇs ǝןqɐʌoɯ ɐ ǝʇɐǝɹƆ", @@ -2289,6 +2686,8 @@ "create.recipe.sequenced_assembly": "ǝɔuǝnbǝS ǝdıɔǝᴚ", "create.recipe.spout_filling": "ʇnodS ʎq buıןןıℲ", "create.recipe.wood_cutting": "buıʇʇnƆ pooM", + "create.redstone_requester.keeper_connected": "ʎןןnɟssǝɔɔns ɹǝdǝǝʞ ʞɔoʇS oʇ pǝʇɔǝuuoƆ", + "create.redstone_requester.keeper_too_far_away": "ɹǝdǝǝʞ ʞɔoʇS ɯoɹɟ ʎɐʍɐ ɹɐɟ ooʇ ɹǝʇsǝnbǝᴚ", "create.schedule.applied_to_train": "ǝןnpǝɥɔS sıɥʇ buıʍoןןoɟ ʍou sı uıɐɹ⟘", "create.schedule.auto_removed_from_train": "pǝpɹɐɔsıp ǝןnpǝɥɔS-oʇnⱯ", "create.schedule.condition.delay": "ʎɐןǝᗡ pǝןnpǝɥɔS", @@ -2355,6 +2754,10 @@ "create.schedule.condition.unloaded.status": "pɐoןun ʞunɥɔ ɹoɟ buıʇıɐM", "create.schedule.condition_type": ":ɹǝʇɟɐ/ɟı ǝnuıʇuoƆ", "create.schedule.continued": "pǝɯnsǝɹ ǝןnpǝɥɔS", + "create.schedule.instruction.address_filter_edit_box": "ssǝɹppⱯ sıɥʇ ɥʇıʍ sǝbɐʞɔɐԀ ǝʌǝıɹʇǝᴚ", + "create.schedule.instruction.address_filter_edit_box_1": "pɹɐɔpןıʍ ʇxǝʇ ɐ sɐ * ǝs∩", + "create.schedule.instruction.address_filter_edit_box_2": "ʇı ʇɔǝןןoɔ oʇ ǝɹǝɥʍʎuɐ ǝʇɐbıʌɐu ʎɐɯ uıɐɹ⟘", + "create.schedule.instruction.address_filter_edit_box_3": "uɹnʇǝɹ ʇı ǝʞɐɯ oʇ uoıʇɔnɹʇsuı ɹǝɥʇouɐ ppⱯ", "create.schedule.instruction.destination": "uoıʇɐʇS oʇ ןǝʌɐɹ⟘", "create.schedule.instruction.destination.summary": ":doʇS ʇxǝN", "create.schedule.instruction.editor": "ɹoʇıpƎ uoıʇɔnɹʇsuI", @@ -2365,6 +2768,14 @@ "create.schedule.instruction.name_edit_box": "ǝןʇı⟘ ǝןnpǝɥɔS", "create.schedule.instruction.name_edit_box_1": "sʎɐןdsıp uo uʍoɥs ʇxǝʇ sʇɔǝɟɟⱯ", "create.schedule.instruction.name_edit_box_2": "ǝɯɐu s,uoıʇɐuıʇsǝp ʇxǝu oʇ sʇןnɐɟǝᗡ", + "create.schedule.instruction.package_delivery": "ǝbɐʞɔɐԀ ɹǝʌıןǝᗡ", + "create.schedule.instruction.package_delivery.summary": "obɹɐɔ uı ǝbɐʞɔɐd ʇsɹıɟ ɹǝʌıןǝᗡ", + "create.schedule.instruction.package_delivery.summary_1": "ɥʇıʍ uoıʇɐʇs ǝɥʇ oʇ sǝʌıɹᗡ", + "create.schedule.instruction.package_delivery.summary_2": "xoqʇsod ʇɔǝɹɹoɔ ǝɥʇ", + "create.schedule.instruction.package_retrieval": "ǝbɐʞɔɐԀ ǝʌǝıɹʇǝᴚ", + "create.schedule.instruction.package_retrieval.summary": ":oʇ pǝssǝɹppɐ ǝbɐʞɔɐd ɐ ɥɔʇǝℲ", + "create.schedule.instruction.package_retrieval.summary_1": "ɥʇıʍ xoqʇsod ɐ oʇ sǝʌıɹᗡ", + "create.schedule.instruction.package_retrieval.summary_2": "ǝbɐʞɔɐd pǝɹǝʌıןǝpun uɐ", "create.schedule.instruction.rename": "ǝןʇı⟘ ǝןnpǝɥɔS ǝʇɐpd∩", "create.schedule.instruction.rename.summary": ":ǝןʇı⟘ ʍǝN", "create.schedule.instruction.throttle": "pǝǝdS xɐW ʇıɯıꞀ", @@ -2456,6 +2867,7 @@ "create.schematics.maxAllowedSize": ":sı ǝzıs ǝןıɟ ɔıʇɐɯǝɥɔs pǝʍoןןɐ ɯnɯıxɐɯ ǝɥ⟘", "create.schematics.synchronizing": "˙˙˙buıɔuʎS", "create.schematics.uploadTooLarge": "˙ɹǝʌɹǝs ǝɥʇ ʎq pǝıɟıɔǝds suoıʇɐʇıɯıן spǝǝɔxǝ ɔıʇɐɯǝɥɔs ɹnoʎ", + "create.schematics.wrongFormat": "˙ʇɐɯɹoɟ ǝןqıʇɐdɯoɔ ԀIZ⅁ ɥʇıʍ pǝpoɔuǝ ǝq pןnoɥs ʇI ¡ʎןbuoɹʍ pǝpoɔuǝ ɹo ʇdnɹɹoɔ ɹǝɥʇıǝ sı pɐoןdn oʇ buıʎɹʇ ǝɹɐ noʎ ɔıʇɐɯǝɥɔs ǝɥ⟘", "create.station.assemble_train": "uıɐɹ⟘ ǝןqɯǝssⱯ", "create.station.assembly_title": "ʎןqɯǝssⱯ uıɐɹ⟘", "create.station.cancel": "ʎןqɯǝssⱯ ןǝɔuɐƆ", @@ -2482,9 +2894,24 @@ "create.station.train_map_color": "sdɐW uo ɹoןoƆ", "create.station.train_not_aligned": "'ǝןqɯǝssɐsıp ʇouuɐƆ", "create.station.train_not_aligned_1": "pǝubıןɐ sǝbɐıɹɹɐɔ ןןɐ ʇou", + "create.stock_keeper.cash_register_full": "ɹǝʇsıbǝᴚ ɥsɐƆ uı ǝɔɐds ɥbnouǝ ʇoN :pǝןןǝɔuɐɔ ǝsɐɥɔɹnԀ", + "create.stock_keeper.keeper_missing": "buıssıɯ ɹǝdǝǝʞ ʞɔoʇS", + "create.stock_keeper.limited_stock": "pǝɥɔɐǝɹ ʇıɯıן ʞɔoʇS", + "create.stock_keeper.locked": "pǝʞɔoן uǝǝq sɐɥ ssǝɔɔɐ ʇɔǝɹıp 'ʇsıן buıddoɥS ɐ buısn ʇɔɐɹǝʇuI", + "create.stock_keeper.no_price_set": "ʇsɹıɟ ǝɔıɹd ɐ ʇǝs ʇsnɯ ɹǝuʍo doɥS", + "create.stock_keeper.out_of_stock": "ʞɔoʇS ɟo ʇnO", + "create.stock_keeper.shopping_list_empty_hand": "ʇsıן buıddoɥs ɐ ʇɹɐʇs oʇ pǝɹınbǝɹ puɐɥ ʎʇdɯƎ", + "create.stock_keeper.stock_level_too_low": "pǝʇɔǝdxǝ uɐɥʇ ɹǝʍoן sןǝʌǝן ʞɔoʇS :pǝןןǝɔuɐɔ ǝsɐɥɔɹnԀ", + "create.stock_keeper.too_broke": "ǝsɐɥɔɹnd sıɥʇ pɹoɟɟɐ ʇouuɐɔ noʎ", + "create.stock_keeper.use_list_to_add_purchases": "ǝsɐɥɔɹnd ɹnoʎ oʇ ǝɹoɯ ppɐ oʇ ʇsıן sıɥʇ ǝs∩", + "create.stock_ticker.click_to_retrieve": "ǝʌǝıɹʇǝɹ oʇ ʞɔıןƆ", + "create.stock_ticker.contains_payments": ":sʇuǝɯʎɐd suıɐʇuoƆ", + "create.stock_ticker.keeper_missing": "ʇı ǝsn oʇ ʞɔoןq sıɥʇ oʇ ʇxǝu ɹǝuɹnq ǝzɐןq ɹo qoɯ ɐ ʇɐǝS", "create.subtitle.blaze_munch": "sǝɥɔunɯ ɹǝuɹnᗺ ǝzɐןᗺ", + "create.subtitle.cardboard_bonk": "ʞuoq ʇuɐuosǝᴚ", "create.subtitle.cogs": "ǝןqɯnɹ sןǝǝɥʍboƆ", "create.subtitle.confirm": "buıp ǝʌıʇɐɯɹıɟɟⱯ", + "create.subtitle.confirm_2": "buıp ǝʌıʇɐɯɹıɟɟⱯ", "create.subtitle.contraption_assemble": "sǝʌoɯ uoıʇdɐɹʇuoƆ", "create.subtitle.contraption_disassemble": "sdoʇs uoıʇdɐɹʇuoƆ", "create.subtitle.controller_click": "sʞɔıןɔ ɹǝןןoɹʇuoƆ", @@ -2498,13 +2925,21 @@ "create.subtitle.deny": "dooq buıuıןɔǝᗡ", "create.subtitle.depot_plop": "spuɐן ɯǝʇI", "create.subtitle.depot_slide": "sǝpıןs ɯǝʇI", + "create.subtitle.desk_bell": "sbuıp ןןǝq uoıʇdǝɔǝᴚ", + "create.subtitle.frogport_catch": "ǝbɐʞɔɐd sǝɥɔʇɐɔ ʇɹodboɹℲ", + "create.subtitle.frogport_close": "sʇnɥs ʇɹodboɹℲ", + "create.subtitle.frogport_deposit": "ǝbɐʞɔɐd sǝɔɐןd ʇɹodboɹℲ", + "create.subtitle.frogport_open": "suǝdo ʇɹodboɹℲ", "create.subtitle.funnel_flap": "sdɐןɟ ןǝuunℲ", - "create.subtitle.fwoomp": "sdɯooʍɟ ɹǝɥɔunɐꞀ oʇɐʇoԀ", + "create.subtitle.fwoomp": "dɯooʍɟ ʇuɐuosǝᴚ", "create.subtitle.haunted_bell_convert": "suǝʞɐʍɐ ןןǝᗺ pǝʇunɐH", "create.subtitle.haunted_bell_use": "sןןoʇ ןןǝᗺ pǝʇunɐH", + "create.subtitle.item_hatch": "suǝdo ɥɔʇɐH ɯǝʇI", "create.subtitle.mechanical_press_activation": "sbuɐןɔ ssǝɹԀ ןɐɔıuɐɥɔǝW", "create.subtitle.mechanical_press_activation_belt": "sʞuoq ssǝɹԀ ןɐɔıuɐɥɔǝW", "create.subtitle.mixing": "sǝsıou buıxıW", + "create.subtitle.package_pop": "sʞɐǝɹq ǝbɐʞɔɐԀ", + "create.subtitle.packager": "sǝbɐʞɔɐd ɹǝbɐʞɔɐԀ", "create.subtitle.peculiar_bell_use": "sןןoʇ ןןǝᗺ ɹɐıןnɔǝԀ", "create.subtitle.potato_hit": "sʇɔɐdɯı ǝןqɐʇǝbǝΛ", "create.subtitle.sanding_long": "sǝsıou buıpuɐS", @@ -2517,6 +2952,9 @@ "create.subtitle.slime_added": "sǝɥsınbs ǝɯıןS", "create.subtitle.spout": "sʇɹnds ʇnodS", "create.subtitle.steam": "sǝsıou ɯɐǝʇS", + "create.subtitle.stock_link": "sʇɔɐǝɹ ʞuıן ʞɔoʇS", + "create.subtitle.stock_ticker_request": "sʇsǝnbǝɹ ɹǝʞɔıʇ ʞɔoʇS", + "create.subtitle.stock_ticker_trade": ",¡buıɥɔ-ɐʞ, sǝob ɹǝʞɔıʇ ʞɔoʇS", "create.subtitle.train": "ǝןqɯnɹ sןǝǝɥʍ ʎǝboᗺ", "create.subtitle.train3": "pǝןɟɟnɯ ǝןqɯnɹ sןǝǝɥʍ ʎǝboᗺ", "create.subtitle.whistle": "buıןʇsıɥM", @@ -2540,6 +2978,13 @@ "create.symmetry.mirror.doublePlane": "ɹɐןnbuɐʇɔǝᴚ", "create.symmetry.mirror.plane": "ǝɔuO ɹoɹɹıW", "create.symmetry.mirror.triplePlane": "ןɐuobɐʇɔO", + "create.table_cloth.amount": "ʇunoɯⱯ", + "create.table_cloth.hand_to_shop_keeper": "ɹǝdǝǝʞ doɥs ɐ oʇ sıɥʇ puɐH", + "create.table_cloth.price_per_order": "ɹǝpɹO ɹǝd ǝɔıɹԀ", + "create.table_cloth.shop_configured": "pǝɹnbıɟuoɔ doɥs ɯǝʇI", + "create.table_cloth.shopping_list_discarded": "pǝpɹɐɔsıp ʇsıן buıddoɥS", + "create.table_cloth.sneak_click_discard": "pɹɐɔsıp oʇ ʞɔıןƆ-ʞɐǝuS", + "create.table_cloth.total_cost": " :ʇsoɔ ןɐʇo⟘", "create.terrainzapper.leftClickToSet": "ןɐıɹǝʇɐW ʇǝs oʇ ʞɔoןᗺ ɐ ʞɔıןƆ-ʇɟǝꞀ", "create.terrainzapper.shiftRightClickToSet": "ǝdɐɥS ɐ ʇɔǝןǝS oʇ ʞɔıןƆ-ʇɥbıᴚ-ʇɟıɥS", "create.terrainzapper.usingBlock": "%1$s :buıs∩", @@ -2627,6 +3072,7 @@ "create.train.status": "%1$s :uıɐɹ⟘ ʇnoqɐ uoıʇɐɯɹoɟuI >ı<", "create.train.status.back_on_track": "ʞɔɐɹ⟘ uo ʞɔɐq sı uıɐɹ⟘", "create.train.status.collision": "uıɐɹ⟘ ɹǝɥʇo ɥʇıʍ uoısıןןoƆ", + "create.train.status.collision.where": "]%2$s[ ɹɐǝu %1$s uI", "create.train.status.coupling_stress": "sbuıןdnoƆ uo ssǝɹʇS oʇ ǝnp doʇs pǝɔɹoℲ", "create.train.status.double_portal": "ɹǝɥʇouɐ buıʌɐǝן ʇsןıɥʍ ןɐʇɹod ɐ ɹǝʇuǝ ʇouuɐɔ ǝbɐıɹɹɐƆ Ɐ", "create.train.status.end_of_track": "ʞɔɐɹ⟘ sʇı ɟo puǝ ǝɥʇ pǝɥɔɐǝɹ sɐɥ ǝbɐıɹɹɐƆ Ɐ", @@ -2634,6 +3080,7 @@ "create.train.status.missing_driver": "buıssıɯ ǝuob sɐɥ ɹǝʌıɹᗡ", "create.train.status.navigation_success": "pǝpǝǝɔɔns uoıʇɐbıʌɐN", "create.train.status.no_match": ",%1$s, sǝɥɔʇɐɯ ɥdɐɹb uo uoıʇɐʇs oN", + "create.train.status.no_package_target": "ssǝɹppɐ sʇı sǝɥɔʇɐɯ ʇɐɥʇ xoqʇsod ou sɐɥ obɹɐɔ uı ǝbɐʞɔɐd Ɐ", "create.train.status.no_path": "punoɟ ǝq pןnoɔ uoıʇɐuıʇsǝp pǝןnpǝɥɔS ʇxǝu ǝɥʇ oʇ ɥʇɐd ǝןqɐʇıns oN", "create.train.status.opposite_driver": "uoıʇɔǝɹıp ǝʇısoddo ǝɥʇ buıɔɐɟ ɹǝʌıɹp ɐ sǝɹınbǝɹ ɥʇɐԀ", "create.train.status.paused_for_manual": "sןoɹʇuoɔ ןɐnuɐɯ ɹoɟ pǝsnɐd ǝןnpǝɥɔS", @@ -2646,7 +3093,7 @@ "create.train_assembly.no_controls": ")¿ǝnן⅁ ɹǝdnS buıssıɯ noʎ ǝɹⱯ( ʞɔoןq sןoɹʇuoƆ uıɐɹ⟘ buıɔɐɟ-pɹɐʍɹoɟ ǝuo ʇsɐǝן ʇɐ ɥɔɐʇʇⱯ", "create.train_assembly.not_connected_in_order": "ɹǝpɹo uı pǝʇɔǝuuoɔ ʇou ǝɹɐ sʎǝboᗺ", "create.train_assembly.nothing_attached": "%1$s ʎǝboᗺ oʇ pǝɥɔɐʇʇɐ ǝɹnʇɔnɹʇs oN", - "create.train_assembly.requires_casing": "sʞɔɐɹʇ uo sʎǝboq ǝʇɐǝɹɔ oʇ buısɐƆ ʎɐʍןıɐᴚ ǝs∩", + "create.train_assembly.requires_casing": "sʞɔɐɹʇ uo sʎǝboq ǝʇɐǝɹɔ oʇ buısɐƆ uıɐɹ⟘ ǝs∩", "create.train_assembly.sideways_controls": "sʎɐʍǝpıs ǝɔɐɟ ʇouuɐɔ sןoɹʇuoƆ uıɐɹ⟘", "create.train_assembly.single_bogey_carriage": "uʍo sʇı uo ǝbɐıɹɹɐɔ ɐ ʇɹoddns ʇouuɐɔ ǝdʎʇ ʎǝboᗺ sıɥ⟘", "create.train_assembly.too_many_bogeys": "%1$s :pǝɥɔɐʇʇɐ sʎǝboᗺ ʎuɐɯ oo⟘", @@ -2702,6 +3149,7 @@ "entity.create.contraption": "uoıʇdɐɹʇuoƆ", "entity.create.crafting_blueprint": "ʇuıɹdǝnןᗺ buıʇɟɐɹƆ", "entity.create.gantry_contraption": "uoıʇdɐɹʇuoƆ ʎɹʇuɐ⅁", + "entity.create.package": "ǝbɐʞɔɐԀ", "entity.create.potato_projectile": "ǝןıʇɔǝظoɹԀ oʇɐʇoԀ", "entity.create.seat": "ʇɐǝS", "entity.create.stationary_contraption": "uoıʇdɐɹʇuoƆ ʎɹɐuoıʇɐʇS", @@ -2726,6 +3174,16 @@ "item.create.brass_sheet": "ʇǝǝɥS ssɐɹᗺ", "item.create.builders_tea": "ɐǝ⟘ s,ɹǝpןınᗺ", "item.create.builders_tea.tooltip.summary": "‾˙buıʇɐɹnʇɐS‾ puɐ ‾buıʇɐʌıʇoW‾ -pǝʇɹɐʇs ʎɐp ǝɥʇ ʇǝb oʇ ʞuıɹp ʇɔǝɟɹǝd ǝɥ⟘", + "item.create.cardboard": "pɹɐoqpɹɐƆ", + "item.create.cardboard_armor.tooltip.behaviour1": "˙‾ǝsınbsıp‾ snonɔıdsuoɔuı uɐ ǝʇɐʌıʇɔɐ oʇ ‾ʞɐǝuS‾", + "item.create.cardboard_armor.tooltip.condition1": "pǝddınbǝ ʇǝs ןןnɟ uǝɥM", + "item.create.cardboard_armor.tooltip.summary": "˙‾ɥʇןɐǝʇs‾ puɐ ‾ǝןʎʇs‾ pǝsɐǝɹɔuı ɹoɟ ‾ʇuǝɯdınbǝ‾ ‾ǝןqɐɹɐǝM‾", + "item.create.cardboard_boots": "sʇooᗺ pɹɐoqpɹɐƆ", + "item.create.cardboard_chestplate": "ǝʇɐןdʇsǝɥƆ pɹɐoqpɹɐƆ", + "item.create.cardboard_helmet": "ʇǝɯןǝH pɹɐoqpɹɐƆ", + "item.create.cardboard_leggings": "sbuıbbǝꞀ pɹɐoqpɹɐƆ", + "item.create.cardboard_sword": "pɹoʍS pɹɐoqpɹɐƆ", + "item.create.cardboard_sword.tooltip.summary": "˙ǝɔıoɥɔ ɟo uodɐǝʍ ןnɟɹǝʍod ʇǝʎ '‾ssǝןɯɹɐɥ‾ ‾ʎןʇsoɯ‾ Ɐ ˙ʞuoᗺ", "item.create.chest_minecart_contraption": "uoıʇdɐɹʇuoƆ ʇɹɐɔǝuıW ʇsǝɥƆ", "item.create.chocolate_bucket": "ʇǝʞɔnᗺ ǝʇɐןoɔoɥƆ", "item.create.chocolate_glazed_berries": "sǝıɹɹǝᗺ pǝzɐן⅁ ǝʇɐןoɔoɥƆ", @@ -2838,6 +3296,11 @@ "item.create.netherite_diving_helmet.tooltip.behaviour1": "ɐʌɐꞀ uı ‾uoısıʌ pǝʌoɹdɯı‾ sʇuɐɹb osןⱯ ˙ʞuɐʇʞɔɐᗺ ǝɥʇ ɯoɹɟ ‾ǝɹnssǝɹԀ ɹıⱯ‾ buıuıɐɹp ʎןʍoןs '‾ɐʌɐꞀ‾ puɐ ‾ǝɹıℲ‾ oʇ ʎʇıunɯɯı sǝpıʌoɹԀ", "item.create.netherite_diving_helmet.tooltip.condition1": ")ʇǝs ןןnℲ( uɹoM uǝɥM", "item.create.netherite_diving_helmet.tooltip.summary": "˙ooʇ '‾ǝʇıɹǝɥʇǝN‾ uı pǝɹǝʌoɔ ǝq oʇ ǝʌɐɥ ‾ʇǝǝℲ puɐ sbǝꞀ‾ 'ǝʌıʇɔǝɟɟǝ ǝq o⟘ ˙‾ʇɐǝɥ ǝɯǝɹʇxǝ‾ ɯoɹɟ noʎ ʇɔǝʇoɹd uɐɔ sıɥʇ '‾ʞuɐʇʞɔɐᗺ ǝʇıɹǝɥʇǝN‾ ɐ ɥʇıʍ ɹǝɥʇǝbo⟘", + "item.create.package": "ǝbɐʞɔɐԀ pɹɐoqpɹɐƆ", + "item.create.package_filter": "ɹǝʇןıℲ ǝbɐʞɔɐԀ", + "item.create.package_filter.tooltip.behaviour1": "˙‾ǝɔɐɟɹǝʇuı uoıʇɐɹnbıɟuoɔ‾ ǝɥʇ suǝdO", + "item.create.package_filter.tooltip.condition1": "pǝʞɔıןƆ-ᴚ uǝɥM", + "item.create.package_filter.tooltip.summary": "sʇuǝuodɯoƆ s,ǝʇɐǝɹƆ ɟo ‾sʇoןS ɹǝʇןıℲ‾ uı pǝsn ǝq uɐƆ ˙‾ssǝɹppɐ‾ pǝʇǝbɹɐʇ ɹıǝɥʇ ʎq ‾sɯǝʇı pǝbɐʞɔɐd sǝɥɔʇɐW‾", "item.create.polished_rose_quartz": "zʇɹɐnὉ ǝsoᴚ pǝɥsıןoԀ", "item.create.potato_cannon": "uouuɐƆ oʇɐʇoԀ", "item.create.potato_cannon.tooltip.behaviour1": "˙‾ʎɹoʇuǝʌuI‾ ɹnoʎ ɯoɹɟ ɯǝʇı ǝןqɐʇıns ɐ ‾sʇooɥS‾", @@ -2848,6 +3311,8 @@ "item.create.powdered_obsidian": "uɐıpısqO pǝɹǝpʍoԀ", "item.create.precision_mechanism": "ɯsıuɐɥɔǝW uoısıɔǝɹԀ", "item.create.propeller": "ɹǝןןǝdoɹԀ", + "item.create.pulp": "dןnԀ", + "item.create.rare_package": "ǝbɐʞɔɐԀ ǝɹɐᴚ", "item.create.raw_zinc": "ɔuıZ ʍɐᴚ", "item.create.red_sand_paper": "ɹǝdɐԀ puɐS pǝᴚ", "item.create.refined_radiance": "ǝɔuɐıpɐᴚ pǝuıɟǝᴚ", @@ -2870,9 +3335,11 @@ "item.create.schematic_and_quill.tooltip.condition2": "buıʌɐS puɐ buıʇsnظpⱯ", "item.create.schematic_and_quill.tooltip.summary": "˙‾ǝןıɟ ʇqu˙‾ ɐ oʇ pןɹoʍ ɹnoʎ uı ‾ǝɹnʇɔnɹʇS ɐ buıʌɐs‾ ɹoɟ pǝs∩", "item.create.shadow_steel": "ןǝǝʇS ʍopɐɥS", + "item.create.shopping_list": "ʇsıꞀ buıddoɥS", "item.create.sturdy_sheet": "ʇǝǝɥS ʎpɹnʇS", "item.create.super_glue": "ǝnן⅁ ɹǝdnS", "item.create.sweet_roll": "ןןoᴚ ʇǝǝʍS", + "item.create.transmitter": "ɹǝʇʇıɯsuɐɹ⟘", "item.create.tree_fertilizer": "ɹǝzıןıʇɹǝℲ ǝǝɹ⟘", "item.create.tree_fertilizer.tooltip.behaviour1": "‾suoıʇıpuoɔ buıɔɐds‾ sʇı ɟo ‾ssǝןpɹɐbǝɹ‾ ǝǝɹʇ ɐ sǝʇɐǝɹƆ", "item.create.tree_fertilizer.tooltip.condition1": "buıןdɐS ɐ uo pǝsn uǝɥM", diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 1643231078..b0316a9a86 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -21,6 +21,12 @@ "advancement.create.brass_casing.desc": "Apply Brass Ingots to stripped wood, creating a casing for more sophisticated machines", "advancement.create.burner": "Sentient Fireplace", "advancement.create.burner.desc": "Obtain a Blaze Burner", + "advancement.create.cardboard": "Part and Parcel", + "advancement.create.cardboard.desc": "Produce or obtain your first Cardboard", + "advancement.create.cardboard_armor": "Full Stealth", + "advancement.create.cardboard_armor.desc": "Sneak around in full Cardboard Armor", + "advancement.create.cardboard_armor_trim": "Arts and Crafts", + "advancement.create.cardboard_armor_trim.desc": "Decorate your cardboard equipment with armor trims\n§7(Hidden Advancement)", "advancement.create.cart_pickup": "Strong Arms", "advancement.create.cart_pickup.desc": "Pick up a Minecart Contraption with at least 200 attached blocks", "advancement.create.chained_drain": "On a Roll", @@ -29,7 +35,7 @@ "advancement.create.chocolate_bucket.desc": "Obtain a bucket of molten chocolate", "advancement.create.chute": "Vertical Logistics", "advancement.create.chute.desc": "Transport some items by Chute", - "advancement.create.clockwork_bearing": "Contraption O'Clock", + "advancement.create.clockwork_bearing": "Contraption o'Clock", "advancement.create.clockwork_bearing.desc": "Assemble a structure mounted on a Clockwork Bearing", "advancement.create.compacting": "Compactification", "advancement.create.compacting.desc": "Use a Mechanical Press and a Basin to create fewer items from more", @@ -47,9 +53,9 @@ "advancement.create.cross_streams.desc": "Watch two fluids meet in your pipe network\n§7(Hidden Advancement)", "advancement.create.crusher_maxed_0000": "Crushing It", "advancement.create.crusher_maxed_0000.desc": "Operate a pair of Crushing Wheels at maximum speed", - "advancement.create.crushing_wheel": "A Pair of Giants", + "advancement.create.crushing_wheel": "Wheels of Destruction", "advancement.create.crushing_wheel.desc": "Place and power a set of Crushing Wheels", - "advancement.create.cuckoo_clock": "Is It Time?", + "advancement.create.cuckoo_clock": "Is it Time?", "advancement.create.cuckoo_clock.desc": "Witness your Cuckoo Clock announce bedtime", "advancement.create.deployer": "Artificial Intelligence", "advancement.create.deployer.desc": "Place and power a Deployer, the perfect reflection of yourself", @@ -71,12 +77,16 @@ "advancement.create.extendo_grip.desc": "Get hold of an Extendo Grip", "advancement.create.extendo_grip_dual": "To Full Extent", "advancement.create.extendo_grip_dual.desc": "Dual-wield Extendo Grips for superhuman reach\n§7(Hidden Advancement)", + "advancement.create.factory_gauge": "High Logistics", + "advancement.create.factory_gauge.desc": "Trigger an automatic package request using Factory Gauges", "advancement.create.fan_processing": "Processing by Particle", "advancement.create.fan_processing.desc": "Use an Encased Fan to process materials", "advancement.create.fist_bump": "Pound It, Bro!", "advancement.create.fist_bump.desc": "Make two Deployers fist-bump\n§7(Hidden Advancement)", "advancement.create.foods": "Balanced Diet", "advancement.create.foods.desc": "Create Chocolate Glazed Berries, a Honeyed Apple, and a Sweet Roll all from the same Spout", + "advancement.create.frogport": "Hungry hoppers", + "advancement.create.frogport.desc": "Catch packages from your Chain Conveyor using a Frogport", "advancement.create.funnel": "Airport Aesthetic", "advancement.create.funnel.desc": "Extract or insert items into a container using a Funnel", "advancement.create.glass_pipe": "Flow Discovery", @@ -113,9 +123,13 @@ "advancement.create.millstone.desc": "Use a Millstone to pulverise materials", "advancement.create.musical_arm": "DJ Mechanico", "advancement.create.musical_arm.desc": "Watch a Mechanical Arm operate your Jukebox\n§7(Hidden Advancement)", + "advancement.create.package_chute_throw": "Nothing but net", + "advancement.create.package_chute_throw.desc": "Land your cardboard package throw in an item chute\n§7(Hidden Advancement)", + "advancement.create.packager": "Post Production", + "advancement.create.packager.desc": "Package items from an inventory using the Packager", "advancement.create.pipe_organ": "The Pipe Organ", "advancement.create.pipe_organ.desc": "Attach 12 uniquely pitched Steam Whistles to a single Fluid Tank\n§7(Hidden Advancement)", - "advancement.create.portable_storage_interface": "Drive-By Exchange", + "advancement.create.portable_storage_interface": "Drive-by Exchange", "advancement.create.portable_storage_interface.desc": "Use a Portable Storage Interface to take or insert items into a Contraption", "advancement.create.potato_cannon": "Fwoomp!", "advancement.create.potato_cannon.desc": "Defeat an enemy with your Potato Cannon", @@ -129,7 +143,7 @@ "advancement.create.red_signal.desc": "Run a red Train Signal\n§7(Hidden Advancement)", "advancement.create.root": "Welcome to Create", "advancement.create.root.desc": "Here Be Contraptions", - "advancement.create.rose_quartz": "Pink Diamonds", + "advancement.create.rose_quartz": "Supercharged", "advancement.create.rose_quartz.desc": "Polish some Rose Quartz", "advancement.create.saw_processing": "Workshop's Most Feared", "advancement.create.saw_processing.desc": "Use an upright Mechanical Saw to process materials", @@ -147,6 +161,8 @@ "advancement.create.steam_engine_maxed.desc": "Run a boiler at the maximum level of power", "advancement.create.steam_whistle": "Voice of an Angel", "advancement.create.steam_whistle.desc": "Activate a Steam Whistle", + "advancement.create.stock_ticker": "Order Up!", + "advancement.create.stock_ticker.desc": "Employ a mob at your stock ticker and make your first requests", "advancement.create.stressometer": "Stress for Nerds", "advancement.create.stressometer.desc": "Get an exact readout with the help of Engineer's Goggles and a Stressometer", "advancement.create.stressometer_maxed": "Perfectly Stressed", @@ -155,6 +171,8 @@ "advancement.create.sturdy_sheet.desc": "Assemble a Sturdy Sheet by refining Powdered Obsidian", "advancement.create.super_glue": "Area of Connect", "advancement.create.super_glue.desc": "Super Glue some blocks into a group", + "advancement.create.table_cloth_shop": "Open for business", + "advancement.create.table_cloth_shop.desc": "Put items up for sale using a Table Cloth", "advancement.create.track_0": "A New Gauge", "advancement.create.track_0.desc": "Obtain some Train Tracks", "advancement.create.track_crafting_factory": "Track Factory", @@ -163,7 +181,7 @@ "advancement.create.track_signal.desc": "Place a Train Signal", "advancement.create.train": "All Aboard!", "advancement.create.train.desc": "Assemble your first Train", - "advancement.create.train_casing_00": "The Logistical Age", + "advancement.create.train_casing_00": "The Locomotive Age", "advancement.create.train_casing_00.desc": "Use Sturdy Sheets to create a casing for railway components", "advancement.create.train_crash": "Terrible Service", "advancement.create.train_crash.desc": "Witness a Train crash as a passenger\n§7(Hidden Advancement)", @@ -179,9 +197,9 @@ "advancement.create.water_supply.desc": "Use the pulling end of a Fluid Pipe or Mechanical Pump to collect water", "advancement.create.water_wheel": "Harnessed Hydraulics", "advancement.create.water_wheel.desc": "Place a Water Wheel and use it to generate torque", - "advancement.create.windmill": "A Mild Breeze", + "advancement.create.windmill": "A mild Breeze", "advancement.create.windmill.desc": "Assemble a windmill and use it to generate torque", - "advancement.create.windmill_maxed": "A Strong Breeze", + "advancement.create.windmill_maxed": "A strong Breeze", "advancement.create.windmill_maxed.desc": "Assemble a windmill of maximum strength", "advancement.create.wrench_goggles": "Kitted Out", "advancement.create.wrench_goggles.desc": "Equip Engineer's Goggles and a Wrench", @@ -201,24 +219,32 @@ "block.create.andesite_ladder": "Andesite Ladder", "block.create.andesite_pillar": "Andesite Pillar", "block.create.andesite_scaffolding": "Andesite Scaffolding", + "block.create.andesite_table_cloth": "Andesite Table Cover", "block.create.andesite_tunnel": "Andesite Tunnel", "block.create.asurine": "Asurine", "block.create.asurine_pillar": "Asurine Pillar", + "block.create.bamboo_window": "Bamboo Window", + "block.create.bamboo_window_pane": "Bamboo Window Pane", "block.create.basin": "Basin", "block.create.belt": "Belt", "block.create.birch_window": "Birch Window", "block.create.birch_window_pane": "Birch Window Pane", "block.create.black_nixie_tube": "Black Nixie Tube", + "block.create.black_postbox": "Black Postbox", "block.create.black_sail": "Black Sail", "block.create.black_seat": "Black Seat", + "block.create.black_table_cloth": "Black Table Cloth", "block.create.black_toolbox": "Black Toolbox", "block.create.black_valve_handle": "Black Valve Handle", "block.create.blaze_burner": "Blaze Burner", "block.create.blue_nixie_tube": "Blue Nixie Tube", + "block.create.blue_postbox": "Blue Postbox", "block.create.blue_sail": "Blue Sail", "block.create.blue_seat": "Blue Seat", + "block.create.blue_table_cloth": "Blue Table Cloth", "block.create.blue_toolbox": "Blue Toolbox", "block.create.blue_valve_handle": "Blue Valve Handle", + "block.create.bound_cardboard_block": "Bound Block of Cardboard", "block.create.brass_bars": "Brass Bars", "block.create.brass_belt_funnel": "Brass Belt Funnel", "block.create.brass_block": "Block of Brass", @@ -230,14 +256,21 @@ "block.create.brass_funnel": "Brass Funnel", "block.create.brass_ladder": "Brass Ladder", "block.create.brass_scaffolding": "Brass Scaffolding", + "block.create.brass_table_cloth": "Brass Table Cover", "block.create.brass_tunnel": "Brass Tunnel", "block.create.brown_nixie_tube": "Brown Nixie Tube", + "block.create.brown_postbox": "Brown Postbox", "block.create.brown_sail": "Brown Sail", "block.create.brown_seat": "Brown Seat", + "block.create.brown_table_cloth": "Brown Table Cloth", "block.create.brown_toolbox": "Brown Toolbox", "block.create.brown_valve_handle": "Brown Valve Handle", "block.create.calcite_pillar": "Calcite Pillar", + "block.create.cardboard_block": "Block of Cardboard", "block.create.cart_assembler": "Cart Assembler", + "block.create.chain_conveyor": "Chain Conveyor", + "block.create.cherry_window": "Cherry Window", + "block.create.cherry_window_pane": "Cherry Window Pane", "block.create.chocolate": "Chocolate", "block.create.chute": "Chute", "block.create.clipboard": "Clipboard", @@ -263,6 +296,7 @@ "block.create.copper_shingle_slab": "Copper Shingle Slab", "block.create.copper_shingle_stairs": "Copper Shingle Stairs", "block.create.copper_shingles": "Copper Shingles", + "block.create.copper_table_cloth": "Copper Table Cover", "block.create.copper_tile_slab": "Copper Tile Slab", "block.create.copper_tile_stairs": "Copper Tile Stairs", "block.create.copper_tiles": "Copper Tiles", @@ -408,8 +442,10 @@ "block.create.cut_veridium_stairs": "Cut Veridium Stairs", "block.create.cut_veridium_wall": "Cut Veridium Wall", "block.create.cyan_nixie_tube": "Cyan Nixie Tube", + "block.create.cyan_postbox": "Cyan Postbox", "block.create.cyan_sail": "Cyan Sail", "block.create.cyan_seat": "Cyan Seat", + "block.create.cyan_table_cloth": "Cyan Table Cloth", "block.create.cyan_toolbox": "Cyan Toolbox", "block.create.cyan_valve_handle": "Cyan Valve Handle", "block.create.dark_oak_window": "Dark Oak Window", @@ -418,6 +454,10 @@ "block.create.deepslate_zinc_ore": "Deepslate Zinc Ore", "block.create.deployer": "Deployer", "block.create.depot": "Depot", + "block.create.desk_bell": "Desk Bell", + "block.create.desk_bell.tooltip.behaviour1": "_Plays a sound_ when arriving at the _target floor_.", + "block.create.desk_bell.tooltip.condition1": "When attached to Elevator Contraption", + "block.create.desk_bell.tooltip.summary": "Ring for Service! Emits a _redstone signal_ when activated.", "block.create.diorite_pillar": "Diorite Pillar", "block.create.display_board": "Display Board", "block.create.display_link": "Display Link", @@ -434,6 +474,7 @@ "block.create.exposed_copper_tile_slab": "Exposed Copper Tile Slab", "block.create.exposed_copper_tile_stairs": "Exposed Copper Tile Stairs", "block.create.exposed_copper_tiles": "Exposed Copper Tiles", + "block.create.factory_gauge": "Factory Gauge", "block.create.fake_track": "Track Marker for Maps", "block.create.fluid_pipe": "Fluid Pipe", "block.create.fluid_tank": "Fluid Tank", @@ -453,13 +494,17 @@ "block.create.glass_fluid_pipe": "Glass Fluid Pipe", "block.create.granite_pillar": "Granite Pillar", "block.create.gray_nixie_tube": "Gray Nixie Tube", + "block.create.gray_postbox": "Gray Postbox", "block.create.gray_sail": "Gray Sail", "block.create.gray_seat": "Gray Seat", + "block.create.gray_table_cloth": "Gray Table Cloth", "block.create.gray_toolbox": "Gray Toolbox", "block.create.gray_valve_handle": "Gray Valve Handle", "block.create.green_nixie_tube": "Green Nixie Tube", + "block.create.green_postbox": "Green Postbox", "block.create.green_sail": "Green Sail", "block.create.green_seat": "Green Seat", + "block.create.green_table_cloth": "Green Table Cloth", "block.create.green_toolbox": "Green Toolbox", "block.create.green_valve_handle": "Green Valve Handle", "block.create.hand_crank": "Hand Crank", @@ -472,7 +517,13 @@ "block.create.horizontal_framed_glass_pane": "Horizontal Framed Glass Pane", "block.create.hose_pulley": "Hose Pulley", "block.create.industrial_iron_block": "Block of Industrial Iron", + "block.create.industrial_iron_window": "Industrial Iron Window", + "block.create.industrial_iron_window_pane": "Industrial Iron Window Pane", "block.create.item_drain": "Item Drain", + "block.create.item_hatch": "Item Hatch", + "block.create.item_hatch.tooltip.behaviour1": "_Deposits_ your _held item_ into the _container_ it is placed on. _Sneak-click_ to _deposit_ _everything_ except Hotbar items.", + "block.create.item_hatch.tooltip.condition1": "When R-Clicked", + "block.create.item_hatch.tooltip.summary": "_Quickly solves_ your _inventory_ clutter and makes it someone else's problem.", "block.create.item_vault": "Item Vault", "block.create.jungle_window": "Jungle Window", "block.create.jungle_window_pane": "Jungle Window Pane", @@ -495,18 +546,24 @@ "block.create.layered_veridium": "Layered Veridium", "block.create.lectern_controller": "Lectern Controller", "block.create.light_blue_nixie_tube": "Light Blue Nixie Tube", + "block.create.light_blue_postbox": "Light Blue Postbox", "block.create.light_blue_sail": "Light Blue Sail", "block.create.light_blue_seat": "Light Blue Seat", + "block.create.light_blue_table_cloth": "Light Blue Table Cloth", "block.create.light_blue_toolbox": "Light Blue Toolbox", "block.create.light_blue_valve_handle": "Light Blue Valve Handle", "block.create.light_gray_nixie_tube": "Light Gray Nixie Tube", + "block.create.light_gray_postbox": "Light Gray Postbox", "block.create.light_gray_sail": "Light Gray Sail", "block.create.light_gray_seat": "Light Gray Seat", + "block.create.light_gray_table_cloth": "Light Gray Table Cloth", "block.create.light_gray_toolbox": "Light Gray Toolbox", "block.create.light_gray_valve_handle": "Light Gray Valve Handle", "block.create.lime_nixie_tube": "Lime Nixie Tube", + "block.create.lime_postbox": "Lime Postbox", "block.create.lime_sail": "Lime Sail", "block.create.lime_seat": "Lime Seat", + "block.create.lime_table_cloth": "Lime Table Cloth", "block.create.lime_toolbox": "Lime Toolbox", "block.create.lime_valve_handle": "Lime Valve Handle", "block.create.limestone": "Limestone", @@ -514,8 +571,10 @@ "block.create.linear_chassis": "Linear Chassis", "block.create.lit_blaze_burner": "Lit Blaze Burner", "block.create.magenta_nixie_tube": "Magenta Nixie Tube", + "block.create.magenta_postbox": "Magenta Postbox", "block.create.magenta_sail": "Magenta Sail", "block.create.magenta_seat": "Magenta Seat", + "block.create.magenta_table_cloth": "Magenta Table Cloth", "block.create.magenta_toolbox": "Magenta Toolbox", "block.create.magenta_valve_handle": "Magenta Valve Handle", "block.create.mangrove_window": "Mangrove Window", @@ -548,8 +607,10 @@ "block.create.oak_window_pane": "Oak Window Pane", "block.create.ochrum": "Ochrum", "block.create.ochrum_pillar": "Ochrum Pillar", + "block.create.orange_postbox": "Orange Postbox", "block.create.orange_sail": "Orange Sail", "block.create.orange_seat": "Orange Seat", + "block.create.orange_table_cloth": "Orange Table Cloth", "block.create.orange_toolbox": "Orange Toolbox", "block.create.orange_valve_handle": "Orange Valve Handle", "block.create.ornate_iron_window": "Ornate Iron Window", @@ -560,11 +621,15 @@ "block.create.oxidized_copper_tile_slab": "Oxidized Copper Tile Slab", "block.create.oxidized_copper_tile_stairs": "Oxidized Copper Tile Stairs", "block.create.oxidized_copper_tiles": "Oxidized Copper Tiles", + "block.create.package_frogport": "Package Frogport", + "block.create.packager": "Packager", "block.create.peculiar_bell": "Peculiar Bell", "block.create.peculiar_bell.tooltip.summary": "A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may have side-effects...", "block.create.pink_nixie_tube": "Pink Nixie Tube", + "block.create.pink_postbox": "Pink Postbox", "block.create.pink_sail": "Pink Sail", "block.create.pink_seat": "Pink Seat", + "block.create.pink_table_cloth": "Pink Table Cloth", "block.create.pink_toolbox": "Pink Toolbox", "block.create.pink_valve_handle": "Pink Valve Handle", "block.create.piston_extension_pole": "Piston Extension Pole", @@ -638,22 +703,29 @@ "block.create.pulley_magnet": "Pulley Magnet", "block.create.pulse_extender": "Pulse Extender", "block.create.pulse_repeater": "Pulse Repeater", + "block.create.pulse_timer": "Pulse Timer", "block.create.purple_nixie_tube": "Purple Nixie Tube", + "block.create.purple_postbox": "Purple Postbox", "block.create.purple_sail": "Purple Sail", "block.create.purple_seat": "Purple Seat", + "block.create.purple_table_cloth": "Purple Table Cloth", "block.create.purple_toolbox": "Purple Toolbox", "block.create.purple_valve_handle": "Purple Valve Handle", "block.create.radial_chassis": "Radial Chassis", "block.create.railway_casing": "Train Casing", "block.create.raw_zinc_block": "Block of Raw Zinc", "block.create.red_nixie_tube": "Red Nixie Tube", + "block.create.red_postbox": "Red Postbox", "block.create.red_sail": "Red Sail", "block.create.red_seat": "Red Seat", + "block.create.red_table_cloth": "Red Table Cloth", "block.create.red_toolbox": "Red Toolbox", "block.create.red_valve_handle": "Red Valve Handle", "block.create.redstone_contact": "Redstone Contact", "block.create.redstone_link": "Redstone Link", + "block.create.redstone_requester": "Redstone Requester", "block.create.refined_radiance_casing": "Radiant Casing", + "block.create.repackager": "Re-Packager", "block.create.rope": "Rope", "block.create.rope_pulley": "Rope Pulley", "block.create.rose_quartz_block": "Block of Rose Quartz", @@ -749,6 +821,8 @@ "block.create.steam_whistle_extension": "Steam Whistle Extension", "block.create.sticker": "Sticker", "block.create.sticky_mechanical_piston": "Sticky Mechanical Piston", + "block.create.stock_link": "Stock Link", + "block.create.stock_ticker": "Stock Ticker", "block.create.stockpile_switch": "Threshold Switch", "block.create.stressometer": "Stressometer", "block.create.tiled_glass": "Tiled Glass", @@ -807,18 +881,25 @@ "block.create.weathered_copper_tile_slab": "Weathered Copper Tile Slab", "block.create.weathered_copper_tile_stairs": "Weathered Copper Tile Stairs", "block.create.weathered_copper_tiles": "Weathered Copper Tiles", + "block.create.weathered_iron_block": "Block of Weathered Iron", + "block.create.weathered_iron_window": "Weathered Iron Window", + "block.create.weathered_iron_window_pane": "Weathered Iron Window Pane", "block.create.weighted_ejector": "Weighted Ejector", "block.create.white_nixie_tube": "White Nixie Tube", + "block.create.white_postbox": "White Postbox", "block.create.white_sail": "Windmill Sail", "block.create.white_seat": "White Seat", + "block.create.white_table_cloth": "White Table Cloth", "block.create.white_toolbox": "White Toolbox", "block.create.white_valve_handle": "White Valve Handle", "block.create.windmill_bearing": "Windmill Bearing", "block.create.wooden_bracket": "Wooden Bracket", "block.create.wooden_bracket.tooltip.summary": "_Decorate_ your _Shafts, Cogwheels_ and _Pipes_ with a cozy and wooden bit of reinforcement.", "block.create.yellow_nixie_tube": "Yellow Nixie Tube", + "block.create.yellow_postbox": "Yellow Postbox", "block.create.yellow_sail": "Yellow Sail", "block.create.yellow_seat": "Yellow Seat", + "block.create.yellow_table_cloth": "Yellow Table Cloth", "block.create.yellow_toolbox": "Yellow Toolbox", "block.create.yellow_valve_handle": "Yellow Valve Handle", "block.create.zinc_block": "Block of Zinc", @@ -853,8 +934,22 @@ "create.boiler.water": "Water", "create.boiler.water_dots": "... ", "create.boiler.water_input_rate": "Water input rate", + "create.chain_conveyor.already_connected": "Conveyors are already connected", + "create.chain_conveyor.blocks_invalid": "Conveyor blocks invalid, Sneak-click to reset", + "create.chain_conveyor.cannot_add_more_connections": "Cannot add more connections to this Conveyor", + "create.chain_conveyor.cannot_connect_vertically": "Cannot connect vertically", + "create.chain_conveyor.not_enough_chains": "Not holding enough chains", + "create.chain_conveyor.select_second": "Select a second conveyor to connect", + "create.chain_conveyor.selection_cleared": "Selection Cleared", + "create.chain_conveyor.too_close": "Too close together", + "create.chain_conveyor.too_far": "Too far apart", + "create.chain_conveyor.too_steep": "Slope too steep", + "create.chain_conveyor.valid_connection": "Can Connect ✔", "create.clipboard.actions": "Clipboard Actions", + "create.clipboard.address_added": "'%1$s' added to Clipboard", "create.clipboard.copied_from": "Copying settings from %1$s", + "create.clipboard.copied_from_clipboard": "Added entries from Clipboard", + "create.clipboard.copy_other_clipboard": "%1$s to Copy entries from this Clipboard", "create.clipboard.pasted_to": "Applied settings to %1$s", "create.clipboard.to_copy": "%1$s to Copy settings", "create.clipboard.to_paste": "%1$s to Paste settings", @@ -954,6 +1049,7 @@ "create.display_source.fill_level.percent": "Percent", "create.display_source.fill_level.progress_bar": "Progress Bar", "create.display_source.fluid_amount": "Amount of matching Fluids", + "create.display_source.gauge_status": "Factory gauge status", "create.display_source.item_throughput": "Item Throughput", "create.display_source.item_throughput.interval": "Interval", "create.display_source.item_throughput.interval.hour": "per Hour", @@ -976,6 +1072,7 @@ "create.display_source.nixie_tube": "Copy Nixie Tubes", "create.display_source.observed_train_name": "Detected Train Name", "create.display_source.player_deaths": "Player Deaths", + "create.display_source.read_package_address": "Read Package Address", "create.display_source.redstone_power": "Redstone Power", "create.display_source.redstone_power.display": "Display Format", "create.display_source.redstone_power.number": "Number", @@ -1008,6 +1105,29 @@ "create.elevator_contact.floor_description": "Floor Description", "create.elevator_contact.floor_identifier": "Floor Identifier", "create.elevator_contact.title": "Elevator Contact", + "create.factory_panel.already_connected": "Gauges are already connected", + "create.factory_panel.cannot_add_more_inputs": "Cannot add more inputs to this gauge", + "create.factory_panel.click_second_panel": "Click a second gauge to connect...", + "create.factory_panel.click_to_configure": "Click to configure", + "create.factory_panel.click_to_relocate": "Click a spot to relocate this panel to...", + "create.factory_panel.connection_aborted": "Input connection aborted", + "create.factory_panel.cycled_arrow_path": "Cycled arrow pathing mode %1$s", + "create.factory_panel.hold_to_set_amount": "Click and hold for target amount", + "create.factory_panel.in_progress": "(In Progress)", + "create.factory_panel.input_in_restock_mode": "Input gauge cannot be in restock mode", + "create.factory_panel.link_connected": "Gauge connected to %1$s", + "create.factory_panel.new_factory_task": "New factory task", + "create.factory_panel.no_item": "Input gauge must have an item first", + "create.factory_panel.panels_connected": "Now using %1$s to create %2$s", + "create.factory_panel.redstone_paused": "(Redstone Paused)", + "create.factory_panel.relocated": "Gauge moved to new position", + "create.factory_panel.relocation_aborted": "Gauge relocation aborted", + "create.factory_panel.same_orientation": "Blocks must have the same orientation", + "create.factory_panel.same_surface": "Blocks must be on the same surface", + "create.factory_panel.some_links_unloaded": "Some links are not loaded", + "create.factory_panel.target_amount": "Target Amount in Storage", + "create.factory_panel.too_far_apart": "Blocks are too far away from each other", + "create.factory_panel.tune_before_placing": "Tune to a stock link before placing", "create.flap_display.cycles.alphabet": " ;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;X;Y;Z", "create.flap_display.cycles.arrival_time": " ; min;now;15s;30s;45s", "create.flap_display.cycles.fluid_units": "mB;B ", @@ -1043,6 +1163,11 @@ "create.generic.unit.stress": "su", "create.generic.unit.ticks": "Ticks", "create.generic.width": "Width", + "create.gui.address_box.clipboard_tip": "Keeping Track", + "create.gui.address_box.clipboard_tip_1": "Entries starting with '#' on", + "create.gui.address_box.clipboard_tip_2": "held or nearby clipboards will", + "create.gui.address_box.clipboard_tip_3": "help auto-complete this input.", + "create.gui.address_box.clipboard_tip_4": "(e.g. #storage, #factory)", "create.gui.adjustable_crate.storageSpace": "Storage Space", "create.gui.adjustable_crate.title": "Adjustable Crate", "create.gui.assembly.exception": "This Contraption was unable to assemble:", @@ -1079,6 +1204,53 @@ "create.gui.config.overlay8": "to reset to the default position", "create.gui.contraptions.network_overstressed": "It appears that this contraption is _overstressed_. Add more sources or _slow_ _down_ the components with a high _stress_ _impact_.", "create.gui.contraptions.not_fast_enough": "It appears that this %1$s is _not_ rotating with _enough_ _speed_.", + "create.gui.factory_panel.activate_crafting": "Use Mechanical Crafting", + "create.gui.factory_panel.address_missing": "Inactive: missing a target address", + "create.gui.factory_panel.connect_input": "Add new connection", + "create.gui.factory_panel.crafting_input": "Packaged Ingredients", + "create.gui.factory_panel.crafting_input_tip": "Unpackage into connected", + "create.gui.factory_panel.crafting_input_tip_1": "mechanical crafters (3x3)", + "create.gui.factory_panel.empty_panel": "Empty panel", + "create.gui.factory_panel.expected_output": "Expecting %1$s", + "create.gui.factory_panel.expected_output_tip": "The amount of output returning", + "create.gui.factory_panel.expected_output_tip_1": "after each successful request", + "create.gui.factory_panel.expected_output_tip_2": "Scroll to change", + "create.gui.factory_panel.has_link_connections": "Gauge has connected links", + "create.gui.factory_panel.inactive": " Inactive ", + "create.gui.factory_panel.left_click_disconnect": "Left-Click to disconnect", + "create.gui.factory_panel.left_click_reset": "Left-Click to reset", + "create.gui.factory_panel.no_open_promises": "No open promises", + "create.gui.factory_panel.no_target_amount_set": "Inactive: no target amount set", + "create.gui.factory_panel.place_item_to_monitor": "Place Item to Monitor", + "create.gui.factory_panel.promise_prevents_oversending": "This prevents over-sending.", + "create.gui.factory_panel.promised_items": "Promised items", + "create.gui.factory_panel.promises_do_not_expire": "Promises do not expire", + "create.gui.factory_panel.promises_expire_title": "Promises expire after", + "create.gui.factory_panel.recipe_address": "Send inputs to...", + "create.gui.factory_panel.recipe_address_given": "Sending inputs to", + "create.gui.factory_panel.recipe_address_tip": "Enter the address where", + "create.gui.factory_panel.recipe_address_tip_1": "this recipe is crafted.", + "create.gui.factory_panel.recipe_promises_tip": "When inputs are sent, a promise", + "create.gui.factory_panel.recipe_promises_tip_1": "is held until outputs arrive.", + "create.gui.factory_panel.relocate": "Move this gauge", + "create.gui.factory_panel.reset": "Reset all settings", + "create.gui.factory_panel.restocker_address": "Send items to...", + "create.gui.factory_panel.restocker_address_given": "Sending to", + "create.gui.factory_panel.restocker_address_tip": "Enter the address that will", + "create.gui.factory_panel.restocker_address_tip_1": "cause packages to arrive here.", + "create.gui.factory_panel.restocker_promises_tip": "When items are sent, a promise", + "create.gui.factory_panel.restocker_promises_tip_1": "is held until they arrive.", + "create.gui.factory_panel.save_and_close": "Save and close", + "create.gui.factory_panel.scroll_to_change_amount": "Scroll to change amount", + "create.gui.factory_panel.send_item": "Send %1$s", + "create.gui.factory_panel.sending_item": "Sending %1$s", + "create.gui.factory_panel.sending_item_tip": "whenever local stock level", + "create.gui.factory_panel.sending_item_tip_1": "is below the target amount", + "create.gui.factory_panel.title_as_recipe": "Recipe Settings", + "create.gui.factory_panel.title_as_restocker": "Restocker Settings", + "create.gui.factory_panel.unconfigured_input": "Recipe ingredients", + "create.gui.factory_panel.unconfigured_input_tip": "Ingredients can be added by", + "create.gui.factory_panel.unconfigured_input_tip_1": "connecting other factory gauges", "create.gui.filter.allow_list": "Allow-List", "create.gui.filter.allow_list.description": "Items pass if they match any of the above. An empty Allow-List rejects everything.", "create.gui.filter.deny_list": "Deny-List", @@ -1095,6 +1267,18 @@ "create.gui.goggles.generator_stats": "Generator Stats:", "create.gui.goggles.kinetic_stats": "Kinetic Stats:", "create.gui.goggles.pole_length": "Pole Length:", + "create.gui.package_port.catch_packages": "Catch packages addressed to...", + "create.gui.package_port.catch_packages_empty": "Leave empty to match non-addressed", + "create.gui.package_port.catch_packages_wildcard": "Use * as a text wildcard", + "create.gui.package_port.not_targeting_anything": "No target selected", + "create.gui.package_port.send_and_receive": "Send and receive packages", + "create.gui.package_port.send_only": "Only send packages", + "create.gui.redstone_requester.allow_partial": "Allow partial orders", + "create.gui.redstone_requester.dont_allow_partial": "Must send all items", + "create.gui.redstone_requester.requester_address": "Send order to...", + "create.gui.redstone_requester.requester_address_given": "Sending order to", + "create.gui.redstone_requester.requester_address_tip": "Enter the address this", + "create.gui.redstone_requester.requester_address_tip_1": "order should be send to.", "create.gui.schedule.add_condition": "Add Condition", "create.gui.schedule.add_entry": "Add Action", "create.gui.schedule.alternative_condition": "Alternative Condition", @@ -1160,6 +1344,40 @@ "create.gui.sequenced_gearshift.speed.forward_fast": "Double speed, Forwards", "create.gui.sequenced_gearshift.title": "Sequenced Gearshift", "create.gui.speedometer.title": "Rotation Speed", + "create.gui.stock_keeper.already_ordering_recipe": "Already ordering this recipe", + "create.gui.stock_keeper.checking_stocks": "Checking stocks...", + "create.gui.stock_keeper.configure": "Configure", + "create.gui.stock_keeper.confirm_order": "Confirm Order", + "create.gui.stock_keeper.craft": "Craft %1$s", + "create.gui.stock_keeper.inventories_empty": "Linked Inventories are Empty", + "create.gui.stock_keeper.network_lock_tip": "Locking prevents other Players", + "create.gui.stock_keeper.network_lock_tip_1": "from ordering items directly", + "create.gui.stock_keeper.network_lock_tip_2": "Click to toggle", + "create.gui.stock_keeper.network_locked": "Network is locked", + "create.gui.stock_keeper.network_open": "Network is open", + "create.gui.stock_keeper.no_packagers_linked": "No Packagers Linked", + "create.gui.stock_keeper.no_search_results": "No matching items found", + "create.gui.stock_keeper.not_in_stock": "Required items are not in Stock", + "create.gui.stock_keeper.package_adress": "Package Address", + "create.gui.stock_keeper.program_requester": "Program Requester", + "create.gui.stock_keeper.request_sent": "Request Sent!", + "create.gui.stock_keeper.schematic_list.no_results": "No items from your checklist are in stock", + "create.gui.stock_keeper.schematic_list.requesting": "Click 'Send' to request all available items from your checklist", + "create.gui.stock_keeper.search_items": "Search Items", + "create.gui.stock_keeper.send": "Send", + "create.gui.stock_keeper.slots_full": "Order slots already full", + "create.gui.stock_keeper.title": "Stock Keeper", + "create.gui.stock_keeper.unsorted_category": "Unsorted", + "create.gui.stock_ticker.category_editor": "Category Editor", + "create.gui.stock_ticker.category_filter": "Category Filter", + "create.gui.stock_ticker.category_filter_tip": "Place a List or Attribute Filter", + "create.gui.stock_ticker.category_filter_tip_1": "to specify which items are included", + "create.gui.stock_ticker.category_name": "Category Name", + "create.gui.stock_ticker.delete_category": "Delete Category", + "create.gui.stock_ticker.empty_category_name_placeholder": "(Empty)", + "create.gui.stock_ticker.new_category": "New Category", + "create.gui.stock_ticker.shift_moves_bottom": "Shift moves to bottom", + "create.gui.stock_ticker.shift_moves_top": "Shift moves to top", "create.gui.stressometer.capacity": "Remaining Capacity", "create.gui.stressometer.no_rotation": "No Rotation", "create.gui.stressometer.overstressed": "Overstressed", @@ -1193,14 +1411,24 @@ "create.gui.terrainzapper.tool.overlay": "Overlay", "create.gui.terrainzapper.tool.place": "Place", "create.gui.terrainzapper.tool.replace": "Replace", + "create.gui.threshold_switch.currently": "Currently %1$s", + "create.gui.threshold_switch.incompatible": "Incompatible block", "create.gui.threshold_switch.invert_signal": "Invert Signal", - "create.gui.threshold_switch.move_to_lower_at": "Move to lower lane at %1$s%%", - "create.gui.threshold_switch.move_to_upper_at": "Move to upper lane at %1$s%%", + "create.gui.threshold_switch.lower_threshold": "...at or below:", + "create.gui.threshold_switch.not_attached": "Not attached to a block", + "create.gui.threshold_switch.power_off_when": "Power off when...", + "create.gui.threshold_switch.power_on_when": "Power on when...", + "create.gui.threshold_switch.pulley_y_level": "%1$sy", + "create.gui.threshold_switch.range": "(%1$s to %2$s)", + "create.gui.threshold_switch.range_max": "(max. %1$s)", "create.gui.threshold_switch.title": "Threshold Switch", + "create.gui.threshold_switch.upper_threshold": "...at or above:", "create.gui.toolmenu.cycle": "[SCROLL] to Cycle", "create.gui.toolmenu.focusKey": "Hold [%1$s] to Focus", "create.gui.value_settings.hold_to_edit": "Click and hold to edit", "create.gui.value_settings.release_to_confirm": "Release %1$s to Confirm", + "create.hint.blocked_frogport": "A _Package_ caught by this _Frogport_ could not be transferred to the _inventory_ _below._ Could it be full?", + "create.hint.blocked_frogport.title": "Contains Packages", "create.hint.derailed_train": "It appears this _Train_ is no longer sitting on a connected track piece. _Right-Click_ using a _wrench_ in order to relocate it to a nearby track.", "create.hint.derailed_train.title": "Derailed Train", "create.hint.empty_bearing": "_Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", @@ -1284,9 +1512,9 @@ "create.item_attributes.smokable.inverted": "cannot be Smoked", "create.item_attributes.washable": "can be Washed", "create.item_attributes.washable.inverted": "cannot be Washed", - "create.keyinfo.ponder": "Ponder", - "create.keyinfo.scrolldown": "Simulate Mousewheel Down (inworld)", - "create.keyinfo.scrollup": "Simulate Mousewheel Up (inworld)", + "create.item_hatch.deposit_inventory": "Inventory items deposited", + "create.item_hatch.deposit_item": "Held item deposited", + "create.keyinfo.rotate_menu": "Open Block Rotation Menu", "create.keyinfo.toolbelt": "Access Nearby Toolboxes", "create.keyinfo.toolmenu": "Focus Schematic Overlay", "create.kinetics.creative_motor.rotation_speed": "Generated Speed in RPM", @@ -1298,6 +1526,12 @@ "create.linked_controller.frequency_slot_2": "Keybind: %1$s, Freq. #2", "create.linked_controller.key_bound": "Frequency bound to %1$s", "create.linked_controller.press_keybind": "Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.logistically_linked.connected": "Connected to existing network successfully", + "create.logistically_linked.new_network_started": "New link network started", + "create.logistically_linked.protected": "Logistics Network is Protected", + "create.logistically_linked.tooltip": "Frequency configured", + "create.logistically_linked.tooltip_clear": "Place in crafting grid to reset", + "create.logistically_linked.tuned": "Tuned to this network", "create.logistics.crafter.click_to_merge": "Click to merge Inventories", "create.logistics.crafter.click_to_separate": "Click to separate Inventories", "create.logistics.crafter.connected": "Connected Crafters", @@ -1344,6 +1578,13 @@ "create.orientation.diagonal": "Diagonal", "create.orientation.horizontal": "Horizontal", "create.orientation.orthogonal": "Orthogonal", + "create.package_port.cannot_reach_down": "Cannot connect downward", + "create.package_port.too_far": "Too far away", + "create.package_port.valid": "Can Connect ✔", + "create.packager.no_portable_storage": "Packagers cannot interface with Portable Storage directly", + "create.packager_link.clear": "Cleared selection", + "create.packager_link.set": "Target selected", + "create.packager_link.success": "Successfully bound to target", "create.ponder.analog_lever.header": "Controlling signals using the Analog Lever", "create.ponder.analog_lever.text_1": "Analog Levers make for a compact and precise source of redstone power", "create.ponder.analog_lever.text_2": "Right-click to increase its analog power output", @@ -1353,7 +1594,6 @@ "create.ponder.andesite_tunnel.text_2": "Whenever an Andesite Tunnel has connections to the sides...", "create.ponder.andesite_tunnel.text_3": "...they will split exactly one item off of any passing stacks", "create.ponder.andesite_tunnel.text_4": "The remainder will continue on its path", - "create.ponder.associated": "Associated Entries", "create.ponder.auto_schedule.header": "Stations & Scheduling", "create.ponder.auto_schedule.text_1": "Schedules can be used to provide drivers with a destination", "create.ponder.auto_schedule.text_2": "Comparators will receive a signal whenever a Train is present", @@ -1443,7 +1683,12 @@ "create.ponder.cart_assembler_rails.text_2": "When on Powered or Controller Rail, the carts will be held in place until it's Powered", "create.ponder.cart_assembler_rails.text_3": "Other types of Minecarts can be used as the anchor", "create.ponder.cart_assembler_rails.text_4": "Furnace Carts will keep themselves powered, pulling fuel from any attached inventories", - "create.ponder.categories": "Available Categories in Create", + "create.ponder.chain_conveyor.header": "Relaying rotational force using Chain Conveyors", + "create.ponder.chain_conveyor.text_1": "Right-click two conveyors with chains to connect them", + "create.ponder.chain_conveyor.text_2": "Chain conveyors relay rotational power between each other..", + "create.ponder.chain_conveyor.text_3": "..and connect to shafts above or below them", + "create.ponder.chain_conveyor.text_4": "Right-click holding a wrench to start travelling on the chain", + "create.ponder.chain_conveyor.text_5": "At a junction, face towards a chain to follow it", "create.ponder.chain_drive.header": "Relaying rotational force with Chain Drives", "create.ponder.chain_drive.text_1": "Chain Drives relay rotation to each other in a row", "create.ponder.chain_drive.text_2": "All shafts connected like this will rotate in the same direction", @@ -1473,7 +1718,6 @@ "create.ponder.clockwork_bearing.text_6": "In front of the Hour Hand, a second structure can be added", "create.ponder.clockwork_bearing.text_7": "Ensure that the two Structures are not glued to each other", "create.ponder.clockwork_bearing.text_8": "The Second Structure will now rotate as the Minute Hand", - "create.ponder.close": "Close", "create.ponder.clutch.header": "Controlling rotational force using a Clutch", "create.ponder.clutch.text_1": "Clutches will relay rotation in a straight line", "create.ponder.clutch.text_2": "When powered by Redstone, it breaks the connection", @@ -1600,7 +1844,52 @@ "create.ponder.encased_fluid_pipe.text_1": "Copper Casing can be used to decorate Fluid Pipes", "create.ponder.encased_fluid_pipe.text_2": "Aside from being concealed, Encased Pipes are locked into their connectivity state", "create.ponder.encased_fluid_pipe.text_3": "It will no longer react to any neighbouring blocks being added or removed", - "create.ponder.exit": "Exit", + "create.ponder.factory_gauge_crafting.header": "Automatic Crafting with Factory Gauges", + "create.ponder.factory_gauge_crafting.text_1": "Factory gauges provide auto-arrangement for crafting table recipes", + "create.ponder.factory_gauge_crafting.text_2": "Connect the required ingredients as before", + "create.ponder.factory_gauge_crafting.text_3": "When a valid recipe is detected, a new button appears in the UI", + "create.ponder.factory_gauge_crafting.text_4": "With auto-arrangement active, the boxes can be unwrapped into crafters directly", + "create.ponder.factory_gauge_crafting.text_5": "The setup must be 3x3 and the crafters have to be connected via wrench", + "create.ponder.factory_gauge_crafting.text_6": "Hold Right-click on the gauge to set the target amount", + "create.ponder.factory_gauge_crafting.text_7": "This crafter can now be used universally, by more gauges with different recipes", + "create.ponder.factory_gauge_crafting.text_8": "Outputs should be sent back to a linked inventory to close the loop", + "create.ponder.factory_gauge_crafting.text_9": "Using a Re-packager is recommended to prevent fragmentation of input packages", + "create.ponder.factory_gauge_links.header": "Connecting Gauges to other Blocks", + "create.ponder.factory_gauge_links.text_1": "When adding a new connection from the UI...", + "create.ponder.factory_gauge_links.text_2": "...the gauge also accepts Redstone and Display Links", + "create.ponder.factory_gauge_links.text_3": "Redstone links will be powered when the stock level is at or above the target amount", + "create.ponder.factory_gauge_links.text_4": "In receiver mode, links can stop the gauge from sending requests", + "create.ponder.factory_gauge_links.text_5": "Display links can provide a status overview of connected gauges", + "create.ponder.factory_gauge_recipe.header": "Automated Recipes with Factory Gauges", + "create.ponder.factory_gauge_recipe.text_1": "Whenever gauges are not placed on a packager...", + "create.ponder.factory_gauge_recipe.text_10": "Specify the address that ingredients should be sent to", + "create.ponder.factory_gauge_recipe.text_11": "The target amount to maintain can now be set by holding Right-click on the gauge", + "create.ponder.factory_gauge_recipe.text_12": "Whenever the network has fewer items than the amount...", + "create.ponder.factory_gauge_recipe.text_13": "...it will send new ingredients to the specified address", + "create.ponder.factory_gauge_recipe.text_14": "The outputs then need to return to any of the linked inventories", + "create.ponder.factory_gauge_recipe.text_15": "Green connections indicate that the target amount has been reached", + "create.ponder.factory_gauge_recipe.text_16": "The board of gauges can expand to include more recipe steps", + "create.ponder.factory_gauge_recipe.text_17": "Each gauge maintains the stock level of its item independently", + "create.ponder.factory_gauge_recipe.text_2": "They will instead monitor stock levels of all linked inventories", + "create.ponder.factory_gauge_recipe.text_3": "Right-click it with the item that should be monitored", + "create.ponder.factory_gauge_recipe.text_4": "It will now display the total amount present on the network", + "create.ponder.factory_gauge_recipe.text_5": "The gauge can replenish stock levels by sending other items to be processed", + "create.ponder.factory_gauge_recipe.text_6": "First, add the required ingredients as new factory gauges", + "create.ponder.factory_gauge_recipe.text_7": "From the target's UI, new connections can be made", + "create.ponder.factory_gauge_recipe.text_8": "For aesthetics, input panels can be wrenched to change the pathing", + "create.ponder.factory_gauge_recipe.text_9": "In the UI, review the inputs and specify how much of the output gets made per batch", + "create.ponder.factory_gauge_restocker.header": "Restocking with Factory Gauges", + "create.ponder.factory_gauge_restocker.text_1": "Right-click a Stock link before placement to connect to its network", + "create.ponder.factory_gauge_restocker.text_10": "...the logistics network sends more, with the specified address", + "create.ponder.factory_gauge_restocker.text_11": "From there, they can be routed to the packager", + "create.ponder.factory_gauge_restocker.text_2": "When placed on a packager, factory gauges can monitor items inside the inventory", + "create.ponder.factory_gauge_restocker.text_3": "Right-click it with the item that should be monitored", + "create.ponder.factory_gauge_restocker.text_4": "It will now display the amount present in the inventory", + "create.ponder.factory_gauge_restocker.text_5": "The gauge can refill this inventory from the logistics network", + "create.ponder.factory_gauge_restocker.text_6": "Right-click it again to open its configuration UI", + "create.ponder.factory_gauge_restocker.text_7": "Set an address that should be used for the requested items", + "create.ponder.factory_gauge_restocker.text_8": "The target amount to maintain can now be set by holding Right-click on the gauge", + "create.ponder.factory_gauge_restocker.text_9": "Whenever the chest has fewer items than this amount...", "create.ponder.fan_direction.header": "Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "Strength and Direction of Flow depends on the Rotational Input", @@ -1687,7 +1976,6 @@ "create.ponder.hand_crank.text_1": "Hand Cranks can be used by players to apply rotational force manually", "create.ponder.hand_crank.text_2": "Hold Right-Click to rotate it Counter-Clockwise", "create.ponder.hand_crank.text_3": "Sneak and Hold Right-Click to rotate it Clockwise", - "create.ponder.hold_to_ponder": "Hold [%1$s] to Ponder", "create.ponder.hose_pulley.header": "Source Filling and Draining using Hose Pulleys", "create.ponder.hose_pulley.text_1": "Hose Pulleys can be used to fill or drain large bodies of Fluid", "create.ponder.hose_pulley.text_2": "With the Kinetic Input, the height of the pulleys' hose can be controlled", @@ -1706,10 +1994,6 @@ "create.ponder.hose_pulley_level.text_3": "The surface level will end up just below where the hose ends", "create.ponder.hose_pulley_level.text_4": "Filling runs from bottom to top", "create.ponder.hose_pulley_level.text_5": "The filled pool will not grow beyond the layer above the hose end", - "create.ponder.identify": "Identify", - "create.ponder.identify_mode": "Identify mode active.\nUnpause with [%1$s]", - "create.ponder.index_description": "Click one of the icons to learn about its associated Items and Blocks", - "create.ponder.index_title": "Ponder Index", "create.ponder.item_drain.header": "Emptying Fluid Containers using Item Drains", "create.ponder.item_drain.text_1": "Item Drains can extract fluids from items", "create.ponder.item_drain.text_2": "Right-click it to pour fluids from your held item into it", @@ -1878,16 +2162,54 @@ "create.ponder.millstone.text_3": "Throw or Insert items at the top", "create.ponder.millstone.text_4": "After some time, the result can be obtained via Right-click", "create.ponder.millstone.text_5": "The outputs can also be extracted by automation", - "create.ponder.next": "Next Scene", - "create.ponder.next_up": "Up Next:", + "create.ponder.mod_name": "Create", "create.ponder.nixie_tube.header": "Using Nixie Tubes", "create.ponder.nixie_tube.text_1": "When powered by Redstone, Nixie Tubes will display the signal strength", "create.ponder.nixie_tube.text_2": "Using written Clipboards, custom text can be displayed", "create.ponder.nixie_tube.text_3": "Right-Click with Dye to change their display colour", + "create.ponder.package_frogport.header": "Transporting packages between Frogports", + "create.ponder.package_frogport.text_1": "Right-click a Chain Conveyor and place the Frogport nearby", + "create.ponder.package_frogport.text_10": "Packages find their path to a matching frog on the chain network", + "create.ponder.package_frogport.text_11": "Peter", + "create.ponder.package_frogport.text_12": "→ Peter", + "create.ponder.package_frogport.text_13": "Frogports can directly interface with inventories below them", + "create.ponder.package_frogport.text_14": "This also works with packagers. Items can be packed and shipped directly", + "create.ponder.package_frogport.text_15": "Albert", + "create.ponder.package_frogport.text_16": "Peter", + "create.ponder.package_frogport.text_17": "Addresses packages to 'Peter'", + "create.ponder.package_frogport.text_18": "Right-click Frogports with a clipboard to collect their address", + "create.ponder.package_frogport.text_19": "Clipboards with collected names can help auto-complete address inputs in other UIs", + "create.ponder.package_frogport.text_2": "Assign it an address in the inventory UI", + "create.ponder.package_frogport.text_3": "If the address of an inserted package does not match it..", + "create.ponder.package_frogport.text_4": "Albert", + "create.ponder.package_frogport.text_5": "→ Peter", + "create.ponder.package_frogport.text_6": "..the Frogport will place the package on the conveyor", + "create.ponder.package_frogport.text_7": "Packages spin in place if they have no valid destination", + "create.ponder.package_frogport.text_8": "More Frogports can be added anywhere on the chain network", + "create.ponder.package_frogport.text_9": "Peter", + "create.ponder.packager.header": "Creating and unwrapping packages", + "create.ponder.packager.text_1": "Attach packagers to the inventory they should target", + "create.ponder.packager.text_2": "Given redstone power, it will pack items from the inventory into a package", + "create.ponder.packager.text_3": "These can be picked up and transported like any other item", + "create.ponder.packager.text_4": "Packages inserted will be destroyed, unpacking the contents into the inventory", + "create.ponder.packager.text_5": "Full", + "create.ponder.packager.text_6": "Packagers will not accept packages they cannot fully unpack", + "create.ponder.packager_address.header": "Routing packages with an address", + "create.ponder.packager_address.text_1": "Warehouse", + "create.ponder.packager_address.text_10": "For compactness, mechanical saws can unpack straight onto a belt", + "create.ponder.packager_address.text_11": "Aside from filters, Frogports and Postboxes have package routing abilities", + "create.ponder.packager_address.text_12": "Inspect them to find out more about their behaviour", + "create.ponder.packager_address.text_2": "When a sign is placed on a packager..", + "create.ponder.packager_address.text_3": "→ Warehouse", + "create.ponder.packager_address.text_4": "Created packages will carry the written line of text as their address", + "create.ponder.packager_address.text_5": "Package filters route packages based on their address", + "create.ponder.packager_address.text_6": "→ Warehouse", + "create.ponder.packager_address.text_7": "Factory", + "create.ponder.packager_address.text_8": "→ Factory", + "create.ponder.packager_address.text_9": "Factory", "create.ponder.piston_pole.header": "Piston Extension Poles", "create.ponder.piston_pole.text_1": "Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "The Length of pole added at its back determines the Extension Range", - "create.ponder.pondering": "Pondering about...", "create.ponder.portable_fluid_interface.header": "Contraption Fluid Exchange", "create.ponder.portable_fluid_interface.text_1": "Fluid Tanks on moving contraptions cannot be accessed by any pipes", "create.ponder.portable_fluid_interface.text_2": "This component can interact with fluid tanks without the need to stop the contraption", @@ -1908,6 +2230,19 @@ "create.ponder.portable_storage_interface.text_8": "After no items have been exchanged for a while, the contraption will continue on its way", "create.ponder.portable_storage_interface_redstone.header": "Redstone Control", "create.ponder.portable_storage_interface_redstone.text_1": "Redstone power will prevent the stationary interface from engaging", + "create.ponder.postbox.header": "Transporting packages between Postboxes", + "create.ponder.postbox.text_1": "Right-click a Train Station and place the Postbox nearby", + "create.ponder.postbox.text_10": "→ Warehouse", + "create.ponder.postbox.text_11": "Just like trains, Postboxes maintain their behaviour in unloaded chunks", + "create.ponder.postbox.text_12": "Packages can still be delivered from or to their inventory", + "create.ponder.postbox.text_2": "Assign it an address in the inventory UI", + "create.ponder.postbox.text_3": "If the address of an inserted package does not match it..", + "create.ponder.postbox.text_4": "Warehouse", + "create.ponder.postbox.text_5": "→ Outpost", + "create.ponder.postbox.text_6": "..trains stopping at the station will collect it as cargo", + "create.ponder.postbox.text_7": "Conversely, packages matching the address will be dropped off", + "create.ponder.postbox.text_8": "Packages that arrived by train can be extracted from the Postbox", + "create.ponder.postbox.text_9": "Warehouse", "create.ponder.powered_latch.header": "Controlling signals using the Powered Latch", "create.ponder.powered_latch.text_1": "Powered Latches are redstone controllable Levers", "create.ponder.powered_latch.text_2": "Signals at the back switch it on", @@ -1918,7 +2253,6 @@ "create.ponder.powered_toggle_latch.text_2": "Signals at the back will toggle its state", "create.ponder.powered_toggle_latch.text_3": "...on and back off", "create.ponder.powered_toggle_latch.text_4": "Powered toggle latches can also be toggled manually", - "create.ponder.previous": "Previous Scene", "create.ponder.pulse_extender.header": "Controlling signals using Pulse Extenders", "create.ponder.pulse_extender.text_1": "Pulse Extenders can lengthen a signal passing through", "create.ponder.pulse_extender.text_2": "They activate after a short delay...", @@ -1929,6 +2263,12 @@ "create.ponder.pulse_repeater.text_1": "Pulse Repeaters emit a short pulse after a delay", "create.ponder.pulse_repeater.text_2": "Using the value panel, the charge time can be configured", "create.ponder.pulse_repeater.text_3": "Configured delays can range up to an hour", + "create.ponder.pulse_timer.header": "Redstone output of the Pulse Timer", + "create.ponder.pulse_timer.text_1": "Pulse Timers repeatedly emit short pulses", + "create.ponder.pulse_timer.text_2": "Using the value panel, the time interval can be configured", + "create.ponder.pulse_timer.text_3": "Powering the input side will pause and reset them", + "create.ponder.pulse_timer.text_4": "Right-click the circuit base to invert the output", + "create.ponder.pulse_timer.text_5": "This helps trigger mechanisms that activate only without a redstone signal", "create.ponder.radial_chassis.header": "Attaching blocks using Radial Chassis", "create.ponder.radial_chassis.text_1": "Radial Chassis connect to identical Chassis blocks in a row", "create.ponder.radial_chassis.text_2": "When one is moved by a Contraption, the others are dragged with it", @@ -1949,7 +2289,22 @@ "create.ponder.redstone_link.text_4": "Receivers emit the redstone power of transmitters within 256 blocks", "create.ponder.redstone_link.text_5": "Placing items in the two slots can specify a Frequency", "create.ponder.redstone_link.text_6": "Only the links with matching Frequencies will communicate", - "create.ponder.replay": "Replay", + "create.ponder.redstone_requester.header": "Automated orders with Redstone Requesters", + "create.ponder.redstone_requester.text_1": "Right-click a Stock link before placement to connect to its network", + "create.ponder.redstone_requester.text_2": "Just like Stock tickers, Redstone requesters can order items from the logistics network", + "create.ponder.redstone_requester.text_3": "Right-click the requester to open its configuration UI", + "create.ponder.redstone_requester.text_4": "The order set in the UI will be requested on every redstone pulse", + "create.ponder.redstone_requester.text_5": "Alternatively, the requester can be fully configured before placement", + "create.ponder.redstone_requester.text_6": "Right-click a Stock keeper with it and set the desired order there", + "create.ponder.repackager.header": "Merging packages from a request", + "create.ponder.repackager.text_1": "Sometimes, it is crucial for logistical requests to arrive as a single package", + "create.ponder.repackager.text_2": "Order A", + "create.ponder.repackager.text_3": "Order B", + "create.ponder.repackager.text_4": "Otherwise, other packages could arrive inbetween", + "create.ponder.repackager.text_5": "When this is the case, redirect packages to an inventory", + "create.ponder.repackager.text_6": "Attach a re-packager, and power it with redstone", + "create.ponder.repackager.text_7": "Once all fragments arrived, they will be exported as a new package", + "create.ponder.repackager.text_8": "Now, requested items arrive together and in a predictable order", "create.ponder.rope_pulley.header": "Moving Structures using Rope Pulleys", "create.ponder.rope_pulley.text_1": "Rope Pulleys can move blocks vertically when given Rotational Force", "create.ponder.rope_pulley.text_2": "Direction and Speed of movement depend on the Rotational Input", @@ -1993,15 +2348,12 @@ "create.ponder.shaft_casing.header": "Encasing Shafts", "create.ponder.shaft_casing.text_1": "Brass or Andesite Casing can be used to decorate Shafts", "create.ponder.shared.behaviour_modify_value_panel": "This behaviour can be modified using the value panel", - "create.ponder.shared.ctrl_and": "Ctrl +", - "create.ponder.shared.movement_anchors": "With the help of Super Glue, larger structures can be moved", + "create.ponder.shared.movement_anchors": "With the help of Super Glue, larger structures can be moved.", "create.ponder.shared.rpm16": "16 RPM", "create.ponder.shared.rpm16_source": "Source: 16 RPM", "create.ponder.shared.rpm32": "32 RPM", "create.ponder.shared.rpm8": "8 RPM", - "create.ponder.shared.sneak_and": "Sneak +", "create.ponder.shared.storage_on_contraption": "Inventories attached to the Contraption will pick up their drops automatically", - "create.ponder.slow_text": "Comfy Reading", "create.ponder.smart_chute.header": "Filtering Items using Smart Chutes", "create.ponder.smart_chute.text_1": "Smart Chutes are vertical chutes with additional control", "create.ponder.smart_chute.text_2": "Items in the filter slot specify what to extract or transfer", @@ -2061,11 +2413,43 @@ "create.ponder.sticker.text_2": "Upon receiving a signal, it will toggle its state", "create.ponder.sticker.text_3": "If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "Toggled once again, the block is no longer attached", + "create.ponder.stock_link.header": "Logistics Networks and the Stock Link", + "create.ponder.stock_link.text_1": "When placed, Stock Links create a new stock network", + "create.ponder.stock_link.text_2": "Right-click an existing link before placing it to bind them", + "create.ponder.stock_link.text_3": "Stock-linked packagers make their inventory available to the network", + "create.ponder.stock_link.text_4": "Other components on the network can now find and request their items", + "create.ponder.stock_link.text_5": "On request, items from the inventories will be placed into packages", + "create.ponder.stock_link.text_6": "Stock Link signals have unlimited range, but packages require transportation", + "create.ponder.stock_link.text_7": "Full redstone power will stop a link from broadcasting", + "create.ponder.stock_link.text_8": "Analog power lowers the priority of a link, causing others to act first", + "create.ponder.stock_ticker.header": "Ordering items with Stock tickers", + "create.ponder.stock_ticker.text_1": "Right-click a Stock link before placement to connect to its network", + "create.ponder.stock_ticker.text_10": "Stock tickers can also order blocks required for the schematicannon", + "create.ponder.stock_ticker.text_11": "Simply hand the printed clipboard it generated to the Stock keeper", + "create.ponder.stock_ticker.text_2": "Stock-linked packagers make their attached inventory available to the network", + "create.ponder.stock_ticker.text_3": "Stock tickers can order items from these inventories", + "create.ponder.stock_ticker.text_4": "Seated mobs or blaze burners in front of it act as the Stock Keeper", + "create.ponder.stock_ticker.text_5": "Right-click the keeper to start ordering items", + "create.ponder.stock_ticker.text_6": "When an order is submitted, the items will be placed into packages", + "create.ponder.stock_ticker.text_7": "From there, they can be transported to the request point", + "create.ponder.stock_ticker.text_8": "Using attribute or list filters, categories can be added to the item listings", + "create.ponder.stock_ticker.text_9": "Right-click the Stock ticker to open the category editor", + "create.ponder.stock_ticker_address.header": "Addressing a Stock ticker order", + "create.ponder.stock_ticker_address.text_1": "When ordering items, a target address can be set in the request", + "create.ponder.stock_ticker_address.text_10": "Aside from filters, Frogports and Postboxes have package routing abilities", + "create.ponder.stock_ticker_address.text_11": "Inspect them to find out more about their behaviour", + "create.ponder.stock_ticker_address.text_2": "→ Workshop", + "create.ponder.stock_ticker_address.text_3": "This address will be on all packages created for the request", + "create.ponder.stock_ticker_address.text_4": "Using package filters, this can control where the packages will go", + "create.ponder.stock_ticker_address.text_5": "→ Workshop", + "create.ponder.stock_ticker_address.text_6": "Workshop", + "create.ponder.stock_ticker_address.text_7": "→ Factory", + "create.ponder.stock_ticker_address.text_8": "→ Factory", + "create.ponder.stock_ticker_address.text_9": "Workshop", "create.ponder.stressometer.header": "Monitoring Kinetic information using the Stressometer", "create.ponder.stressometer.text_1": "The Stressometer displays the current Stress Capacity of the attached kinetic network", "create.ponder.stressometer.text_2": "When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.stressometer.text_3": "Comparators can emit analog Restone Signals relative to the Stressometer's measurements", - "create.ponder.subject": "Subject of this scene", "create.ponder.super_glue.header": "Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "Super Glue groups blocks together into moving contraptions", "create.ponder.super_glue.text_2": "Clicking two endpoints creates a new 'glued' area", @@ -2073,6 +2457,19 @@ "create.ponder.super_glue.text_4": "Adjacent blocks sharing an area will pull each other along", "create.ponder.super_glue.text_5": "Overlapping glue volumes will move together", "create.ponder.super_glue.text_6": "Blocks hanging on others usually do not require glue", + "create.ponder.table_cloth.header": "Selling items with Table Cloths", + "create.ponder.table_cloth.text_1": "Table cloths can be used to display items", + "create.ponder.table_cloth.text_10": "When checking out at the cashier, the bought items will be placed into a package", + "create.ponder.table_cloth.text_11": "From there, they can be transported to the shop front", + "create.ponder.table_cloth.text_12": "The payments will be stored inside the stock ticker block", + "create.ponder.table_cloth.text_2": "With the help of a logistics system, they can also be used to sell items", + "create.ponder.table_cloth.text_3": "Start with the shop's inventory, a Packager and Stock link", + "create.ponder.table_cloth.text_4": "Bind a Stock ticker to the link and place it in the shop", + "create.ponder.table_cloth.text_5": "Employ a mob or blaze burner as the shop keeper", + "create.ponder.table_cloth.text_6": "Fill the shop inventory with items to be sold", + "create.ponder.table_cloth.text_7": "To create a new trade, interact with the shop keeper while holding a table cloth", + "create.ponder.table_cloth.text_8": "Once placed, set a price in the item slot on the side", + "create.ponder.table_cloth.text_9": "Other players can now interact with the shop", "create.ponder.tag.arm_targets": "Targets for Mechanical Arms", "create.ponder.tag.arm_targets.description": "Components which can be selected as inputs or outputs to the Mechanical Arm", "create.ponder.tag.contraption_actor": "Contraption Actors", @@ -2089,6 +2486,8 @@ "create.ponder.tag.display_targets.description": "Components or Blocks which can process and display the data received from a Display Link", "create.ponder.tag.fluids": "Fluid Manipulators", "create.ponder.tag.fluids.description": "Components which help relaying and making use of Fluids", + "create.ponder.tag.high_logistics": "High Logistics", + "create.ponder.tag.high_logistics.description": "Components which help manage distributed item storage and automated requests around your factory", "create.ponder.tag.kinetic_appliances": "Kinetic Appliances", "create.ponder.tag.kinetic_appliances.description": "Components which make use of Rotational Force", "create.ponder.tag.kinetic_relays": "Kinetic Blocks", @@ -2099,15 +2498,14 @@ "create.ponder.tag.logistics.description": "Components which help moving items around", "create.ponder.tag.movement_anchor": "Movement Anchors", "create.ponder.tag.movement_anchor.description": "Components which allow the creation of moving contraptions, animating an attached structure in a variety of ways", - "create.ponder.tag.recently_updated": "Recent Changes", - "create.ponder.tag.recently_updated.description": "Components that have been added or changed significantly in the latest versions of Create", "create.ponder.tag.redstone": "Logic Components", "create.ponder.tag.redstone.description": "Components which help with redstone engineering", + "create.ponder.tag.threshold_switch_targets": "Targets for Threshold Switches", + "create.ponder.tag.threshold_switch_targets.description": "Threshold Switches can read from these blocks, as well as most item and fluid containers.", "create.ponder.tag.train_related": "Railway Equipment", "create.ponder.tag.train_related.description": "Components used in the construction or management of Train Contraptions", "create.ponder.tag.windmill_sails": "Sails for Windmill Bearings", "create.ponder.tag.windmill_sails.description": "Blocks that count towards the strength of a Windmill Contraption when assembled. Each of these have equal efficiency in doing so.", - "create.ponder.think_back": "Think Back", "create.ponder.threshold_switch.header": "Monitoring with the Threshold Switch", "create.ponder.threshold_switch.text_1": "Threshold Switches monitor the fill level of containers", "create.ponder.threshold_switch.text_2": "When the inventory content exceeds the upper threshold...", @@ -2229,7 +2627,6 @@ "create.ponder.weighted_ejector_tunnel.text_3": "The Stack Size set on the Ejector now determines the amount to be split off", "create.ponder.weighted_ejector_tunnel.text_4": "While a new stack of the configured size exits the side output...", "create.ponder.weighted_ejector_tunnel.text_5": "...the remainder will continue on its path", - "create.ponder.welcome": "Welcome to Ponder", "create.ponder.windmill_source.header": "Generating Rotational Force using Windmill Bearings", "create.ponder.windmill_source.text_1": "Windmill Bearings attach to the block in front of them", "create.ponder.windmill_source.text_2": "Create a movable structure with the help of Super Glue", @@ -2289,6 +2686,8 @@ "create.recipe.sequenced_assembly": "Recipe Sequence", "create.recipe.spout_filling": "Filling by Spout", "create.recipe.wood_cutting": "Wood Cutting", + "create.redstone_requester.keeper_connected": "Connected to Stock keeper successfully", + "create.redstone_requester.keeper_too_far_away": "Requester too far away from Stock keeper", "create.schedule.applied_to_train": "Train is now following this Schedule", "create.schedule.auto_removed_from_train": "Auto-Schedule discarded", "create.schedule.condition.delay": "Scheduled Delay", @@ -2355,6 +2754,10 @@ "create.schedule.condition.unloaded.status": "Waiting for chunk unload", "create.schedule.condition_type": "Continue if/after:", "create.schedule.continued": "Schedule resumed", + "create.schedule.instruction.address_filter_edit_box": "Retrieve Packages with this Address", + "create.schedule.instruction.address_filter_edit_box_1": "Use * as a text wildcard", + "create.schedule.instruction.address_filter_edit_box_2": "Train may navigate anywhere to collect it", + "create.schedule.instruction.address_filter_edit_box_3": "Add another instruction to make it return", "create.schedule.instruction.destination": "Travel to Station", "create.schedule.instruction.destination.summary": "Next Stop:", "create.schedule.instruction.editor": "Instruction Editor", @@ -2365,6 +2768,14 @@ "create.schedule.instruction.name_edit_box": "Schedule Title", "create.schedule.instruction.name_edit_box_1": "Affects text shown on displays", "create.schedule.instruction.name_edit_box_2": "Defaults to next destination's name", + "create.schedule.instruction.package_delivery": "Deliver Package", + "create.schedule.instruction.package_delivery.summary": "Deliver first package in cargo", + "create.schedule.instruction.package_delivery.summary_1": "Drives to the station with", + "create.schedule.instruction.package_delivery.summary_2": "the correct postbox", + "create.schedule.instruction.package_retrieval": "Retrieve Package", + "create.schedule.instruction.package_retrieval.summary": "Fetch a package addressed to:", + "create.schedule.instruction.package_retrieval.summary_1": "Drives to a postbox with", + "create.schedule.instruction.package_retrieval.summary_2": "an undelivered package", "create.schedule.instruction.rename": "Update Schedule Title", "create.schedule.instruction.rename.summary": "New Title:", "create.schedule.instruction.throttle": "Limit Max Speed", @@ -2456,6 +2867,7 @@ "create.schematics.maxAllowedSize": "The maximum allowed schematic file size is:", "create.schematics.synchronizing": "Syncing...", "create.schematics.uploadTooLarge": "Your schematic exceeds limitations specified by the server.", + "create.schematics.wrongFormat": "The schematic you are trying to upload is either corrupt or encoded wrongly! It should be encoded with GZIP compatible format.", "create.station.assemble_train": "Assemble Train", "create.station.assembly_title": "Train Assembly", "create.station.cancel": "Cancel Assembly", @@ -2482,9 +2894,24 @@ "create.station.train_map_color": "Color on Maps", "create.station.train_not_aligned": "Cannot disassemble,", "create.station.train_not_aligned_1": "not all carriages aligned", + "create.stock_keeper.cash_register_full": "Purchase cancelled: Not enough space in Cash Register", + "create.stock_keeper.keeper_missing": "Stock keeper missing", + "create.stock_keeper.limited_stock": "Stock limit reached", + "create.stock_keeper.locked": "Interact using a Shopping list, direct access has been locked", + "create.stock_keeper.no_price_set": "Shop owner must set a price first", + "create.stock_keeper.out_of_stock": "Out of Stock", + "create.stock_keeper.shopping_list_empty_hand": "Empty hand required to start a shopping list", + "create.stock_keeper.stock_level_too_low": "Purchase cancelled: Stock levels lower than expected", + "create.stock_keeper.too_broke": "You cannot afford this purchase", + "create.stock_keeper.use_list_to_add_purchases": "Use this list to add more to your purchase", + "create.stock_ticker.click_to_retrieve": "Click to retrieve", + "create.stock_ticker.contains_payments": "Contains payments:", + "create.stock_ticker.keeper_missing": "Seat a mob or blaze burner next to this block to use it", "create.subtitle.blaze_munch": "Blaze Burner munches", + "create.subtitle.cardboard_bonk": "Resonant bonk", "create.subtitle.cogs": "Cogwheels rumble", "create.subtitle.confirm": "Affirmative ding", + "create.subtitle.confirm_2": "Affirmative ding", "create.subtitle.contraption_assemble": "Contraption moves", "create.subtitle.contraption_disassemble": "Contraption stops", "create.subtitle.controller_click": "Controller clicks", @@ -2498,13 +2925,21 @@ "create.subtitle.deny": "Declining boop", "create.subtitle.depot_plop": "Item lands", "create.subtitle.depot_slide": "Item slides", + "create.subtitle.desk_bell": "Reception bell dings", + "create.subtitle.frogport_catch": "Frogport catches package", + "create.subtitle.frogport_close": "Frogport shuts", + "create.subtitle.frogport_deposit": "Frogport places package", + "create.subtitle.frogport_open": "Frogport opens", "create.subtitle.funnel_flap": "Funnel flaps", - "create.subtitle.fwoomp": "Potato Launcher fwoomps", + "create.subtitle.fwoomp": "Resonant fwoomp", "create.subtitle.haunted_bell_convert": "Haunted Bell awakens", "create.subtitle.haunted_bell_use": "Haunted Bell tolls", + "create.subtitle.item_hatch": "Item Hatch opens", "create.subtitle.mechanical_press_activation": "Mechanical Press clangs", "create.subtitle.mechanical_press_activation_belt": "Mechanical Press bonks", "create.subtitle.mixing": "Mixing noises", + "create.subtitle.package_pop": "Package breaks", + "create.subtitle.packager": "Packager packages", "create.subtitle.peculiar_bell_use": "Peculiar Bell tolls", "create.subtitle.potato_hit": "Vegetable impacts", "create.subtitle.sanding_long": "Sanding noises", @@ -2517,6 +2952,9 @@ "create.subtitle.slime_added": "Slime squishes", "create.subtitle.spout": "Spout spurts", "create.subtitle.steam": "Steam noises", + "create.subtitle.stock_link": "Stock link reacts", + "create.subtitle.stock_ticker_request": "Stock ticker requests", + "create.subtitle.stock_ticker_trade": "Stock ticker goes 'ka-ching!'", "create.subtitle.train": "Bogey wheels rumble", "create.subtitle.train3": "Bogey wheels rumble muffled", "create.subtitle.whistle": "Whistling", @@ -2540,6 +2978,13 @@ "create.symmetry.mirror.doublePlane": "Rectangular", "create.symmetry.mirror.plane": "Mirror Once", "create.symmetry.mirror.triplePlane": "Octagonal", + "create.table_cloth.amount": "Amount", + "create.table_cloth.hand_to_shop_keeper": "Hand this to a shop keeper", + "create.table_cloth.price_per_order": "Price per Order", + "create.table_cloth.shop_configured": "Item shop configured", + "create.table_cloth.shopping_list_discarded": "Shopping list discarded", + "create.table_cloth.sneak_click_discard": "Sneak-Click to discard", + "create.table_cloth.total_cost": "Total cost: ", "create.terrainzapper.leftClickToSet": "Left-Click a Block to set Material", "create.terrainzapper.shiftRightClickToSet": "Shift-Right-Click to Select a Shape", "create.terrainzapper.usingBlock": "Using: %1$s", @@ -2627,6 +3072,7 @@ "create.train.status": " Information about Train: %1$s", "create.train.status.back_on_track": "Train is back on Track", "create.train.status.collision": "Collision with other Train", + "create.train.status.collision.where": "In %1$s near [%2$s]", "create.train.status.coupling_stress": "Forced stop due to Stress on Couplings", "create.train.status.double_portal": "A Carriage cannot enter a portal whilst leaving another", "create.train.status.end_of_track": "A Carriage has reached the end of its Track", @@ -2634,6 +3080,7 @@ "create.train.status.missing_driver": "Driver has gone missing", "create.train.status.navigation_success": "Navigation succeeded", "create.train.status.no_match": "No station on graph matches '%1$s'", + "create.train.status.no_package_target": "A package in cargo has no postbox that matches its address", "create.train.status.no_path": "No suitable path to the next Scheduled destination could be found", "create.train.status.opposite_driver": "Path requires a driver facing the opposite direction", "create.train.status.paused_for_manual": "Schedule paused for manual controls", @@ -2646,7 +3093,7 @@ "create.train_assembly.no_controls": "Attach at least one forward-facing Train Controls block (Are you missing Super Glue?)", "create.train_assembly.not_connected_in_order": "Bogeys are not connected in order", "create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s", - "create.train_assembly.requires_casing": "Use Railway Casing to create bogeys on tracks", + "create.train_assembly.requires_casing": "Use Train Casing to create bogeys on tracks", "create.train_assembly.sideways_controls": "Train Controls cannot face sideways", "create.train_assembly.single_bogey_carriage": "This Bogey type cannot support a carriage on its own", "create.train_assembly.too_many_bogeys": "Too many Bogeys attached: %1$s", @@ -2702,6 +3149,7 @@ "entity.create.contraption": "Contraption", "entity.create.crafting_blueprint": "Crafting Blueprint", "entity.create.gantry_contraption": "Gantry Contraption", + "entity.create.package": "Package", "entity.create.potato_projectile": "Potato Projectile", "entity.create.seat": "Seat", "entity.create.stationary_contraption": "Stationary Contraption", @@ -2726,6 +3174,16 @@ "item.create.brass_sheet": "Brass Sheet", "item.create.builders_tea": "Builder's Tea", "item.create.builders_tea.tooltip.summary": "The perfect drink to get the day started- _Motivating_ and _Saturating._", + "item.create.cardboard": "Cardboard", + "item.create.cardboard_armor.tooltip.behaviour1": "_Sneak_ to activate an inconspicuous _disguise_.", + "item.create.cardboard_armor.tooltip.condition1": "When full set equipped", + "item.create.cardboard_armor.tooltip.summary": "_Wearable_ _equipment_ for increased _style_ and _stealth_.", + "item.create.cardboard_boots": "Cardboard Boots", + "item.create.cardboard_chestplate": "Cardboard Chestplate", + "item.create.cardboard_helmet": "Cardboard Helmet", + "item.create.cardboard_leggings": "Cardboard Leggings", + "item.create.cardboard_sword": "Cardboard Sword", + "item.create.cardboard_sword.tooltip.summary": "Bonk. A _mostly_ _harmless_, yet powerful weapon of choice.", "item.create.chest_minecart_contraption": "Chest Minecart Contraption", "item.create.chocolate_bucket": "Chocolate Bucket", "item.create.chocolate_glazed_berries": "Chocolate Glazed Berries", @@ -2838,6 +3296,11 @@ "item.create.netherite_diving_helmet.tooltip.behaviour1": "Provides immunity to _Fire_ and _Lava_, slowly draining _Air Pressure_ from the Backtank. Also grants _improved vision_ in Lava", "item.create.netherite_diving_helmet.tooltip.condition1": "When Worn (Full set)", "item.create.netherite_diving_helmet.tooltip.summary": "Together with a _Netherite Backtank_, this can protect you from _extreme heat_. To be effective, _Legs and Feet_ have to be covered in _Netherite_, too.", + "item.create.package": "Cardboard Package", + "item.create.package_filter": "Package Filter", + "item.create.package_filter.tooltip.behaviour1": "Opens the _configuration interface_.", + "item.create.package_filter.tooltip.condition1": "When R-Clicked", + "item.create.package_filter.tooltip.summary": "_Matches packaged items_ by their targeted _address_. Can be used in _Filter Slots_ of Create's Components", "item.create.polished_rose_quartz": "Polished Rose Quartz", "item.create.potato_cannon": "Potato Cannon", "item.create.potato_cannon.tooltip.behaviour1": "_Shoots_ a suitable item from your _Inventory_.", @@ -2848,6 +3311,8 @@ "item.create.powdered_obsidian": "Powdered Obsidian", "item.create.precision_mechanism": "Precision Mechanism", "item.create.propeller": "Propeller", + "item.create.pulp": "Pulp", + "item.create.rare_package": "Rare Package", "item.create.raw_zinc": "Raw Zinc", "item.create.red_sand_paper": "Red Sand Paper", "item.create.refined_radiance": "Refined Radiance", @@ -2870,9 +3335,11 @@ "item.create.schematic_and_quill.tooltip.condition2": "Adjusting and Saving", "item.create.schematic_and_quill.tooltip.summary": "Used for _saving a Structure_ in your world to a _.nbt file_.", "item.create.shadow_steel": "Shadow Steel", + "item.create.shopping_list": "Shopping List", "item.create.sturdy_sheet": "Sturdy Sheet", "item.create.super_glue": "Super Glue", "item.create.sweet_roll": "Sweet Roll", + "item.create.transmitter": "Transmitter", "item.create.tree_fertilizer": "Tree Fertilizer", "item.create.tree_fertilizer.tooltip.behaviour1": "Creates a tree _regardless_ of its _spacing conditions_", "item.create.tree_fertilizer.tooltip.condition1": "When used on a Sapling", diff --git a/src/generated/resources/assets/create/models/block/andesite_table_cloth.json b/src/generated/resources/assets/create/models/block/andesite_table_cloth.json new file mode 100644 index 0000000000..04982e5c02 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/andesite" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/bamboo_window.json b/src/generated/resources/assets/create/models/block/bamboo_window.json new file mode 100644 index 0000000000..832c3b256b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/bamboo_window.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "minecraft:block/bamboo_planks", + "side": "create:block/palettes/bamboo_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/bamboo_window_pane_noside.json b/src/generated/resources/assets/create/models/block/bamboo_window_pane_noside.json new file mode 100644 index 0000000000..f721c82c3d --- /dev/null +++ b/src/generated/resources/assets/create/models/block/bamboo_window_pane_noside.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside", + "textures": { + "edge": "minecraft:block/bamboo_planks", + "pane": "create:block/palettes/bamboo_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/bamboo_window_pane_noside_alt.json b/src/generated/resources/assets/create/models/block/bamboo_window_pane_noside_alt.json new file mode 100644 index 0000000000..05e942f80b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/bamboo_window_pane_noside_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside_alt", + "textures": { + "edge": "minecraft:block/bamboo_planks", + "pane": "create:block/palettes/bamboo_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/bamboo_window_pane_post.json b/src/generated/resources/assets/create/models/block/bamboo_window_pane_post.json new file mode 100644 index 0000000000..7bf9489eca --- /dev/null +++ b/src/generated/resources/assets/create/models/block/bamboo_window_pane_post.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/post", + "textures": { + "edge": "minecraft:block/bamboo_planks", + "pane": "create:block/palettes/bamboo_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/bamboo_window_pane_side.json b/src/generated/resources/assets/create/models/block/bamboo_window_pane_side.json new file mode 100644 index 0000000000..3a5e28cfc6 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/bamboo_window_pane_side.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side", + "textures": { + "edge": "minecraft:block/bamboo_planks", + "pane": "create:block/palettes/bamboo_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/bamboo_window_pane_side_alt.json b/src/generated/resources/assets/create/models/block/bamboo_window_pane_side_alt.json new file mode 100644 index 0000000000..1be0a9c1b2 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/bamboo_window_pane_side_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side_alt", + "textures": { + "edge": "minecraft:block/bamboo_planks", + "pane": "create:block/palettes/bamboo_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/black_postbox_closed.json b/src/generated/resources/assets/create/models/block/black_postbox_closed.json new file mode 100644 index 0000000000..8d60726287 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/black_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_black", + "1": "create:block/post_box/post_box_black_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/black_postbox_open.json b/src/generated/resources/assets/create/models/block/black_postbox_open.json new file mode 100644 index 0000000000..5e9b0af55a --- /dev/null +++ b/src/generated/resources/assets/create/models/block/black_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_black", + "1": "create:block/post_box/post_box_black_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/black_table_cloth.json b/src/generated/resources/assets/create/models/block/black_table_cloth.json new file mode 100644 index 0000000000..9221b40e52 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/black_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/black" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/blue_postbox_closed.json b/src/generated/resources/assets/create/models/block/blue_postbox_closed.json new file mode 100644 index 0000000000..42cb79fd27 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/blue_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_blue", + "1": "create:block/post_box/post_box_blue_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/blue_postbox_open.json b/src/generated/resources/assets/create/models/block/blue_postbox_open.json new file mode 100644 index 0000000000..7a4c608e2f --- /dev/null +++ b/src/generated/resources/assets/create/models/block/blue_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_blue", + "1": "create:block/post_box/post_box_blue_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/blue_table_cloth.json b/src/generated/resources/assets/create/models/block/blue_table_cloth.json new file mode 100644 index 0000000000..68064dfdf1 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/blue_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_table_cloth.json b/src/generated/resources/assets/create/models/block/brass_table_cloth.json new file mode 100644 index 0000000000..d209590f23 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/brass" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brown_postbox_closed.json b/src/generated/resources/assets/create/models/block/brown_postbox_closed.json new file mode 100644 index 0000000000..80e719bf55 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brown_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_brown", + "1": "create:block/post_box/post_box_brown_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brown_postbox_open.json b/src/generated/resources/assets/create/models/block/brown_postbox_open.json new file mode 100644 index 0000000000..037670e724 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brown_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_brown", + "1": "create:block/post_box/post_box_brown_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brown_table_cloth.json b/src/generated/resources/assets/create/models/block/brown_table_cloth.json new file mode 100644 index 0000000000..565a2631ff --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brown_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/brown" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cherry_window.json b/src/generated/resources/assets/create/models/block/cherry_window.json new file mode 100644 index 0000000000..3c02e74959 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cherry_window.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "minecraft:block/cherry_planks", + "side": "create:block/palettes/cherry_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cherry_window_pane_noside.json b/src/generated/resources/assets/create/models/block/cherry_window_pane_noside.json new file mode 100644 index 0000000000..1b5bf0a3d0 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cherry_window_pane_noside.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside", + "textures": { + "edge": "minecraft:block/cherry_planks", + "pane": "create:block/palettes/cherry_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cherry_window_pane_noside_alt.json b/src/generated/resources/assets/create/models/block/cherry_window_pane_noside_alt.json new file mode 100644 index 0000000000..3f23c0d4b7 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cherry_window_pane_noside_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside_alt", + "textures": { + "edge": "minecraft:block/cherry_planks", + "pane": "create:block/palettes/cherry_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cherry_window_pane_post.json b/src/generated/resources/assets/create/models/block/cherry_window_pane_post.json new file mode 100644 index 0000000000..c175bc7352 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cherry_window_pane_post.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/post", + "textures": { + "edge": "minecraft:block/cherry_planks", + "pane": "create:block/palettes/cherry_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cherry_window_pane_side.json b/src/generated/resources/assets/create/models/block/cherry_window_pane_side.json new file mode 100644 index 0000000000..03bf47f9ae --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cherry_window_pane_side.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side", + "textures": { + "edge": "minecraft:block/cherry_planks", + "pane": "create:block/palettes/cherry_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cherry_window_pane_side_alt.json b/src/generated/resources/assets/create/models/block/cherry_window_pane_side_alt.json new file mode 100644 index 0000000000..edfbf362fb --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cherry_window_pane_side_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side_alt", + "textures": { + "edge": "minecraft:block/cherry_planks", + "pane": "create:block/palettes/cherry_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_table_cloth.json b/src/generated/resources/assets/create/models/block/copper_table_cloth.json new file mode 100644 index 0000000000..85a080aa46 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/copper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cyan_postbox_closed.json b/src/generated/resources/assets/create/models/block/cyan_postbox_closed.json new file mode 100644 index 0000000000..7fce29c937 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cyan_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_cyan", + "1": "create:block/post_box/post_box_cyan_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cyan_postbox_open.json b/src/generated/resources/assets/create/models/block/cyan_postbox_open.json new file mode 100644 index 0000000000..855f1d76aa --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cyan_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_cyan", + "1": "create:block/post_box/post_box_cyan_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/cyan_table_cloth.json b/src/generated/resources/assets/create/models/block/cyan_table_cloth.json new file mode 100644 index 0000000000..244f28041f --- /dev/null +++ b/src/generated/resources/assets/create/models/block/cyan_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/cyan" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/gray_postbox_closed.json b/src/generated/resources/assets/create/models/block/gray_postbox_closed.json new file mode 100644 index 0000000000..de82bfa465 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/gray_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_gray", + "1": "create:block/post_box/post_box_gray_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/gray_postbox_open.json b/src/generated/resources/assets/create/models/block/gray_postbox_open.json new file mode 100644 index 0000000000..6863bc3219 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/gray_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_gray", + "1": "create:block/post_box/post_box_gray_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/gray_table_cloth.json b/src/generated/resources/assets/create/models/block/gray_table_cloth.json new file mode 100644 index 0000000000..8490fd85ed --- /dev/null +++ b/src/generated/resources/assets/create/models/block/gray_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/green_postbox_closed.json b/src/generated/resources/assets/create/models/block/green_postbox_closed.json new file mode 100644 index 0000000000..094485db4c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/green_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_green", + "1": "create:block/post_box/post_box_green_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/green_postbox_open.json b/src/generated/resources/assets/create/models/block/green_postbox_open.json new file mode 100644 index 0000000000..29eab5611d --- /dev/null +++ b/src/generated/resources/assets/create/models/block/green_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_green", + "1": "create:block/post_box/post_box_green_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/green_table_cloth.json b/src/generated/resources/assets/create/models/block/green_table_cloth.json new file mode 100644 index 0000000000..654ac65e34 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/green_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/green" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/industrial_iron_window.json b/src/generated/resources/assets/create/models/block/industrial_iron_window.json new file mode 100644 index 0000000000..85a7b320da --- /dev/null +++ b/src/generated/resources/assets/create/models/block/industrial_iron_window.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/palettes/industrial_iron_window_end", + "side": "create:block/palettes/industrial_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_noside.json b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_noside.json new file mode 100644 index 0000000000..e3a58e86bc --- /dev/null +++ b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_noside.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside", + "textures": { + "edge": "create:block/palettes/industrial_iron_window_pane_top", + "pane": "create:block/palettes/industrial_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_noside_alt.json b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_noside_alt.json new file mode 100644 index 0000000000..1e913b806f --- /dev/null +++ b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_noside_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside_alt", + "textures": { + "edge": "create:block/palettes/industrial_iron_window_pane_top", + "pane": "create:block/palettes/industrial_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_post.json b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_post.json new file mode 100644 index 0000000000..819fb29f3c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_post.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/post", + "textures": { + "edge": "create:block/palettes/industrial_iron_window_pane_top", + "pane": "create:block/palettes/industrial_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_side.json b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_side.json new file mode 100644 index 0000000000..5eda7010ae --- /dev/null +++ b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_side.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side", + "textures": { + "edge": "create:block/palettes/industrial_iron_window_pane_top", + "pane": "create:block/palettes/industrial_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_side_alt.json b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_side_alt.json new file mode 100644 index 0000000000..e09fc74d5e --- /dev/null +++ b/src/generated/resources/assets/create/models/block/industrial_iron_window_pane_side_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side_alt", + "textures": { + "edge": "create:block/palettes/industrial_iron_window_pane_top", + "pane": "create:block/palettes/industrial_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_blue_postbox_closed.json b/src/generated/resources/assets/create/models/block/light_blue_postbox_closed.json new file mode 100644 index 0000000000..8ac6c675a7 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_blue_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_light_blue", + "1": "create:block/post_box/post_box_light_blue_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_blue_postbox_open.json b/src/generated/resources/assets/create/models/block/light_blue_postbox_open.json new file mode 100644 index 0000000000..6bec66e514 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_blue_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_light_blue", + "1": "create:block/post_box/post_box_light_blue_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_blue_table_cloth.json b/src/generated/resources/assets/create/models/block/light_blue_table_cloth.json new file mode 100644 index 0000000000..56847ef6cc --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_blue_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/light_blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_gray_postbox_closed.json b/src/generated/resources/assets/create/models/block/light_gray_postbox_closed.json new file mode 100644 index 0000000000..b697cfa73b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_gray_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_light_gray", + "1": "create:block/post_box/post_box_light_gray_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_gray_postbox_open.json b/src/generated/resources/assets/create/models/block/light_gray_postbox_open.json new file mode 100644 index 0000000000..6208d0cddf --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_gray_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_light_gray", + "1": "create:block/post_box/post_box_light_gray_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/light_gray_table_cloth.json b/src/generated/resources/assets/create/models/block/light_gray_table_cloth.json new file mode 100644 index 0000000000..c2d9dbfbfd --- /dev/null +++ b/src/generated/resources/assets/create/models/block/light_gray_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/light_gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/lime_postbox_closed.json b/src/generated/resources/assets/create/models/block/lime_postbox_closed.json new file mode 100644 index 0000000000..f40476f584 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/lime_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_lime", + "1": "create:block/post_box/post_box_lime_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/lime_postbox_open.json b/src/generated/resources/assets/create/models/block/lime_postbox_open.json new file mode 100644 index 0000000000..2b27ee0755 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/lime_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_lime", + "1": "create:block/post_box/post_box_lime_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/lime_table_cloth.json b/src/generated/resources/assets/create/models/block/lime_table_cloth.json new file mode 100644 index 0000000000..3b5e46589b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/lime_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/lime" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/magenta_postbox_closed.json b/src/generated/resources/assets/create/models/block/magenta_postbox_closed.json new file mode 100644 index 0000000000..3c52aaf863 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/magenta_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_magenta", + "1": "create:block/post_box/post_box_magenta_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/magenta_postbox_open.json b/src/generated/resources/assets/create/models/block/magenta_postbox_open.json new file mode 100644 index 0000000000..f2067ef047 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/magenta_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_magenta", + "1": "create:block/post_box/post_box_magenta_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/magenta_table_cloth.json b/src/generated/resources/assets/create/models/block/magenta_table_cloth.json new file mode 100644 index 0000000000..400f011ec4 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/magenta_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/magenta" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/orange_postbox_closed.json b/src/generated/resources/assets/create/models/block/orange_postbox_closed.json new file mode 100644 index 0000000000..4af3a5f369 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/orange_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_orange", + "1": "create:block/post_box/post_box_orange_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/orange_postbox_open.json b/src/generated/resources/assets/create/models/block/orange_postbox_open.json new file mode 100644 index 0000000000..26973cd8a3 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/orange_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_orange", + "1": "create:block/post_box/post_box_orange_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/orange_table_cloth.json b/src/generated/resources/assets/create/models/block/orange_table_cloth.json new file mode 100644 index 0000000000..6a0ed67b57 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/orange_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/orange" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pink_postbox_closed.json b/src/generated/resources/assets/create/models/block/pink_postbox_closed.json new file mode 100644 index 0000000000..e3f09b3486 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pink_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_pink", + "1": "create:block/post_box/post_box_pink_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pink_postbox_open.json b/src/generated/resources/assets/create/models/block/pink_postbox_open.json new file mode 100644 index 0000000000..97c3e0bd09 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pink_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_pink", + "1": "create:block/post_box/post_box_pink_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pink_table_cloth.json b/src/generated/resources/assets/create/models/block/pink_table_cloth.json new file mode 100644 index 0000000000..19f9c1958b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pink_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/pink" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pulse_timer_powered.json b/src/generated/resources/assets/create/models/block/pulse_timer_powered.json new file mode 100644 index 0000000000..2a9436c93a --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pulse_timer_powered.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/diodes/pulse_timer", + "textures": { + "top": "create:block/diodes/pulse_timer/powered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pulse_timer_powered_powering.json b/src/generated/resources/assets/create/models/block/pulse_timer_powered_powering.json new file mode 100644 index 0000000000..f70f3548bb --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pulse_timer_powered_powering.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/diodes/pulse_timer", + "textures": { + "top": "create:block/diodes/pulse_timer/powered_powering", + "torch": "minecraft:block/redstone_torch" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/pulse_timer_powering.json b/src/generated/resources/assets/create/models/block/pulse_timer_powering.json new file mode 100644 index 0000000000..8d437e1e64 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/pulse_timer_powering.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/diodes/pulse_timer", + "textures": { + "top": "create:block/diodes/pulse_timer/powering", + "torch": "minecraft:block/redstone_torch" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/purple_postbox_closed.json b/src/generated/resources/assets/create/models/block/purple_postbox_closed.json new file mode 100644 index 0000000000..b874575e1a --- /dev/null +++ b/src/generated/resources/assets/create/models/block/purple_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_purple", + "1": "create:block/post_box/post_box_purple_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/purple_postbox_open.json b/src/generated/resources/assets/create/models/block/purple_postbox_open.json new file mode 100644 index 0000000000..a1606532ad --- /dev/null +++ b/src/generated/resources/assets/create/models/block/purple_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_purple", + "1": "create:block/post_box/post_box_purple_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/purple_table_cloth.json b/src/generated/resources/assets/create/models/block/purple_table_cloth.json new file mode 100644 index 0000000000..be140a0db7 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/purple_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/purple" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/red_postbox_closed.json b/src/generated/resources/assets/create/models/block/red_postbox_closed.json new file mode 100644 index 0000000000..fa815e3145 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/red_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_red", + "1": "create:block/post_box/post_box_red_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/red_postbox_open.json b/src/generated/resources/assets/create/models/block/red_postbox_open.json new file mode 100644 index 0000000000..c13dccaf99 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/red_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_red", + "1": "create:block/post_box/post_box_red_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/red_table_cloth.json b/src/generated/resources/assets/create/models/block/red_table_cloth.json new file mode 100644 index 0000000000..7800278c4e --- /dev/null +++ b/src/generated/resources/assets/create/models/block/red_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/red" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_0.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_0.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_ceiling_0.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_0.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_1.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_1.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_ceiling_1.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_1.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_2.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_2.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_ceiling_2.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_2.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_3.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_3.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_ceiling_3.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_3.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_4.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_4.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_ceiling_4.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_4.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_5.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_5.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_ceiling_5.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_ceiling_5.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_0.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_floor_0.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_floor_0.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_floor_0.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_1.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_floor_1.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_floor_1.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_floor_1.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_2.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_floor_2.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_floor_2.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_floor_2.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_3.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_floor_3.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_floor_3.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_floor_3.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_4.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_floor_4.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_floor_4.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_floor_4.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_5.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_floor_5.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_floor_5.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_floor_5.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_0.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_wall_0.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_wall_0.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_wall_0.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_1.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_wall_1.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_wall_1.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_wall_1.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_2.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_wall_2.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_wall_2.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_wall_2.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_3.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_wall_3.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_wall_3.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_wall_3.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_4.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_wall_4.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_wall_4.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_wall_4.json diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_5.json b/src/generated/resources/assets/create/models/block/threshold_switch/block_wall_5.json similarity index 100% rename from src/generated/resources/assets/create/models/threshold_switch/block_wall_5.json rename to src/generated/resources/assets/create/models/block/threshold_switch/block_wall_5.json diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_block.json b/src/generated/resources/assets/create/models/block/weathered_iron_block.json new file mode 100644 index 0000000000..5f7ccdebe4 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_block.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/weathered_iron_block_top", + "side": "create:block/weathered_iron_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_1.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_1.json new file mode 100644 index 0000000000..6376f886b3 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_1.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/palettes/weathered_iron_window_1_end", + "side": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_2.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_2.json new file mode 100644 index 0000000000..14f0a36ec5 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_2.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/palettes/weathered_iron_window_2_end", + "side": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_3.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_3.json new file mode 100644 index 0000000000..18b50dc166 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_3.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/palettes/weathered_iron_window_3_end", + "side": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_4.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_4.json new file mode 100644 index 0000000000..6eee07195b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_4.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/palettes/weathered_iron_window_4_end", + "side": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_noside.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_noside.json new file mode 100644 index 0000000000..a7c2623e9c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_noside.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside", + "textures": { + "edge": "create:block/palettes/weathered_iron_window_pane_top", + "pane": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_noside_alt.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_noside_alt.json new file mode 100644 index 0000000000..c1b049e593 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_noside_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside_alt", + "textures": { + "edge": "create:block/palettes/weathered_iron_window_pane_top", + "pane": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_post.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_post.json new file mode 100644 index 0000000000..836f61fc95 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_post.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/post", + "textures": { + "edge": "create:block/palettes/weathered_iron_window_pane_top", + "pane": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_side.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_side.json new file mode 100644 index 0000000000..c6bb36f691 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_side.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side", + "textures": { + "edge": "create:block/palettes/weathered_iron_window_pane_top", + "pane": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_side_alt.json b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_side_alt.json new file mode 100644 index 0000000000..73c130b128 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/weathered_iron_window_pane_side_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side_alt", + "textures": { + "edge": "create:block/palettes/weathered_iron_window_pane_top", + "pane": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/white_postbox_closed.json b/src/generated/resources/assets/create/models/block/white_postbox_closed.json new file mode 100644 index 0000000000..b1ff4edbc3 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/white_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_white", + "1": "create:block/post_box/post_box_white_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/white_postbox_open.json b/src/generated/resources/assets/create/models/block/white_postbox_open.json new file mode 100644 index 0000000000..bb1b084cb7 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/white_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_white", + "1": "create:block/post_box/post_box_white_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/white_table_cloth.json b/src/generated/resources/assets/create/models/block/white_table_cloth.json new file mode 100644 index 0000000000..6b450c27c3 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/white_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/white" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/yellow_postbox_closed.json b/src/generated/resources/assets/create/models/block/yellow_postbox_closed.json new file mode 100644 index 0000000000..53080575c5 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/yellow_postbox_closed.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_closed", + "textures": { + "0": "create:block/post_box/post_box_yellow", + "1": "create:block/post_box/post_box_yellow_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/yellow_postbox_open.json b/src/generated/resources/assets/create/models/block/yellow_postbox_open.json new file mode 100644 index 0000000000..6ce15c57c8 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/yellow_postbox_open.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/block_open", + "textures": { + "0": "create:block/post_box/post_box_yellow", + "1": "create:block/post_box/post_box_yellow_open" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/yellow_table_cloth.json b/src/generated/resources/assets/create/models/block/yellow_table_cloth.json new file mode 100644 index 0000000000..2b5ff22b31 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/yellow_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/block", + "textures": { + "0": "create:block/table_cloth/yellow" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/acacia_window_pane.json b/src/generated/resources/assets/create/models/item/acacia_window_pane.json index 03ea16c3ac..9ccf7a224c 100644 --- a/src/generated/resources/assets/create/models/item/acacia_window_pane.json +++ b/src/generated/resources/assets/create/models/item/acacia_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/acacia_planks", - "pane": "create:block/palettes/acacia_window" + "layer0": "create:block/palettes/acacia_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_bars.json b/src/generated/resources/assets/create/models/item/andesite_bars.json index a881e12f6b..ee12bac6c3 100644 --- a/src/generated/resources/assets/create/models/item/andesite_bars.json +++ b/src/generated/resources/assets/create/models/item/andesite_bars.json @@ -1,7 +1,6 @@ { - "parent": "create:item/bars", + "parent": "minecraft:item/generated", "textures": { - "bars": "create:block/bars/andesite_bars", - "edge": "create:block/bars/andesite_bars_edge" + "layer0": "create:block/bars/andesite_bars" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_table_cloth.json b/src/generated/resources/assets/create/models/item/andesite_table_cloth.json new file mode 100644 index 0000000000..7249d5519e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/andesite_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/andesite" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/bamboo_window.json b/src/generated/resources/assets/create/models/item/bamboo_window.json new file mode 100644 index 0000000000..4d7ca412ea --- /dev/null +++ b/src/generated/resources/assets/create/models/item/bamboo_window.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bamboo_window" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/bamboo_window_pane.json b/src/generated/resources/assets/create/models/item/bamboo_window_pane.json new file mode 100644 index 0000000000..12cfd60014 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/bamboo_window_pane.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:block/palettes/bamboo_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/birch_window_pane.json b/src/generated/resources/assets/create/models/item/birch_window_pane.json index 3eb2e72698..f7e09d8f24 100644 --- a/src/generated/resources/assets/create/models/item/birch_window_pane.json +++ b/src/generated/resources/assets/create/models/item/birch_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/birch_planks", - "pane": "create:block/palettes/birch_window" + "layer0": "create:block/palettes/birch_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/black_postbox.json b/src/generated/resources/assets/create/models/item/black_postbox.json new file mode 100644 index 0000000000..ac76bee8fb --- /dev/null +++ b/src/generated/resources/assets/create/models/item/black_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_black", + "1": "create:block/post_box/post_box_black_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/black_table_cloth.json b/src/generated/resources/assets/create/models/item/black_table_cloth.json new file mode 100644 index 0000000000..caa880e12b --- /dev/null +++ b/src/generated/resources/assets/create/models/item/black_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/black" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/blue_postbox.json b/src/generated/resources/assets/create/models/item/blue_postbox.json new file mode 100644 index 0000000000..4ddfa86bc0 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/blue_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_blue", + "1": "create:block/post_box/post_box_blue_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/blue_table_cloth.json b/src/generated/resources/assets/create/models/item/blue_table_cloth.json new file mode 100644 index 0000000000..60affaec7b --- /dev/null +++ b/src/generated/resources/assets/create/models/item/blue_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/bound_cardboard_block.json b/src/generated/resources/assets/create/models/item/bound_cardboard_block.json new file mode 100644 index 0000000000..9eadc7114d --- /dev/null +++ b/src/generated/resources/assets/create/models/item/bound_cardboard_block.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/bound_cardboard_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_bars.json b/src/generated/resources/assets/create/models/item/brass_bars.json index e1b32edd80..8140aae6b3 100644 --- a/src/generated/resources/assets/create/models/item/brass_bars.json +++ b/src/generated/resources/assets/create/models/item/brass_bars.json @@ -1,7 +1,6 @@ { - "parent": "create:item/bars", + "parent": "minecraft:item/generated", "textures": { - "bars": "create:block/bars/brass_bars", - "edge": "create:block/bars/brass_bars_edge" + "layer0": "create:block/bars/brass_bars" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_table_cloth.json b/src/generated/resources/assets/create/models/item/brass_table_cloth.json new file mode 100644 index 0000000000..f97c05bb55 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/brass_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/brass" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brown_postbox.json b/src/generated/resources/assets/create/models/item/brown_postbox.json new file mode 100644 index 0000000000..aa5c8fc6c6 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/brown_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_brown", + "1": "create:block/post_box/post_box_brown_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brown_table_cloth.json b/src/generated/resources/assets/create/models/item/brown_table_cloth.json new file mode 100644 index 0000000000..04aad3977e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/brown_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/brown" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard.json b/src/generated/resources/assets/create/models/item/cardboard.json new file mode 100644 index 0000000000..0c9666da8d --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_block.json b/src/generated/resources/assets/create/models/item/cardboard_block.json new file mode 100644 index 0000000000..c39463f355 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_block.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/cardboard_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots.json b/src/generated/resources/assets/create/models/item/cardboard_boots.json new file mode 100644 index 0000000000..c78fc3d330 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots.json @@ -0,0 +1,68 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "create:item/cardboard_boots_quartz_trim", + "predicate": { + "minecraft:trim_type": 0.1 + } + }, + { + "model": "create:item/cardboard_boots_iron_trim", + "predicate": { + "minecraft:trim_type": 0.2 + } + }, + { + "model": "create:item/cardboard_boots_netherite_trim", + "predicate": { + "minecraft:trim_type": 0.3 + } + }, + { + "model": "create:item/cardboard_boots_redstone_trim", + "predicate": { + "minecraft:trim_type": 0.4 + } + }, + { + "model": "create:item/cardboard_boots_copper_trim", + "predicate": { + "minecraft:trim_type": 0.5 + } + }, + { + "model": "create:item/cardboard_boots_gold_trim", + "predicate": { + "minecraft:trim_type": 0.6 + } + }, + { + "model": "create:item/cardboard_boots_emerald_trim", + "predicate": { + "minecraft:trim_type": 0.7 + } + }, + { + "model": "create:item/cardboard_boots_diamond_trim", + "predicate": { + "minecraft:trim_type": 0.8 + } + }, + { + "model": "create:item/cardboard_boots_lapis_trim", + "predicate": { + "minecraft:trim_type": 0.9 + } + }, + { + "model": "create:item/cardboard_boots_amethyst_trim", + "predicate": { + "minecraft:trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "create:item/cardboard_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_amethyst_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_amethyst_trim.json new file mode 100644 index 0000000000..b590a2b7a4 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_amethyst_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_amethyst" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_copper_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_copper_trim.json new file mode 100644 index 0000000000..bfb821ba91 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_copper_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_copper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_diamond_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_diamond_trim.json new file mode 100644 index 0000000000..fc4e82cdc5 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_diamond_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_diamond" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_emerald_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_emerald_trim.json new file mode 100644 index 0000000000..ba0cd0bb21 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_emerald_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_emerald" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_gold_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_gold_trim.json new file mode 100644 index 0000000000..e21893bc33 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_gold_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_gold" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_iron_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_iron_trim.json new file mode 100644 index 0000000000..8505baf4f4 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_iron_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_iron" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_lapis_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_lapis_trim.json new file mode 100644 index 0000000000..3ad30ed6b5 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_lapis_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_lapis" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_netherite_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_netherite_trim.json new file mode 100644 index 0000000000..78b12a9b3e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_netherite_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_netherite" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_quartz_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_quartz_trim.json new file mode 100644 index 0000000000..6635e107bc --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_quartz_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_quartz" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_boots_redstone_trim.json b/src/generated/resources/assets/create/models/item/cardboard_boots_redstone_trim.json new file mode 100644 index 0000000000..e3d8c5647a --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_boots_redstone_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_boots", + "layer1": "create:trims/items/card_boots_trim_redstone" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate.json new file mode 100644 index 0000000000..28b4eb2b42 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate.json @@ -0,0 +1,68 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "create:item/cardboard_chestplate_quartz_trim", + "predicate": { + "minecraft:trim_type": 0.1 + } + }, + { + "model": "create:item/cardboard_chestplate_iron_trim", + "predicate": { + "minecraft:trim_type": 0.2 + } + }, + { + "model": "create:item/cardboard_chestplate_netherite_trim", + "predicate": { + "minecraft:trim_type": 0.3 + } + }, + { + "model": "create:item/cardboard_chestplate_redstone_trim", + "predicate": { + "minecraft:trim_type": 0.4 + } + }, + { + "model": "create:item/cardboard_chestplate_copper_trim", + "predicate": { + "minecraft:trim_type": 0.5 + } + }, + { + "model": "create:item/cardboard_chestplate_gold_trim", + "predicate": { + "minecraft:trim_type": 0.6 + } + }, + { + "model": "create:item/cardboard_chestplate_emerald_trim", + "predicate": { + "minecraft:trim_type": 0.7 + } + }, + { + "model": "create:item/cardboard_chestplate_diamond_trim", + "predicate": { + "minecraft:trim_type": 0.8 + } + }, + { + "model": "create:item/cardboard_chestplate_lapis_trim", + "predicate": { + "minecraft:trim_type": 0.9 + } + }, + { + "model": "create:item/cardboard_chestplate_amethyst_trim", + "predicate": { + "minecraft:trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "create:item/cardboard_chestplate" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_amethyst_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_amethyst_trim.json new file mode 100644 index 0000000000..d1d97f5d0c --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_amethyst_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_amethyst" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_copper_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_copper_trim.json new file mode 100644 index 0000000000..7e188fb1be --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_copper_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_copper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_diamond_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_diamond_trim.json new file mode 100644 index 0000000000..05dd595373 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_diamond_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_diamond" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_emerald_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_emerald_trim.json new file mode 100644 index 0000000000..e9ec729e1f --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_emerald_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_emerald" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_gold_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_gold_trim.json new file mode 100644 index 0000000000..9cb2d00739 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_gold_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_gold" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_iron_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_iron_trim.json new file mode 100644 index 0000000000..2e758a347e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_iron_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_iron" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_lapis_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_lapis_trim.json new file mode 100644 index 0000000000..a37a71bcbf --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_lapis_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_lapis" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_netherite_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_netherite_trim.json new file mode 100644 index 0000000000..e3d749d65a --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_netherite_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_netherite" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_quartz_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_quartz_trim.json new file mode 100644 index 0000000000..abee637046 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_quartz_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_quartz" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_chestplate_redstone_trim.json b/src/generated/resources/assets/create/models/item/cardboard_chestplate_redstone_trim.json new file mode 100644 index 0000000000..a163ed20d8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_chestplate_redstone_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_chestplate", + "layer1": "create:trims/items/card_chestplate_trim_redstone" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet.json b/src/generated/resources/assets/create/models/item/cardboard_helmet.json new file mode 100644 index 0000000000..4746d0b9fa --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet.json @@ -0,0 +1,68 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "create:item/cardboard_helmet_quartz_trim", + "predicate": { + "minecraft:trim_type": 0.1 + } + }, + { + "model": "create:item/cardboard_helmet_iron_trim", + "predicate": { + "minecraft:trim_type": 0.2 + } + }, + { + "model": "create:item/cardboard_helmet_netherite_trim", + "predicate": { + "minecraft:trim_type": 0.3 + } + }, + { + "model": "create:item/cardboard_helmet_redstone_trim", + "predicate": { + "minecraft:trim_type": 0.4 + } + }, + { + "model": "create:item/cardboard_helmet_copper_trim", + "predicate": { + "minecraft:trim_type": 0.5 + } + }, + { + "model": "create:item/cardboard_helmet_gold_trim", + "predicate": { + "minecraft:trim_type": 0.6 + } + }, + { + "model": "create:item/cardboard_helmet_emerald_trim", + "predicate": { + "minecraft:trim_type": 0.7 + } + }, + { + "model": "create:item/cardboard_helmet_diamond_trim", + "predicate": { + "minecraft:trim_type": 0.8 + } + }, + { + "model": "create:item/cardboard_helmet_lapis_trim", + "predicate": { + "minecraft:trim_type": 0.9 + } + }, + { + "model": "create:item/cardboard_helmet_amethyst_trim", + "predicate": { + "minecraft:trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "create:item/cardboard_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_amethyst_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_amethyst_trim.json new file mode 100644 index 0000000000..d9cb46f71c --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_amethyst_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_amethyst" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_copper_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_copper_trim.json new file mode 100644 index 0000000000..abdd6b152f --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_copper_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_copper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_diamond_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_diamond_trim.json new file mode 100644 index 0000000000..6e97348860 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_diamond_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_diamond" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_emerald_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_emerald_trim.json new file mode 100644 index 0000000000..98f1995b39 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_emerald_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_emerald" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_gold_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_gold_trim.json new file mode 100644 index 0000000000..8ee0eca400 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_gold_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_gold" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_iron_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_iron_trim.json new file mode 100644 index 0000000000..730ddda90b --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_iron_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_iron" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_lapis_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_lapis_trim.json new file mode 100644 index 0000000000..0699f700b4 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_lapis_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_lapis" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_netherite_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_netherite_trim.json new file mode 100644 index 0000000000..b05b40a619 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_netherite_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_netherite" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_quartz_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_quartz_trim.json new file mode 100644 index 0000000000..e1ded50c27 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_quartz_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_quartz" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_helmet_redstone_trim.json b/src/generated/resources/assets/create/models/item/cardboard_helmet_redstone_trim.json new file mode 100644 index 0000000000..ecbb8aa49e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_helmet_redstone_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_helmet", + "layer1": "create:trims/items/card_helmet_trim_redstone" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings.json b/src/generated/resources/assets/create/models/item/cardboard_leggings.json new file mode 100644 index 0000000000..014b01ea75 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings.json @@ -0,0 +1,68 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "create:item/cardboard_leggings_quartz_trim", + "predicate": { + "minecraft:trim_type": 0.1 + } + }, + { + "model": "create:item/cardboard_leggings_iron_trim", + "predicate": { + "minecraft:trim_type": 0.2 + } + }, + { + "model": "create:item/cardboard_leggings_netherite_trim", + "predicate": { + "minecraft:trim_type": 0.3 + } + }, + { + "model": "create:item/cardboard_leggings_redstone_trim", + "predicate": { + "minecraft:trim_type": 0.4 + } + }, + { + "model": "create:item/cardboard_leggings_copper_trim", + "predicate": { + "minecraft:trim_type": 0.5 + } + }, + { + "model": "create:item/cardboard_leggings_gold_trim", + "predicate": { + "minecraft:trim_type": 0.6 + } + }, + { + "model": "create:item/cardboard_leggings_emerald_trim", + "predicate": { + "minecraft:trim_type": 0.7 + } + }, + { + "model": "create:item/cardboard_leggings_diamond_trim", + "predicate": { + "minecraft:trim_type": 0.8 + } + }, + { + "model": "create:item/cardboard_leggings_lapis_trim", + "predicate": { + "minecraft:trim_type": 0.9 + } + }, + { + "model": "create:item/cardboard_leggings_amethyst_trim", + "predicate": { + "minecraft:trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "create:item/cardboard_leggings" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_amethyst_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_amethyst_trim.json new file mode 100644 index 0000000000..c5652cbcc2 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_amethyst_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_amethyst" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_copper_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_copper_trim.json new file mode 100644 index 0000000000..95771e62dc --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_copper_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_copper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_diamond_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_diamond_trim.json new file mode 100644 index 0000000000..706e7a6693 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_diamond_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_diamond" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_emerald_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_emerald_trim.json new file mode 100644 index 0000000000..97f74ca197 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_emerald_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_emerald" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_gold_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_gold_trim.json new file mode 100644 index 0000000000..5d2291c6b9 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_gold_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_gold" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_iron_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_iron_trim.json new file mode 100644 index 0000000000..f0c2be4338 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_iron_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_iron" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_lapis_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_lapis_trim.json new file mode 100644 index 0000000000..2466245a51 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_lapis_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_lapis" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_netherite_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_netherite_trim.json new file mode 100644 index 0000000000..70b05181c7 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_netherite_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_netherite" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_quartz_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_quartz_trim.json new file mode 100644 index 0000000000..fe41a39804 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_quartz_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_quartz" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_leggings_redstone_trim.json b/src/generated/resources/assets/create/models/item/cardboard_leggings_redstone_trim.json new file mode 100644 index 0000000000..1cdd7647e1 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_leggings_redstone_trim.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/cardboard_leggings", + "layer1": "create:trims/items/card_leggings_trim_redstone" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_package_10x12.json b/src/generated/resources/assets/create/models/item/cardboard_package_10x12.json new file mode 100644 index 0000000000..5e66034af1 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_package_10x12.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/package/cardboard_10x12" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_package_10x8.json b/src/generated/resources/assets/create/models/item/cardboard_package_10x8.json new file mode 100644 index 0000000000..11eed5824e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_package_10x8.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/package/cardboard_10x8" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_package_12x10.json b/src/generated/resources/assets/create/models/item/cardboard_package_12x10.json new file mode 100644 index 0000000000..90326f1358 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_package_12x10.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/package/cardboard_12x10" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_package_12x12.json b/src/generated/resources/assets/create/models/item/cardboard_package_12x12.json new file mode 100644 index 0000000000..aa52db09e3 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_package_12x12.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/package/cardboard_12x12" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cardboard_sword.json b/src/generated/resources/assets/create/models/item/cardboard_sword.json new file mode 100644 index 0000000000..c3786698f9 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cardboard_sword.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/cardboard_sword/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/chain_conveyor.json b/src/generated/resources/assets/create/models/item/chain_conveyor.json new file mode 100644 index 0000000000..6cd1930f7c --- /dev/null +++ b/src/generated/resources/assets/create/models/item/chain_conveyor.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/chain_conveyor/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cherry_window.json b/src/generated/resources/assets/create/models/item/cherry_window.json new file mode 100644 index 0000000000..02a0066dc5 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cherry_window.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/cherry_window" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cherry_window_pane.json b/src/generated/resources/assets/create/models/item/cherry_window_pane.json new file mode 100644 index 0000000000..3eaeaa351d --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cherry_window_pane.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:block/palettes/cherry_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copper_bars.json b/src/generated/resources/assets/create/models/item/copper_bars.json index 66553f12e1..eeb2a9d626 100644 --- a/src/generated/resources/assets/create/models/item/copper_bars.json +++ b/src/generated/resources/assets/create/models/item/copper_bars.json @@ -1,7 +1,6 @@ { - "parent": "create:item/bars", + "parent": "minecraft:item/generated", "textures": { - "bars": "create:block/bars/copper_bars", - "edge": "create:block/bars/copper_bars_edge" + "layer0": "create:block/bars/copper_bars" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copper_table_cloth.json b/src/generated/resources/assets/create/models/item/copper_table_cloth.json new file mode 100644 index 0000000000..339e836882 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copper_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/copper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crimson_window_pane.json b/src/generated/resources/assets/create/models/item/crimson_window_pane.json index 496b0c0fc4..d12dce270a 100644 --- a/src/generated/resources/assets/create/models/item/crimson_window_pane.json +++ b/src/generated/resources/assets/create/models/item/crimson_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/crimson_planks", - "pane": "create:block/palettes/crimson_window" + "layer0": "create:block/palettes/crimson_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cyan_postbox.json b/src/generated/resources/assets/create/models/item/cyan_postbox.json new file mode 100644 index 0000000000..0e73d013f1 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cyan_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_cyan", + "1": "create:block/post_box/post_box_cyan_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/cyan_table_cloth.json b/src/generated/resources/assets/create/models/item/cyan_table_cloth.json new file mode 100644 index 0000000000..b6aad4d9ec --- /dev/null +++ b/src/generated/resources/assets/create/models/item/cyan_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/cyan" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/dark_oak_window_pane.json b/src/generated/resources/assets/create/models/item/dark_oak_window_pane.json index ea970f28e1..b618ec86cc 100644 --- a/src/generated/resources/assets/create/models/item/dark_oak_window_pane.json +++ b/src/generated/resources/assets/create/models/item/dark_oak_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/dark_oak_planks", - "pane": "create:block/palettes/dark_oak_window" + "layer0": "create:block/palettes/dark_oak_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/desk_bell.json b/src/generated/resources/assets/create/models/item/desk_bell.json new file mode 100644 index 0000000000..866b99fd86 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/desk_bell.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/desk_bell/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/factory_gauge.json b/src/generated/resources/assets/create/models/item/factory_gauge.json new file mode 100644 index 0000000000..47ba842ada --- /dev/null +++ b/src/generated/resources/assets/create/models/item/factory_gauge.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/factory_gauge/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/framed_glass_pane.json b/src/generated/resources/assets/create/models/item/framed_glass_pane.json index 1d48f846b8..34cd0fa5d8 100644 --- a/src/generated/resources/assets/create/models/item/framed_glass_pane.json +++ b/src/generated/resources/assets/create/models/item/framed_glass_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "create:block/palettes/framed_glass_pane_top", - "pane": "create:block/palettes/framed_glass" + "layer0": "create:block/palettes/framed_glass" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/gray_postbox.json b/src/generated/resources/assets/create/models/item/gray_postbox.json new file mode 100644 index 0000000000..90e72e86d8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/gray_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_gray", + "1": "create:block/post_box/post_box_gray_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/gray_table_cloth.json b/src/generated/resources/assets/create/models/item/gray_table_cloth.json new file mode 100644 index 0000000000..2e4f480cac --- /dev/null +++ b/src/generated/resources/assets/create/models/item/gray_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/green_postbox.json b/src/generated/resources/assets/create/models/item/green_postbox.json new file mode 100644 index 0000000000..39f53f41be --- /dev/null +++ b/src/generated/resources/assets/create/models/item/green_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_green", + "1": "create:block/post_box/post_box_green_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/green_table_cloth.json b/src/generated/resources/assets/create/models/item/green_table_cloth.json new file mode 100644 index 0000000000..3370bf8000 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/green_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/green" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/horizontal_framed_glass_pane.json b/src/generated/resources/assets/create/models/item/horizontal_framed_glass_pane.json index 5b8c4b78c6..19ba12ca20 100644 --- a/src/generated/resources/assets/create/models/item/horizontal_framed_glass_pane.json +++ b/src/generated/resources/assets/create/models/item/horizontal_framed_glass_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "create:block/palettes/framed_glass_pane_top", - "pane": "create:block/palettes/horizontal_framed_glass" + "layer0": "create:block/palettes/horizontal_framed_glass" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/industrial_iron_window.json b/src/generated/resources/assets/create/models/item/industrial_iron_window.json new file mode 100644 index 0000000000..3387bcdffc --- /dev/null +++ b/src/generated/resources/assets/create/models/item/industrial_iron_window.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/industrial_iron_window" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/industrial_iron_window_pane.json b/src/generated/resources/assets/create/models/item/industrial_iron_window_pane.json new file mode 100644 index 0000000000..83f5bfd65d --- /dev/null +++ b/src/generated/resources/assets/create/models/item/industrial_iron_window_pane.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:block/palettes/industrial_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/item_hatch.json b/src/generated/resources/assets/create/models/item/item_hatch.json new file mode 100644 index 0000000000..4c509189fb --- /dev/null +++ b/src/generated/resources/assets/create/models/item/item_hatch.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/item_hatch/block_closed" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/jungle_window_pane.json b/src/generated/resources/assets/create/models/item/jungle_window_pane.json index 9f783191e1..561935c644 100644 --- a/src/generated/resources/assets/create/models/item/jungle_window_pane.json +++ b/src/generated/resources/assets/create/models/item/jungle_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/jungle_planks", - "pane": "create:block/palettes/jungle_window" + "layer0": "create:block/palettes/jungle_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/light_blue_postbox.json b/src/generated/resources/assets/create/models/item/light_blue_postbox.json new file mode 100644 index 0000000000..c4556c8247 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/light_blue_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_light_blue", + "1": "create:block/post_box/post_box_light_blue_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/light_blue_table_cloth.json b/src/generated/resources/assets/create/models/item/light_blue_table_cloth.json new file mode 100644 index 0000000000..3c20d0734e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/light_blue_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/light_blue" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/light_gray_postbox.json b/src/generated/resources/assets/create/models/item/light_gray_postbox.json new file mode 100644 index 0000000000..3620b008fd --- /dev/null +++ b/src/generated/resources/assets/create/models/item/light_gray_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_light_gray", + "1": "create:block/post_box/post_box_light_gray_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/light_gray_table_cloth.json b/src/generated/resources/assets/create/models/item/light_gray_table_cloth.json new file mode 100644 index 0000000000..bc2e6ce8b8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/light_gray_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/light_gray" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/lime_postbox.json b/src/generated/resources/assets/create/models/item/lime_postbox.json new file mode 100644 index 0000000000..c4eb51bd53 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/lime_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_lime", + "1": "create:block/post_box/post_box_lime_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/lime_table_cloth.json b/src/generated/resources/assets/create/models/item/lime_table_cloth.json new file mode 100644 index 0000000000..860775ebc2 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/lime_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/lime" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/magenta_postbox.json b/src/generated/resources/assets/create/models/item/magenta_postbox.json new file mode 100644 index 0000000000..b7f6f1288e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/magenta_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_magenta", + "1": "create:block/post_box/post_box_magenta_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/magenta_table_cloth.json b/src/generated/resources/assets/create/models/item/magenta_table_cloth.json new file mode 100644 index 0000000000..d5c88a89f1 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/magenta_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/magenta" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/mangrove_window_pane.json b/src/generated/resources/assets/create/models/item/mangrove_window_pane.json index e34b9714e4..5af42dbe6b 100644 --- a/src/generated/resources/assets/create/models/item/mangrove_window_pane.json +++ b/src/generated/resources/assets/create/models/item/mangrove_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/mangrove_planks", - "pane": "create:block/palettes/mangrove_window" + "layer0": "create:block/palettes/mangrove_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/oak_window_pane.json b/src/generated/resources/assets/create/models/item/oak_window_pane.json index fad014834e..62417042b4 100644 --- a/src/generated/resources/assets/create/models/item/oak_window_pane.json +++ b/src/generated/resources/assets/create/models/item/oak_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/oak_planks", - "pane": "create:block/palettes/oak_window" + "layer0": "create:block/palettes/oak_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/orange_postbox.json b/src/generated/resources/assets/create/models/item/orange_postbox.json new file mode 100644 index 0000000000..3dcf782a1e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/orange_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_orange", + "1": "create:block/post_box/post_box_orange_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/orange_table_cloth.json b/src/generated/resources/assets/create/models/item/orange_table_cloth.json new file mode 100644 index 0000000000..aa170587db --- /dev/null +++ b/src/generated/resources/assets/create/models/item/orange_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/orange" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/ornate_iron_window_pane.json b/src/generated/resources/assets/create/models/item/ornate_iron_window_pane.json index e522e49a62..e15dab88e9 100644 --- a/src/generated/resources/assets/create/models/item/ornate_iron_window_pane.json +++ b/src/generated/resources/assets/create/models/item/ornate_iron_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "create:block/palettes/ornate_iron_window_pane_top", - "pane": "create:block/palettes/ornate_iron_window" + "layer0": "create:block/palettes/ornate_iron_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/package_filter.json b/src/generated/resources/assets/create/models/item/package_filter.json new file mode 100644 index 0000000000..43b4b3213e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/package_filter.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/package_filter" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/package_frogport.json b/src/generated/resources/assets/create/models/item/package_frogport.json new file mode 100644 index 0000000000..0598cfec30 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/package_frogport.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/package_frogport/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/packager.json b/src/generated/resources/assets/create/models/item/packager.json new file mode 100644 index 0000000000..18467506e5 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/packager.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/packager/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/pink_postbox.json b/src/generated/resources/assets/create/models/item/pink_postbox.json new file mode 100644 index 0000000000..3c1d74edc8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/pink_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_pink", + "1": "create:block/post_box/post_box_pink_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/pink_table_cloth.json b/src/generated/resources/assets/create/models/item/pink_table_cloth.json new file mode 100644 index 0000000000..4ab7a28bd8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/pink_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/pink" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/pulp.json b/src/generated/resources/assets/create/models/item/pulp.json new file mode 100644 index 0000000000..7ea580f56a --- /dev/null +++ b/src/generated/resources/assets/create/models/item/pulp.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/pulp" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/pulse_timer.json b/src/generated/resources/assets/create/models/item/pulse_timer.json new file mode 100644 index 0000000000..ddecb0a494 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/pulse_timer.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/diodes/pulse_timer", + "textures": { + "top": "create:block/diodes/pulse_timer/item" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/purple_postbox.json b/src/generated/resources/assets/create/models/item/purple_postbox.json new file mode 100644 index 0000000000..0d99cca218 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/purple_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_purple", + "1": "create:block/post_box/post_box_purple_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/purple_table_cloth.json b/src/generated/resources/assets/create/models/item/purple_table_cloth.json new file mode 100644 index 0000000000..7737fb6800 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/purple_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/purple" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_creeper_package.json b/src/generated/resources/assets/create/models/item/rare_creeper_package.json new file mode 100644 index 0000000000..b90f949880 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_creeper_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_creeper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_darcy_package.json b/src/generated/resources/assets/create/models/item/rare_darcy_package.json new file mode 100644 index 0000000000..d5a366d229 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_darcy_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_darcy" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_evan_package.json b/src/generated/resources/assets/create/models/item/rare_evan_package.json new file mode 100644 index 0000000000..28aa663b83 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_evan_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_evan" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_jinx_package.json b/src/generated/resources/assets/create/models/item/rare_jinx_package.json new file mode 100644 index 0000000000..f5c305b991 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_jinx_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_jinx" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_kryppers_package.json b/src/generated/resources/assets/create/models/item/rare_kryppers_package.json new file mode 100644 index 0000000000..4e26296658 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_kryppers_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_kryppers" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_simi_package.json b/src/generated/resources/assets/create/models/item/rare_simi_package.json new file mode 100644 index 0000000000..5a4bfd3481 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_simi_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_simi" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_starlotte_package.json b/src/generated/resources/assets/create/models/item/rare_starlotte_package.json new file mode 100644 index 0000000000..d46b50c63e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_starlotte_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_starlotte" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_thunder_package.json b/src/generated/resources/assets/create/models/item/rare_thunder_package.json new file mode 100644 index 0000000000..45d192ce32 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_thunder_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_thunder" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_up_package.json b/src/generated/resources/assets/create/models/item/rare_up_package.json new file mode 100644 index 0000000000..562b182ac2 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_up_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_up" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/rare_vector_package.json b/src/generated/resources/assets/create/models/item/rare_vector_package.json new file mode 100644 index 0000000000..4aa2f054e5 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/rare_vector_package.json @@ -0,0 +1,6 @@ +{ + "parent": "create:item/package/custom_12x10", + "textures": { + "2": "create:item/package/rare_vector" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/red_postbox.json b/src/generated/resources/assets/create/models/item/red_postbox.json new file mode 100644 index 0000000000..8806a65a81 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/red_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_red", + "1": "create:block/post_box/post_box_red_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/red_table_cloth.json b/src/generated/resources/assets/create/models/item/red_table_cloth.json new file mode 100644 index 0000000000..4e2cf2433c --- /dev/null +++ b/src/generated/resources/assets/create/models/item/red_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/red" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/redstone_requester.json b/src/generated/resources/assets/create/models/item/redstone_requester.json new file mode 100644 index 0000000000..d8caa6f255 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/redstone_requester.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/redstone_requester/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/repackager.json b/src/generated/resources/assets/create/models/item/repackager.json new file mode 100644 index 0000000000..a4acf1aa3a --- /dev/null +++ b/src/generated/resources/assets/create/models/item/repackager.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/repackager/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/shopping_list.json b/src/generated/resources/assets/create/models/item/shopping_list.json new file mode 100644 index 0000000000..f51d72f6cb --- /dev/null +++ b/src/generated/resources/assets/create/models/item/shopping_list.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/shopping_list" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/spruce_window_pane.json b/src/generated/resources/assets/create/models/item/spruce_window_pane.json index f6f6c6e7d3..b40d8d6d35 100644 --- a/src/generated/resources/assets/create/models/item/spruce_window_pane.json +++ b/src/generated/resources/assets/create/models/item/spruce_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/spruce_planks", - "pane": "create:block/palettes/spruce_window" + "layer0": "create:block/palettes/spruce_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/stock_link.json b/src/generated/resources/assets/create/models/item/stock_link.json new file mode 100644 index 0000000000..498a66c399 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/stock_link.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/stock_link/block_vertical" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/stock_ticker.json b/src/generated/resources/assets/create/models/item/stock_ticker.json new file mode 100644 index 0000000000..923a047f25 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/stock_ticker.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/stock_ticker" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/tiled_glass_pane.json b/src/generated/resources/assets/create/models/item/tiled_glass_pane.json index 8223e7d169..d9c1453d35 100644 --- a/src/generated/resources/assets/create/models/item/tiled_glass_pane.json +++ b/src/generated/resources/assets/create/models/item/tiled_glass_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/glass_pane_top", - "pane": "create:block/palettes/tiled_glass" + "layer0": "create:block/palettes/tiled_glass" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/transmitter.json b/src/generated/resources/assets/create/models/item/transmitter.json new file mode 100644 index 0000000000..2fca934ff3 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/transmitter.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/transmitter" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/vertical_framed_glass_pane.json b/src/generated/resources/assets/create/models/item/vertical_framed_glass_pane.json index c5df1d782b..6c15091d70 100644 --- a/src/generated/resources/assets/create/models/item/vertical_framed_glass_pane.json +++ b/src/generated/resources/assets/create/models/item/vertical_framed_glass_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "create:block/palettes/framed_glass_pane_top", - "pane": "create:block/palettes/vertical_framed_glass" + "layer0": "create:block/palettes/vertical_framed_glass" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/warped_window_pane.json b/src/generated/resources/assets/create/models/item/warped_window_pane.json index c8569bb459..9158d904b2 100644 --- a/src/generated/resources/assets/create/models/item/warped_window_pane.json +++ b/src/generated/resources/assets/create/models/item/warped_window_pane.json @@ -1,7 +1,6 @@ { - "parent": "create:item/pane", + "parent": "minecraft:item/generated", "textures": { - "edge": "minecraft:block/warped_planks", - "pane": "create:block/palettes/warped_window" + "layer0": "create:block/palettes/warped_window" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/weathered_iron_block.json b/src/generated/resources/assets/create/models/item/weathered_iron_block.json new file mode 100644 index 0000000000..beab17e2e1 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/weathered_iron_block.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/weathered_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/weathered_iron_window.json b/src/generated/resources/assets/create/models/item/weathered_iron_window.json new file mode 100644 index 0000000000..6376f886b3 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/weathered_iron_window.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/palettes/weathered_iron_window_1_end", + "side": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/weathered_iron_window_pane.json b/src/generated/resources/assets/create/models/item/weathered_iron_window_pane.json new file mode 100644 index 0000000000..dd738de895 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/weathered_iron_window_pane.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:block/palettes/weathered_iron_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/white_postbox.json b/src/generated/resources/assets/create/models/item/white_postbox.json new file mode 100644 index 0000000000..a57e176769 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/white_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_white", + "1": "create:block/post_box/post_box_white_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/white_table_cloth.json b/src/generated/resources/assets/create/models/item/white_table_cloth.json new file mode 100644 index 0000000000..9a384f722c --- /dev/null +++ b/src/generated/resources/assets/create/models/item/white_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/white" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/yellow_postbox.json b/src/generated/resources/assets/create/models/item/yellow_postbox.json new file mode 100644 index 0000000000..8dc9e1471d --- /dev/null +++ b/src/generated/resources/assets/create/models/item/yellow_postbox.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/package_postbox/item", + "textures": { + "0": "create:block/post_box/post_box_yellow", + "1": "create:block/post_box/post_box_yellow_closed" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/yellow_table_cloth.json b/src/generated/resources/assets/create/models/item/yellow_table_cloth.json new file mode 100644 index 0000000000..2c35c28e48 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/yellow_table_cloth.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/table_cloth/item", + "textures": { + "0": "create:block/table_cloth/yellow" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/sounds.json b/src/generated/resources/assets/create/sounds.json index dc904af682..e658638449 100644 --- a/src/generated/resources/assets/create/sounds.json +++ b/src/generated/resources/assets/create/sounds.json @@ -8,6 +8,15 @@ ], "subtitle": "create.subtitle.blaze_munch" }, + "cardboard_bonk": { + "sounds": [ + { + "type": "file", + "name": "create:cardboard_bonk" + } + ], + "subtitle": "create.subtitle.cardboard_bonk" + }, "chiff": { "sounds": [ { @@ -50,6 +59,15 @@ ], "subtitle": "create.subtitle.confirm" }, + "confirm_2": { + "sounds": [ + { + "type": "file", + "name": "create:confirm_2" + } + ], + "subtitle": "create.subtitle.confirm_2" + }, "contraption_assemble": { "sounds": [ { @@ -207,6 +225,64 @@ ], "subtitle": "create.subtitle.depot_slide" }, + "desk_bell": { + "sounds": [ + { + "type": "file", + "attenuation_distance": 64, + "name": "create:desk_bell" + } + ], + "subtitle": "create.subtitle.desk_bell" + }, + "frogport_catch": { + "sounds": [ + { + "type": "file", + "name": "create:frogport_catch" + }, + { + "type": "file", + "name": "create:frogport_catch_1" + }, + { + "type": "file", + "name": "create:frogport_catch_2" + }, + { + "type": "file", + "name": "create:frogport_catch_3" + } + ], + "subtitle": "create.subtitle.frogport_catch" + }, + "frogport_close": { + "sounds": [ + { + "type": "file", + "name": "create:frogport_close" + } + ], + "subtitle": "create.subtitle.frogport_close" + }, + "frogport_deposit": { + "sounds": [ + { + "type": "event", + "name": "minecraft:entity.frog.tongue" + } + ], + "subtitle": "create.subtitle.frogport_deposit" + }, + "frogport_open": { + "sounds": [ + { + "type": "event", + "name": "minecraft:entity.warden.tendril_clicks" + } + ], + "subtitle": "create.subtitle.frogport_open" + }, "funnel_flap": { "sounds": [ { @@ -251,6 +327,23 @@ ], "subtitle": "create.subtitle.haunted_bell_use" }, + "item_hatch": { + "sounds": [ + { + "type": "event", + "name": "minecraft:block.barrel.open" + } + ], + "subtitle": "create.subtitle.item_hatch" + }, + "item_hatch_compounded_1": { + "sounds": [ + { + "type": "event", + "name": "minecraft:block.netherite_block.place" + } + ] + }, "mechanical_press_activation": { "sounds": [ { @@ -302,6 +395,32 @@ } ] }, + "package_pop": { + "sounds": [ + { + "type": "event", + "name": "minecraft:block.chiseled_bookshelf.break" + } + ], + "subtitle": "create.subtitle.package_pop" + }, + "package_pop_compounded_1": { + "sounds": [ + { + "type": "event", + "name": "minecraft:block.wool.break" + } + ] + }, + "packager": { + "sounds": [ + { + "type": "event", + "name": "minecraft:entity.shulker.open" + } + ], + "subtitle": "create.subtitle.packager" + }, "peculiar_bell_use": { "sounds": [ { @@ -435,6 +554,33 @@ ], "subtitle": "create.subtitle.steam" }, + "stock_link": { + "sounds": [ + { + "type": "file", + "name": "create:stock_link" + } + ], + "subtitle": "create.subtitle.stock_link" + }, + "stock_ticker_request": { + "sounds": [ + { + "type": "file", + "name": "create:stock_ticker_request" + } + ], + "subtitle": "create.subtitle.stock_ticker_request" + }, + "stock_ticker_trade": { + "sounds": [ + { + "type": "file", + "name": "create:stock_ticker_trade" + } + ], + "subtitle": "create.subtitle.stock_ticker_trade" + }, "train": { "sounds": [ { diff --git a/src/generated/resources/assets/minecraft/train_hat_info/wolf.json b/src/generated/resources/assets/minecraft/train_hat_info/wolf.json index 048fa265ea..fb1300073d 100644 --- a/src/generated/resources/assets/minecraft/train_hat_info/wolf.json +++ b/src/generated/resources/assets/minecraft/train_hat_info/wolf.json @@ -1,8 +1,8 @@ { "model_part": "real_head", "offset": [ - 0.5, + 1.0, 2.5, - 0.25 + 1.0 ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/cardboard.json b/src/generated/resources/data/create/advancements/cardboard.json new file mode 100644 index 0000000000..8f253fd4b8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/cardboard.json @@ -0,0 +1,39 @@ +{ + "parent": "create:mechanical_mixer", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.create.cardboard.desc" + }, + "frame": "task", + "hidden": false, + "icon": { + "item": "create:cardboard" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.cardboard" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/cardboard_armor.json b/src/generated/resources/data/create/advancements/cardboard_armor.json new file mode 100644 index 0000000000..178b6e3546 --- /dev/null +++ b/src/generated/resources/data/create/advancements/cardboard_armor.json @@ -0,0 +1,32 @@ +{ + "parent": "create:factory_gauge", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:cardboard_armor_builtin" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.create.cardboard_armor.desc" + }, + "frame": "task", + "hidden": false, + "icon": { + "item": "create:cardboard_chestplate", + "nbt": "{Damage:0}" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.cardboard_armor" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/cardboard_armor_trim.json b/src/generated/resources/data/create/advancements/cardboard_armor_trim.json new file mode 100644 index 0000000000..1874168cfd --- /dev/null +++ b/src/generated/resources/data/create/advancements/cardboard_armor_trim.json @@ -0,0 +1,32 @@ +{ + "parent": "create:cardboard_armor", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:cardboard_armor_trim_builtin" + } + }, + "display": { + "announce_to_chat": true, + "description": { + "color": "#DBA213", + "translate": "advancement.create.cardboard_armor_trim.desc" + }, + "frame": "goal", + "hidden": true, + "icon": { + "item": "create:cardboard_chestplate", + "nbt": "{Damage:0,Trim:{material:\"minecraft:diamond\",pattern:\"minecraft:sentry\"}}" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.cardboard_armor_trim" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/copper_casing.json b/src/generated/resources/data/create/advancements/copper_casing.json index 4a0e4b18a2..2e71bc2764 100644 --- a/src/generated/resources/data/create/advancements/copper_casing.json +++ b/src/generated/resources/data/create/advancements/copper_casing.json @@ -7,7 +7,7 @@ } }, "display": { - "announce_to_chat": true, + "announce_to_chat": false, "description": { "color": "#DBA213", "translate": "advancement.create.copper_casing.desc" diff --git a/src/generated/resources/data/create/advancements/display_link.json b/src/generated/resources/data/create/advancements/display_link.json index 6f774c3543..07fb9bedbd 100644 --- a/src/generated/resources/data/create/advancements/display_link.json +++ b/src/generated/resources/data/create/advancements/display_link.json @@ -7,7 +7,7 @@ } }, "display": { - "announce_to_chat": true, + "announce_to_chat": false, "description": { "color": "#DBA213", "translate": "advancement.create.display_link.desc" diff --git a/src/generated/resources/data/create/advancements/factory_gauge.json b/src/generated/resources/data/create/advancements/factory_gauge.json new file mode 100644 index 0000000000..319c1e81c3 --- /dev/null +++ b/src/generated/resources/data/create/advancements/factory_gauge.json @@ -0,0 +1,31 @@ +{ + "parent": "create:table_cloth_shop", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:factory_gauge_builtin" + } + }, + "display": { + "announce_to_chat": true, + "description": { + "color": "#DBA213", + "translate": "advancement.create.factory_gauge.desc" + }, + "frame": "task", + "hidden": false, + "icon": { + "item": "create:factory_gauge" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.factory_gauge" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/frogport.json b/src/generated/resources/data/create/advancements/frogport.json new file mode 100644 index 0000000000..ad6321a327 --- /dev/null +++ b/src/generated/resources/data/create/advancements/frogport.json @@ -0,0 +1,31 @@ +{ + "parent": "create:stock_ticker", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:frogport_builtin" + } + }, + "display": { + "announce_to_chat": true, + "description": { + "color": "#DBA213", + "translate": "advancement.create.frogport.desc" + }, + "frame": "task", + "hidden": false, + "icon": { + "item": "create:package_frogport" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.frogport" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/package_chute_throw.json b/src/generated/resources/data/create/advancements/package_chute_throw.json new file mode 100644 index 0000000000..9f31bdff19 --- /dev/null +++ b/src/generated/resources/data/create/advancements/package_chute_throw.json @@ -0,0 +1,31 @@ +{ + "parent": "create:cardboard_armor", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:package_chute_throw_builtin" + } + }, + "display": { + "announce_to_chat": true, + "description": { + "color": "#DBA213", + "translate": "advancement.create.package_chute_throw.desc" + }, + "frame": "goal", + "hidden": true, + "icon": { + "item": "create:cardboard_package_12x12" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.package_chute_throw" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/packager.json b/src/generated/resources/data/create/advancements/packager.json new file mode 100644 index 0000000000..579a6700ba --- /dev/null +++ b/src/generated/resources/data/create/advancements/packager.json @@ -0,0 +1,31 @@ +{ + "parent": "create:cardboard", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:packager_builtin" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.create.packager.desc" + }, + "frame": "task", + "hidden": false, + "icon": { + "item": "create:packager" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.packager" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/bamboo_window.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/bamboo_window.json new file mode 100644 index 0000000000..486cef41ee --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/bamboo_window.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:bamboo_planks" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:bamboo_window" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:bamboo_window" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/bamboo_window_pane.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/bamboo_window_pane.json new file mode 100644 index 0000000000..246b3c6e95 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/bamboo_window_pane.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "create:bamboo_window" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:bamboo_window_pane" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:bamboo_window_pane" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cherry_window.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cherry_window.json new file mode 100644 index 0000000000..747782465e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/cherry_window.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:cherry_planks" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:cherry_window" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:cherry_window" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cherry_window_pane.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cherry_window_pane.json new file mode 100644 index 0000000000..b252e6f55e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/cherry_window_pane.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "create:cherry_window" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:cherry_window_pane" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:cherry_window_pane" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox.json new file mode 100644 index 0000000000..9455f284ae --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/black_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/black_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox_from_other_postbox.json new file mode 100644 index 0000000000..5770488593 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/black_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/black_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth.json new file mode 100644 index 0000000000..94e3684cf2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/black_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/black_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..b81c071e9f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/black_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/black_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/black_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox.json new file mode 100644 index 0000000000..323db16066 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/blue_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/blue_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox_from_other_postbox.json new file mode 100644 index 0000000000..8e6b664448 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/blue_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/blue_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth.json new file mode 100644 index 0000000000..4db03d9125 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/blue_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/blue_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..aff5b1901f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/blue_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/blue_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/blue_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox.json new file mode 100644 index 0000000000..d0004b543c --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/brown_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/brown_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox_from_other_postbox.json new file mode 100644 index 0000000000..44f4d27789 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/brown_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/brown_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth.json new file mode 100644 index 0000000000..32b6d59c26 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/brown_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/brown_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..f0c7562da4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/brown_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/brown_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/brown_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox.json new file mode 100644 index 0000000000..d75be5c56a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/cyan_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/cyan_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox_from_other_postbox.json new file mode 100644 index 0000000000..d0daebfd7b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/cyan_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/cyan_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth.json new file mode 100644 index 0000000000..e6158620b3 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/cyan_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/cyan_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..860ae51c90 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/cyan_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/cyan_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox.json new file mode 100644 index 0000000000..e0fe7da1e4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/gray_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/gray_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox_from_other_postbox.json new file mode 100644 index 0000000000..64b0408d25 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/gray_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/gray_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth.json new file mode 100644 index 0000000000..0d861b32fb --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/gray_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/gray_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..5b52243471 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/gray_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/gray_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/gray_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox.json new file mode 100644 index 0000000000..8a2872fd28 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/green_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/green_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox_from_other_postbox.json new file mode 100644 index 0000000000..d4a7136535 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/green_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/green_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth.json new file mode 100644 index 0000000000..45c71516a4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/green_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/green_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..d926c70dcd --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/green_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/green_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/green_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox.json new file mode 100644 index 0000000000..d8c8cddfaf --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_blue_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_blue_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox_from_other_postbox.json new file mode 100644 index 0000000000..617aa273b8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_blue_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_blue_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth.json new file mode 100644 index 0000000000..1572eb7842 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_blue_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_blue_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..816bd6116e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_blue_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_blue_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox.json new file mode 100644 index 0000000000..39666afab0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_gray_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_gray_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox_from_other_postbox.json new file mode 100644 index 0000000000..1e87b3ca98 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_gray_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_gray_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth.json new file mode 100644 index 0000000000..66b9b258a2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_gray_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_gray_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..4e7a9322c9 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_gray_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_gray_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox.json new file mode 100644 index 0000000000..9839e8cc00 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/lime_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/lime_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox_from_other_postbox.json new file mode 100644 index 0000000000..e0dcf1f083 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/lime_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/lime_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth.json new file mode 100644 index 0000000000..93d5783ed0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/lime_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/lime_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..60f3afa997 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/lime_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/lime_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/lime_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox.json new file mode 100644 index 0000000000..91a28b4532 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/magenta_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/magenta_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox_from_other_postbox.json new file mode 100644 index 0000000000..eac643a415 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/magenta_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/magenta_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth.json new file mode 100644 index 0000000000..10d4a9c9a1 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/magenta_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/magenta_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..8cb0ad152d --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/magenta_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/magenta_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox.json new file mode 100644 index 0000000000..ba16928747 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/orange_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/orange_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox_from_other_postbox.json new file mode 100644 index 0000000000..0e68c5682f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/orange_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/orange_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth.json new file mode 100644 index 0000000000..da4c9251a7 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/orange_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/orange_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..dadec6a3e2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/orange_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/orange_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/orange_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox.json new file mode 100644 index 0000000000..1287653c1c --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/pink_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/pink_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox_from_other_postbox.json new file mode 100644 index 0000000000..9f23ccc8a8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/pink_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/pink_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth.json new file mode 100644 index 0000000000..3ae9169d7f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/pink_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/pink_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..5b918b9d90 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/pink_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/pink_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/pink_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox.json new file mode 100644 index 0000000000..6de1c644bc --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/purple_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/purple_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox_from_other_postbox.json new file mode 100644 index 0000000000..47e29f4f00 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/purple_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/purple_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth.json new file mode 100644 index 0000000000..8bbf544db4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/purple_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/purple_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..bb546cec12 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/purple_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/purple_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/purple_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox.json new file mode 100644 index 0000000000..647c481081 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/red_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/red_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox_from_other_postbox.json new file mode 100644 index 0000000000..59feffbe43 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/red_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/red_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth.json new file mode 100644 index 0000000000..cb55224528 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/red_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/red_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..90203767fa --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/red_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/red_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/red_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox.json new file mode 100644 index 0000000000..8319328f74 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/white_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/white_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox_from_other_postbox.json new file mode 100644 index 0000000000..8cc0bb2ea7 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/white_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/white_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth.json new file mode 100644 index 0000000000..00424338b8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/white_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/white_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..ee94fc5f33 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/white_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/white_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/white_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox.json new file mode 100644 index 0000000000..1b04dd3c03 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_barrel": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:barrel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/yellow_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_barrel", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/yellow_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox_from_other_postbox.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox_from_other_postbox.json new file mode 100644 index 0000000000..d7ec15bf68 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_postbox_from_other_postbox.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:postboxes" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/yellow_postbox_from_other_postbox" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/yellow_postbox_from_other_postbox" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth.json new file mode 100644 index 0000000000..0eb1f4b163 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/yellow_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wool": { + "conditions": { + "items": [ + { + "tag": "minecraft:wool" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_wool", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/yellow_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..a0661931dc --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_postbox": { + "conditions": { + "items": [ + { + "tag": "create:dyed_table_cloths" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/yellow_table_cloth_from_other_table_cloth" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_postbox", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/yellow_table_cloth_from_other_table_cloth" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/framed_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/framed_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..115d3f96a6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/framed_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_glass_panes_colorless": { + "conditions": { + "items": [ + { + "tag": "forge:glass_panes/colorless" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:framed_glass_pane_from_glass_panes_colorless_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_glass_panes_colorless", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:framed_glass_pane_from_glass_panes_colorless_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..39a4c3970f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_glass_panes_colorless": { + "conditions": { + "items": [ + { + "tag": "forge:glass_panes/colorless" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_glass_panes_colorless", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_window.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_window.json new file mode 100644 index 0000000000..3374702a43 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_window.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "create:industrial_iron_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:industrial_iron_window" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:industrial_iron_window" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_window_pane.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_window_pane.json new file mode 100644 index 0000000000..190e8d4c53 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_window_pane.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "create:industrial_iron_window" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:industrial_iron_window_pane" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:industrial_iron_window_pane" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..3bdaf4c675 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_glass_panes_colorless": { + "conditions": { + "items": [ + { + "tag": "forge:glass_panes/colorless" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:tiled_glass_pane_from_glass_panes_colorless_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_glass_panes_colorless", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:tiled_glass_pane_from_glass_panes_colorless_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..db53e390e8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_glass_panes_colorless": { + "conditions": { + "items": [ + { + "tag": "forge:glass_panes/colorless" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_glass_panes_colorless", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_block_from_ingots_iron_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_block_from_ingots_iron_stonecutting.json new file mode 100644 index 0000000000..536e814bf9 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_block_from_ingots_iron_stonecutting.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_iron": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/iron" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:weathered_iron_block_from_ingots_iron_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_iron", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:weathered_iron_block_from_ingots_iron_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_window.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_window.json new file mode 100644 index 0000000000..b2d722cdbf --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_window.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "create:weathered_iron_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:weathered_iron_window" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:weathered_iron_window" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_window_pane.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_window_pane.json new file mode 100644 index 0000000000..9f5ea0d6b5 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/weathered_iron_window_pane.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "create:weathered_iron_window" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:weathered_iron_window_pane" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:weathered_iron_window_pane" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/andesite_table_cloth_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_table_cloth_from_andesite_alloy_stonecutting.json new file mode 100644 index 0000000000..cd9c833117 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_table_cloth_from_andesite_alloy_stonecutting.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_andesite_alloy": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:andesite_table_cloth_from_andesite_alloy_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_andesite_alloy", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:andesite_table_cloth_from_andesite_alloy_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/brass_table_cloth_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/brass_table_cloth_from_ingots_brass_stonecutting.json new file mode 100644 index 0000000000..476021814c --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/brass_table_cloth_from_ingots_brass_stonecutting.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_brass": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/brass" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:brass_table_cloth_from_ingots_brass_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_brass", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:brass_table_cloth_from_ingots_brass_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/copper_table_cloth_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/copper_table_cloth_from_ingots_copper_stonecutting.json new file mode 100644 index 0000000000..cc3060eda4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/copper_table_cloth_from_ingots_copper_stonecutting.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_copper": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/copper" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copper_table_cloth_from_ingots_copper_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_copper", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copper_table_cloth_from_ingots_copper_stonecutting" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/book.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/book.json new file mode 100644 index 0000000000..14def310be --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/book.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/book" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/book" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_boots.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_boots.json new file mode 100644 index 0000000000..a14e19dec9 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_boots.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/cardboard_boots" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/cardboard_boots" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_chestplate.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_chestplate.json new file mode 100644 index 0000000000..0d08a08398 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_chestplate.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/cardboard_chestplate" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/cardboard_chestplate" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_helmet.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_helmet.json new file mode 100644 index 0000000000..b5cb901f19 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_helmet.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/cardboard_helmet" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/cardboard_helmet" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_leggings.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_leggings.json new file mode 100644 index 0000000000..c2d20cf35e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_leggings.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/cardboard_leggings" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/cardboard_leggings" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_sword.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_sword.json new file mode 100644 index 0000000000..2a69134ba1 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/cardboard_sword.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/cardboard_sword" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/cardboard_sword" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/chain_from_zinc.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/chain_from_zinc.json new file mode 100644 index 0000000000..f4e6f1def5 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/chain_from_zinc.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/zinc" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/chain_from_zinc" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/chain_from_zinc" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/item_frame.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/item_frame.json new file mode 100644 index 0000000000..55277bc2bb --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/item_frame.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/item_frame" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/item_frame" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/name_tag.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/name_tag.json new file mode 100644 index 0000000000..034ad73f78 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/name_tag.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/name_tag" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/name_tag" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/package_filter_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/package_filter_clear.json new file mode 100644 index 0000000000..a7f5838c8e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/package_filter_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:package_filter" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/package_filter_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/package_filter_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/chain_conveyor.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/chain_conveyor.json new file mode 100644 index 0000000000..e794c42efa --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/chain_conveyor.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/chain_conveyor" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/chain_conveyor" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/encased_chain_drive_from_zinc.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/encased_chain_drive_from_zinc.json new file mode 100644 index 0000000000..0fecd4f33d --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/encased_chain_drive_from_zinc.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/encased_chain_drive_from_zinc" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/encased_chain_drive_from_zinc" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gearbox_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gearbox_from_conversion.json new file mode 100644 index 0000000000..e7aebadd26 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gearbox_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:vertical_gearbox" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/gearbox_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/gearbox_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gearboxfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gearboxfrom_conversion.json deleted file mode 100644 index 73608851b5..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gearboxfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:vertical_gearbox" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/gearboxfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/gearboxfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/linear_chassis_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/linear_chassis_from_conversion.json new file mode 100644 index 0000000000..360f8910b0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/linear_chassis_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:secondary_linear_chassis" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/linear_chassis_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/linear_chassis_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/linear_chassisfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/linear_chassisfrom_conversion.json deleted file mode 100644 index 852eeac204..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/linear_chassisfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:secondary_linear_chassis" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/linear_chassisfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/linear_chassisfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/package_filter.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/package_filter.json new file mode 100644 index 0000000000..77f4083f7a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/package_filter.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/zinc" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/package_filter" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/package_filter" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/sail_frame_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/sail_frame_from_conversion.json new file mode 100644 index 0000000000..ced30f9ffc --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/sail_frame_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:white_sail" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/sail_frame_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/sail_frame_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/sail_framefrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/sail_framefrom_conversion.json deleted file mode 100644 index 1cf800e0f5..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/sail_framefrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:white_sail" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/sail_framefrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/sail_framefrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassis_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassis_from_conversion.json new file mode 100644 index 0000000000..4422f2854a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassis_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:linear_chassis" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/secondary_linear_chassis_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/secondary_linear_chassis_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassisfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassisfrom_conversion.json deleted file mode 100644 index df18e75007..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/secondary_linear_chassisfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:linear_chassis" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/secondary_linear_chassisfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/secondary_linear_chassisfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/speedometer_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/speedometer_from_conversion.json new file mode 100644 index 0000000000..68452abb78 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/speedometer_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:stressometer" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/speedometer_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/speedometer_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/speedometerfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/speedometerfrom_conversion.json deleted file mode 100644 index 24b423c1dd..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/speedometerfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:stressometer" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/speedometerfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/speedometerfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/stressometer_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/stressometer_from_conversion.json new file mode 100644 index 0000000000..ad84b318c4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/stressometer_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:speedometer" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/stressometer_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/stressometer_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/stressometerfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/stressometerfrom_conversion.json deleted file mode 100644 index dbef87455c..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/stressometerfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:speedometer" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/stressometerfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/stressometerfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearbox_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearbox_from_conversion.json new file mode 100644 index 0000000000..4055ece96f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearbox_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:gearbox" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/vertical_gearbox_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/vertical_gearbox_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearboxfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearboxfrom_conversion.json deleted file mode 100644 index d83456a830..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearboxfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:gearbox" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/vertical_gearboxfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/vertical_gearboxfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_sail_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_sail_from_conversion.json new file mode 100644 index 0000000000..19c522ced9 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_sail_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:sail_frame" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/white_sail_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/white_sail_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_sailfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_sailfrom_conversion.json deleted file mode 100644 index 6d896ea997..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_sailfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:sail_frame" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/white_sailfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/white_sailfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/andesite_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/andesite_table_cloth_clear.json new file mode 100644 index 0000000000..fcd76c7616 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/andesite_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_andesite_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/andesite_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_andesite_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/andesite_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/black_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/black_table_cloth_clear.json new file mode 100644 index 0000000000..f03a28bf6a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/black_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_black_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:black_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/black_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_black_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/black_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/blue_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/blue_table_cloth_clear.json new file mode 100644 index 0000000000..4d22f1722c --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/blue_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_blue_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:blue_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/blue_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_blue_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/blue_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/brass_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/brass_table_cloth_clear.json new file mode 100644 index 0000000000..8ffcdd2bbc --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/brass_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_brass_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:brass_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/brass_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_brass_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/brass_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/brown_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/brown_table_cloth_clear.json new file mode 100644 index 0000000000..7f6b2e5b6a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/brown_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_brown_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:brown_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/brown_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_brown_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/brown_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/copper_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/copper_table_cloth_clear.json new file mode 100644 index 0000000000..79f4422a3a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/copper_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_copper_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:copper_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/copper_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_copper_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/copper_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/cyan_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/cyan_table_cloth_clear.json new file mode 100644 index 0000000000..685671db78 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/cyan_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cyan_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:cyan_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/cyan_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_cyan_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/cyan_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/desk_bell.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/desk_bell.json new file mode 100644 index 0000000000..368f5ce2f2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/desk_bell.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/desk_bell" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/desk_bell" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/factory_gauge.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/factory_gauge.json new file mode 100644 index 0000000000..09ad4ad72e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/factory_gauge.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:stock_link" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/factory_gauge" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/factory_gauge" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/factory_gauge_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/factory_gauge_clear.json new file mode 100644 index 0000000000..5df5d7367e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/factory_gauge_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:factory_gauge" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/factory_gauge_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/factory_gauge_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/gray_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/gray_table_cloth_clear.json new file mode 100644 index 0000000000..2f6efc30ad --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/gray_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_gray_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:gray_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/gray_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_gray_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/gray_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/green_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/green_table_cloth_clear.json new file mode 100644 index 0000000000..c073c21afa --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/green_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_green_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:green_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/green_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_green_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/green_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/item_hatch.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/item_hatch.json new file mode 100644 index 0000000000..a50e5e1ebf --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/item_hatch.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/item_hatch" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/item_hatch" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/light_blue_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/light_blue_table_cloth_clear.json new file mode 100644 index 0000000000..876ec3fde7 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/light_blue_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_light_blue_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:light_blue_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_blue_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_light_blue_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_blue_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/light_gray_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/light_gray_table_cloth_clear.json new file mode 100644 index 0000000000..ecd289800a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/light_gray_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_light_gray_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:light_gray_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/light_gray_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_light_gray_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/light_gray_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/lime_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/lime_table_cloth_clear.json new file mode 100644 index 0000000000..6b24da20fe --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/lime_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_lime_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:lime_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/lime_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_lime_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/lime_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/magenta_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/magenta_table_cloth_clear.json new file mode 100644 index 0000000000..219a3912b1 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/magenta_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_magenta_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:magenta_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/magenta_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_magenta_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/magenta_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/orange_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/orange_table_cloth_clear.json new file mode 100644 index 0000000000..1b274ecc83 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/orange_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_orange_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:orange_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/orange_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_orange_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/orange_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/package_frogport.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/package_frogport.json new file mode 100644 index 0000000000..c19e60c9c0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/package_frogport.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/package_frogport" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/package_frogport" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/packager.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/packager.json new file mode 100644 index 0000000000..e8489b071a --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/packager.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/packager" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/packager" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/packager_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/packager_from_conversion.json new file mode 100644 index 0000000000..b95f744e22 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/packager_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:repackager" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/packager_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/packager_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/pink_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/pink_table_cloth_clear.json new file mode 100644 index 0000000000..6c4e146467 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/pink_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_pink_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:pink_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/pink_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_pink_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/pink_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/pulse_timer.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/pulse_timer.json new file mode 100644 index 0000000000..4c373171a0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/pulse_timer.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "tag": "forge:dusts/redstone" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/pulse_timer" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/pulse_timer" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/purple_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/purple_table_cloth_clear.json new file mode 100644 index 0000000000..e96da828c8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/purple_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_purple_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:purple_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/purple_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_purple_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/purple_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/red_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/red_table_cloth_clear.json new file mode 100644 index 0000000000..00a7133594 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/red_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_red_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:red_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/red_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_red_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/red_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_link.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_link.json index 54b59c1b72..c58b11b6a0 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_link.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_link.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:brass_casing" + "create:andesite_casing" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_requester.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_requester.json new file mode 100644 index 0000000000..d493e3f614 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_requester.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/redstone_requester" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/redstone_requester" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_requester_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_requester_clear.json new file mode 100644 index 0000000000..80c24e25f2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/redstone_requester_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:redstone_requester" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/redstone_requester_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/redstone_requester_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/repackager_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/repackager_from_conversion.json new file mode 100644 index 0000000000..c7e40de1fc --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/repackager_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:packager" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/repackager_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/repackager_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_link.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_link.json new file mode 100644 index 0000000000..690e33a489 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_link.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/stock_link" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/stock_link" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_link_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_link_clear.json new file mode 100644 index 0000000000..1201d91963 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_link_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:stock_link" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/stock_link_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/stock_link_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_ticker.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_ticker.json new file mode 100644 index 0000000000..0e873c2ae6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_ticker.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/stock_ticker" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/stock_ticker" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_ticker_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_ticker_clear.json new file mode 100644 index 0000000000..fbdff1d2db --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stock_ticker_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:stock_ticker" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/stock_ticker_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/stock_ticker_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/white_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/white_table_cloth_clear.json new file mode 100644 index 0000000000..19d8524c68 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/white_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/white_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_white_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:white_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_white_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/white_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/yellow_table_cloth_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/yellow_table_cloth_clear.json new file mode 100644 index 0000000000..c2ed4252d2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/yellow_table_cloth_clear.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/yellow_table_cloth_clear" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_yellow_table_cloth": { + "conditions": { + "items": [ + { + "items": [ + "create:yellow_table_cloth" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_yellow_table_cloth", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/yellow_table_cloth_clear" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/bound_cardboard_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/bound_cardboard_block.json new file mode 100644 index 0000000000..be198645af --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/bound_cardboard_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/bound_cardboard_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/bound_cardboard_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_block.json new file mode 100644 index 0000000000..fc13ed8ccc --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/cardboard_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/cardboard_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_from_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_from_block.json new file mode 100644 index 0000000000..6585feb979 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_from_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/cardboard_from_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/cardboard_from_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_from_bound_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_from_bound_block.json new file mode 100644 index 0000000000..70c9f03dec --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/cardboard_from_bound_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:cardboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/cardboard_from_bound_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/cardboard_from_bound_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tiles_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tiles_from_conversion.json new file mode 100644 index 0000000000..512be36112 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tiles_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:small_rose_quartz_tiles" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/rose_quartz_tiles_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/rose_quartz_tiles_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tilesfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tilesfrom_conversion.json deleted file mode 100644 index a5e61d9c7c..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/rose_quartz_tilesfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:small_rose_quartz_tiles" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/materials/rose_quartz_tilesfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/materials/rose_quartz_tilesfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tiles_from_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tiles_from_conversion.json new file mode 100644 index 0000000000..0851dea3d6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tiles_from_conversion.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:rose_quartz_tiles" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/small_rose_quartz_tiles_from_conversion" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/small_rose_quartz_tiles_from_conversion" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tilesfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tilesfrom_conversion.json deleted file mode 100644 index aa32e8b300..0000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/small_rose_quartz_tilesfrom_conversion.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:rose_quartz_tiles" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/materials/small_rose_quartz_tilesfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/materials/small_rose_quartz_tilesfrom_conversion" - ] - }, - "sends_telemetry_event": false -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/transmitter.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/transmitter.json new file mode 100644 index 0000000000..62aad811a4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/transmitter.json @@ -0,0 +1,33 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/copper" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/transmitter" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/transmitter" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/stock_ticker.json b/src/generated/resources/data/create/advancements/stock_ticker.json new file mode 100644 index 0000000000..b90b292de1 --- /dev/null +++ b/src/generated/resources/data/create/advancements/stock_ticker.json @@ -0,0 +1,31 @@ +{ + "parent": "create:packager", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:stock_ticker_builtin" + } + }, + "display": { + "announce_to_chat": true, + "description": { + "color": "#DBA213", + "translate": "advancement.create.stock_ticker.desc" + }, + "frame": "task", + "hidden": false, + "icon": { + "item": "create:stock_ticker" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.stock_ticker" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/table_cloth_shop.json b/src/generated/resources/data/create/advancements/table_cloth_shop.json new file mode 100644 index 0000000000..ab6aa8fd1b --- /dev/null +++ b/src/generated/resources/data/create/advancements/table_cloth_shop.json @@ -0,0 +1,31 @@ +{ + "parent": "create:frogport", + "criteria": { + "0": { + "conditions": {}, + "trigger": "create:table_cloth_shop_builtin" + } + }, + "display": { + "announce_to_chat": true, + "description": { + "color": "#DBA213", + "translate": "advancement.create.table_cloth_shop.desc" + }, + "frame": "task", + "hidden": false, + "icon": { + "item": "create:red_table_cloth" + }, + "show_toast": true, + "title": { + "translate": "advancement.create.table_cloth_shop" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/train_casing_00.json b/src/generated/resources/data/create/advancements/train_casing_00.json index f7ede4fb0a..7c9fffe4c7 100644 --- a/src/generated/resources/data/create/advancements/train_casing_00.json +++ b/src/generated/resources/data/create/advancements/train_casing_00.json @@ -7,7 +7,7 @@ } }, "display": { - "announce_to_chat": true, + "announce_to_chat": false, "description": { "color": "#DBA213", "translate": "advancement.create.train_casing_00.desc" diff --git a/src/generated/resources/data/create/create/potato_projectile/type/apple.json b/src/generated/resources/data/create/create/potato_projectile/type/apple.json new file mode 100644 index 0000000000..f2ccca1d80 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/apple.json @@ -0,0 +1,10 @@ +{ + "damage": 5, + "items": "minecraft:apple", + "knockback": 0.5, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.1, + "velocity_multiplier": 1.45 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/baked_potato.json b/src/generated/resources/data/create/create/potato_projectile/type/baked_potato.json new file mode 100644 index 0000000000..fc4ac7dcdb --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/baked_potato.json @@ -0,0 +1,14 @@ +{ + "damage": 5, + "items": "minecraft:baked_potato", + "knockback": 0.5, + "pre_entity_hit": { + "type": "create:set_on_fire", + "ticks": 60 + }, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "velocity_multiplier": 1.25 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/beetroot.json b/src/generated/resources/data/create/create/potato_projectile/type/beetroot.json new file mode 100644 index 0000000000..973aa6bef4 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/beetroot.json @@ -0,0 +1,13 @@ +{ + "damage": 2, + "items": "minecraft:beetroot", + "knockback": 0.1, + "reload_ticks": 5, + "render_mode": { + "type": "create:toward_motion", + "spin": 2.0, + "sprite_angle_offset": 140 + }, + "sound_pitch": 1.6, + "velocity_multiplier": 1.6 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/blaze_cake.json b/src/generated/resources/data/create/create/potato_projectile/type/blaze_cake.json new file mode 100644 index 0000000000..825c465075 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/blaze_cake.json @@ -0,0 +1,15 @@ +{ + "damage": 15, + "items": "create:blaze_cake", + "knockback": 0.3, + "pre_entity_hit": { + "type": "create:set_on_fire", + "ticks": 240 + }, + "reload_ticks": 20, + "render_mode": { + "type": "create:tumble" + }, + "sticky": true, + "velocity_multiplier": 1.1 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/cake.json b/src/generated/resources/data/create/create/potato_projectile/type/cake.json new file mode 100644 index 0000000000..08abe4660c --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/cake.json @@ -0,0 +1,11 @@ +{ + "damage": 8, + "items": "minecraft:cake", + "knockback": 0.1, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "sticky": true, + "velocity_multiplier": 1.1 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/carrot.json b/src/generated/resources/data/create/create/potato_projectile/type/carrot.json new file mode 100644 index 0000000000..9d1c5db947 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/carrot.json @@ -0,0 +1,17 @@ +{ + "damage": 4, + "items": "minecraft:carrot", + "knockback": 0.3, + "on_block_hit": { + "type": "create:plant_crop", + "block": "minecraft:carrots" + }, + "reload_ticks": 12, + "render_mode": { + "type": "create:toward_motion", + "spin": 1.0, + "sprite_angle_offset": 140 + }, + "sound_pitch": 1.5, + "velocity_multiplier": 1.45 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/chocolate_berry.json b/src/generated/resources/data/create/create/potato_projectile/type/chocolate_berry.json new file mode 100644 index 0000000000..028bed0e85 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/chocolate_berry.json @@ -0,0 +1,11 @@ +{ + "damage": 4, + "items": "create:chocolate_glazed_berries", + "knockback": 0.2, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.25, + "split": 3, + "velocity_multiplier": 1.05 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/chorus_fruit.json b/src/generated/resources/data/create/create/potato_projectile/type/chorus_fruit.json new file mode 100644 index 0000000000..bba651329a --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/chorus_fruit.json @@ -0,0 +1,14 @@ +{ + "damage": 3, + "items": "minecraft:chorus_fruit", + "knockback": 0.05, + "on_entity_hit": { + "type": "create:chorus_teleport", + "teleport_diameter": 20.0 + }, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "velocity_multiplier": 1.2 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/enchanted_golden_apple.json b/src/generated/resources/data/create/create/potato_projectile/type/enchanted_golden_apple.json new file mode 100644 index 0000000000..d3ad360bf2 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/enchanted_golden_apple.json @@ -0,0 +1,51 @@ +{ + "items": "minecraft:enchanted_golden_apple", + "knockback": 0.05, + "on_entity_hit": { + "type": "create:food_effects", + "food_property": { + "can_always_eat": true, + "effects": [ + { + "effect": { + "amplifier": 1, + "duration": 400, + "effect": "minecraft:regeneration" + }, + "probability": 1.0 + }, + { + "effect": { + "duration": 6000, + "effect": "minecraft:resistance" + }, + "probability": 1.0 + }, + { + "effect": { + "duration": 6000, + "effect": "minecraft:fire_resistance" + }, + "probability": 1.0 + }, + { + "effect": { + "amplifier": 3, + "duration": 2400, + "effect": "minecraft:absorption" + }, + "probability": 1.0 + } + ], + "nutrition": 4, + "saturation_modifier": 1.2 + }, + "recoverable": false + }, + "reload_ticks": 100, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.1, + "velocity_multiplier": 1.45 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/fallback.json b/src/generated/resources/data/create/create/potato_projectile/type/fallback.json new file mode 100644 index 0000000000..c67cae4213 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/fallback.json @@ -0,0 +1,4 @@ +{ + "damage": 0, + "items": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/fish.json b/src/generated/resources/data/create/create/potato_projectile/type/fish.json new file mode 100644 index 0000000000..6a4a526b88 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/fish.json @@ -0,0 +1,19 @@ +{ + "damage": 4, + "items": [ + "minecraft:cod", + "minecraft:cooked_cod", + "minecraft:salmon", + "minecraft:cooked_salmon", + "minecraft:tropical_fish" + ], + "knockback": 0.6, + "render_mode": { + "type": "create:toward_motion", + "spin": 1.0, + "sprite_angle_offset": 140 + }, + "sound_pitch": 1.3, + "sticky": true, + "velocity_multiplier": 1.3 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/glistering_melon.json b/src/generated/resources/data/create/create/potato_projectile/type/glistering_melon.json new file mode 100644 index 0000000000..67ca2a18fb --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/glistering_melon.json @@ -0,0 +1,18 @@ +{ + "damage": 5, + "items": "minecraft:glistering_melon_slice", + "knockback": 0.1, + "on_entity_hit": { + "type": "create:potion_effect", + "effect": "minecraft:glowing", + "level": 1, + "recoverable": true, + "ticks": 100 + }, + "reload_ticks": 8, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.5, + "velocity_multiplier": 1.45 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/glow_berry.json b/src/generated/resources/data/create/create/potato_projectile/type/glow_berry.json new file mode 100644 index 0000000000..dfacc954b6 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/glow_berry.json @@ -0,0 +1,18 @@ +{ + "damage": 2, + "items": "minecraft:glow_berries", + "knockback": 0.05, + "on_entity_hit": { + "type": "create:potion_effect", + "effect": "minecraft:glowing", + "level": 1, + "recoverable": false, + "ticks": 200 + }, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.2, + "split": 2, + "velocity_multiplier": 1.05 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/golden_apple.json b/src/generated/resources/data/create/create/potato_projectile/type/golden_apple.json new file mode 100644 index 0000000000..d63dcc81aa --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/golden_apple.json @@ -0,0 +1,13 @@ +{ + "items": "minecraft:golden_apple", + "knockback": 0.05, + "on_entity_hit": { + "type": "create:cure_zombie_villager" + }, + "reload_ticks": 100, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.1, + "velocity_multiplier": 1.45 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/golden_carrot.json b/src/generated/resources/data/create/create/potato_projectile/type/golden_carrot.json new file mode 100644 index 0000000000..2c5f25450b --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/golden_carrot.json @@ -0,0 +1,13 @@ +{ + "damage": 12, + "items": "minecraft:golden_carrot", + "knockback": 0.5, + "reload_ticks": 15, + "render_mode": { + "type": "create:toward_motion", + "spin": 2.0, + "sprite_angle_offset": 140 + }, + "sound_pitch": 1.5, + "velocity_multiplier": 1.45 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/honeyed_apple.json b/src/generated/resources/data/create/create/potato_projectile/type/honeyed_apple.json new file mode 100644 index 0000000000..0e658c2187 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/honeyed_apple.json @@ -0,0 +1,18 @@ +{ + "damage": 6, + "items": "create:honeyed_apple", + "knockback": 0.1, + "on_entity_hit": { + "type": "create:potion_effect", + "effect": "minecraft:slowness", + "level": 2, + "recoverable": true, + "ticks": 160 + }, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.1, + "velocity_multiplier": 1.35 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/melon_block.json b/src/generated/resources/data/create/create/potato_projectile/type/melon_block.json new file mode 100644 index 0000000000..e3d3e9933f --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/melon_block.json @@ -0,0 +1,15 @@ +{ + "damage": 8, + "items": "minecraft:melon", + "knockback": 2.0, + "on_block_hit": { + "type": "create:place_block_on_ground", + "block": "minecraft:melon" + }, + "reload_ticks": 20, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 0.9, + "velocity_multiplier": 0.95 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/melon_slice.json b/src/generated/resources/data/create/create/potato_projectile/type/melon_slice.json new file mode 100644 index 0000000000..42caeeac39 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/melon_slice.json @@ -0,0 +1,11 @@ +{ + "damage": 3, + "items": "minecraft:melon_slice", + "knockback": 0.1, + "reload_ticks": 8, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.5, + "velocity_multiplier": 1.45 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/poison_potato.json b/src/generated/resources/data/create/create/potato_projectile/type/poison_potato.json new file mode 100644 index 0000000000..d34bfb8c06 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/poison_potato.json @@ -0,0 +1,17 @@ +{ + "damage": 5, + "items": "minecraft:poisonous_potato", + "knockback": 0.05, + "on_entity_hit": { + "type": "create:potion_effect", + "effect": "minecraft:poison", + "level": 1, + "recoverable": true, + "ticks": 160 + }, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "velocity_multiplier": 1.25 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/potato.json b/src/generated/resources/data/create/create/potato_projectile/type/potato.json new file mode 100644 index 0000000000..155802c5af --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/potato.json @@ -0,0 +1,14 @@ +{ + "damage": 5, + "items": "minecraft:potato", + "knockback": 1.5, + "on_block_hit": { + "type": "create:plant_crop", + "block": "minecraft:potatoes" + }, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "velocity_multiplier": 1.25 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/pufferfish.json b/src/generated/resources/data/create/create/potato_projectile/type/pufferfish.json new file mode 100644 index 0000000000..649c29daf9 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/pufferfish.json @@ -0,0 +1,46 @@ +{ + "damage": 4, + "items": "minecraft:pufferfish", + "knockback": 0.4, + "on_entity_hit": { + "type": "create:food_effects", + "food_property": { + "effects": [ + { + "effect": { + "amplifier": 1, + "duration": 1200, + "effect": "minecraft:poison" + }, + "probability": 1.0 + }, + { + "effect": { + "amplifier": 2, + "duration": 300, + "effect": "minecraft:hunger" + }, + "probability": 1.0 + }, + { + "effect": { + "duration": 300, + "effect": "minecraft:nausea" + }, + "probability": 1.0 + } + ], + "nutrition": 1, + "saturation_modifier": 0.1 + }, + "recoverable": false + }, + "render_mode": { + "type": "create:toward_motion", + "spin": 1.0, + "sprite_angle_offset": 140 + }, + "sound_pitch": 1.1, + "sticky": true, + "velocity_multiplier": 1.1 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/pumpkin_block.json b/src/generated/resources/data/create/create/potato_projectile/type/pumpkin_block.json new file mode 100644 index 0000000000..62edd912b9 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/pumpkin_block.json @@ -0,0 +1,15 @@ +{ + "damage": 6, + "items": "minecraft:pumpkin", + "knockback": 2.0, + "on_block_hit": { + "type": "create:place_block_on_ground", + "block": "minecraft:pumpkin" + }, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 0.9, + "velocity_multiplier": 0.95 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/pumpkin_pie.json b/src/generated/resources/data/create/create/potato_projectile/type/pumpkin_pie.json new file mode 100644 index 0000000000..9a92807e7a --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/pumpkin_pie.json @@ -0,0 +1,12 @@ +{ + "damage": 7, + "items": "minecraft:pumpkin_pie", + "knockback": 0.05, + "reload_ticks": 15, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.1, + "sticky": true, + "velocity_multiplier": 1.1 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/suspicious_stew.json b/src/generated/resources/data/create/create/potato_projectile/type/suspicious_stew.json new file mode 100644 index 0000000000..5fe3eed715 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/suspicious_stew.json @@ -0,0 +1,19 @@ +{ + "damage": 3, + "drop_stack": { + "Count": 1, + "id": "minecraft:bowl" + }, + "items": "minecraft:suspicious_stew", + "knockback": 0.2, + "on_entity_hit": { + "type": "create:suspicious_stew" + }, + "reload_ticks": 40, + "render_mode": { + "type": "create:toward_motion", + "spin": 1.0, + "sprite_angle_offset": 140 + }, + "velocity_multiplier": 0.8 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/sweet_berry.json b/src/generated/resources/data/create/create/potato_projectile/type/sweet_berry.json new file mode 100644 index 0000000000..d065288124 --- /dev/null +++ b/src/generated/resources/data/create/create/potato_projectile/type/sweet_berry.json @@ -0,0 +1,11 @@ +{ + "damage": 3, + "items": "minecraft:sweet_berries", + "knockback": 0.1, + "render_mode": { + "type": "create:tumble" + }, + "sound_pitch": 1.25, + "split": 3, + "velocity_multiplier": 1.05 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/andesite_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/andesite_table_cloth.json new file mode 100644 index 0000000000..d5dcbb5a9e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/andesite_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:andesite_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/andesite_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/bamboo_window.json b/src/generated/resources/data/create/loot_tables/blocks/bamboo_window.json new file mode 100644 index 0000000000..cd9311d3fe --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/bamboo_window.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:bamboo_window" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/bamboo_window" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/bamboo_window_pane.json b/src/generated/resources/data/create/loot_tables/blocks/bamboo_window_pane.json new file mode 100644 index 0000000000..02dbdcef1e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/bamboo_window_pane.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:bamboo_window_pane" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/bamboo_window_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/black_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/black_postbox.json new file mode 100644 index 0000000000..6392812530 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/black_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:black_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/black_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/black_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/black_table_cloth.json new file mode 100644 index 0000000000..bcfb49077d --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/black_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:black_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/black_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/blue_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/blue_postbox.json new file mode 100644 index 0000000000..14e3805b2a --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/blue_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:blue_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/blue_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/blue_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/blue_table_cloth.json new file mode 100644 index 0000000000..8d0aa383a8 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/blue_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:blue_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/blue_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/bound_cardboard_block.json b/src/generated/resources/data/create/loot_tables/blocks/bound_cardboard_block.json new file mode 100644 index 0000000000..e159395588 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/bound_cardboard_block.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:string" + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:cardboard_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/bound_cardboard_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brass_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/brass_table_cloth.json new file mode 100644 index 0000000000..28df84a681 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brass_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:brass_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/brass_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brown_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/brown_postbox.json new file mode 100644 index 0000000000..547a1f196d --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brown_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:brown_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/brown_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brown_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/brown_table_cloth.json new file mode 100644 index 0000000000..d8c66cdb82 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brown_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:brown_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/brown_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/cardboard_block.json b/src/generated/resources/data/create/loot_tables/blocks/cardboard_block.json new file mode 100644 index 0000000000..edd4a2520b --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/cardboard_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:cardboard_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/cardboard_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/chain_conveyor.json b/src/generated/resources/data/create/loot_tables/blocks/chain_conveyor.json new file mode 100644 index 0000000000..2f5a7f326e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/chain_conveyor.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:chain_conveyor" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/chain_conveyor" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/cherry_window.json b/src/generated/resources/data/create/loot_tables/blocks/cherry_window.json new file mode 100644 index 0000000000..4d2da071ce --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/cherry_window.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:cherry_window" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/cherry_window" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/cherry_window_pane.json b/src/generated/resources/data/create/loot_tables/blocks/cherry_window_pane.json new file mode 100644 index 0000000000..64438e0e08 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/cherry_window_pane.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:cherry_window_pane" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/cherry_window_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copper_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/copper_table_cloth.json new file mode 100644 index 0000000000..ce500397b5 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copper_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:copper_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/copper_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/cyan_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/cyan_postbox.json new file mode 100644 index 0000000000..5c7be1045d --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/cyan_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:cyan_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/cyan_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/cyan_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/cyan_table_cloth.json new file mode 100644 index 0000000000..f6214c3ff5 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/cyan_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:cyan_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/cyan_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/desk_bell.json b/src/generated/resources/data/create/loot_tables/blocks/desk_bell.json new file mode 100644 index 0000000000..baa0dfa9c3 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/desk_bell.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:desk_bell" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/desk_bell" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/factory_gauge.json b/src/generated/resources/data/create/loot_tables/blocks/factory_gauge.json new file mode 100644 index 0000000000..ea2899df42 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/factory_gauge.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:factory_gauge" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/factory_gauge" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/gray_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/gray_postbox.json new file mode 100644 index 0000000000..e262d34059 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/gray_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:gray_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/gray_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/gray_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/gray_table_cloth.json new file mode 100644 index 0000000000..9faaacff04 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/gray_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:gray_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/gray_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/green_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/green_postbox.json new file mode 100644 index 0000000000..e3dca64f6e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/green_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:green_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/green_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/green_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/green_table_cloth.json new file mode 100644 index 0000000000..e9cd8e03f0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/green_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:green_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/green_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_window.json b/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_window.json new file mode 100644 index 0000000000..17cb67c733 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_window.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:industrial_iron_window" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/industrial_iron_window" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_window_pane.json b/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_window_pane.json new file mode 100644 index 0000000000..83dfd8e361 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_window_pane.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:industrial_iron_window_pane" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/industrial_iron_window_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/item_hatch.json b/src/generated/resources/data/create/loot_tables/blocks/item_hatch.json new file mode 100644 index 0000000000..604fbaf760 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/item_hatch.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:item_hatch" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/item_hatch" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_blue_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/light_blue_postbox.json new file mode 100644 index 0000000000..5ce4a4eef2 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_blue_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:light_blue_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/light_blue_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_blue_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/light_blue_table_cloth.json new file mode 100644 index 0000000000..e8a961e43e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_blue_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:light_blue_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/light_blue_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_gray_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/light_gray_postbox.json new file mode 100644 index 0000000000..4efb6e6035 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_gray_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:light_gray_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/light_gray_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/light_gray_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/light_gray_table_cloth.json new file mode 100644 index 0000000000..0135623941 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/light_gray_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:light_gray_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/light_gray_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/lime_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/lime_postbox.json new file mode 100644 index 0000000000..578daeea8e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/lime_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:lime_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/lime_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/lime_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/lime_table_cloth.json new file mode 100644 index 0000000000..1270bdee85 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/lime_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:lime_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/lime_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/magenta_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/magenta_postbox.json new file mode 100644 index 0000000000..76e817a3b4 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/magenta_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:magenta_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/magenta_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/magenta_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/magenta_table_cloth.json new file mode 100644 index 0000000000..e75a70ea66 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/magenta_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:magenta_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/magenta_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/orange_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/orange_postbox.json new file mode 100644 index 0000000000..92a50f2d7c --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/orange_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:orange_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/orange_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/orange_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/orange_table_cloth.json new file mode 100644 index 0000000000..df88a6a9c0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/orange_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:orange_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/orange_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/package_frogport.json b/src/generated/resources/data/create/loot_tables/blocks/package_frogport.json new file mode 100644 index 0000000000..2ffb7daf2c --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/package_frogport.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:package_frogport" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/package_frogport" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/packager.json b/src/generated/resources/data/create/loot_tables/blocks/packager.json new file mode 100644 index 0000000000..d72df3d122 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/packager.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:packager" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/packager" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/pink_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/pink_postbox.json new file mode 100644 index 0000000000..2fa4ee3783 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/pink_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:pink_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/pink_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/pink_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/pink_table_cloth.json new file mode 100644 index 0000000000..dbd7471d90 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/pink_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:pink_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/pink_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/pulse_timer.json b/src/generated/resources/data/create/loot_tables/blocks/pulse_timer.json new file mode 100644 index 0000000000..fe56ca9642 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/pulse_timer.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:pulse_timer" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/pulse_timer" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/purple_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/purple_postbox.json new file mode 100644 index 0000000000..373fd05424 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/purple_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:purple_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/purple_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/purple_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/purple_table_cloth.json new file mode 100644 index 0000000000..87822b1e51 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/purple_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:purple_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/purple_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/red_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/red_postbox.json new file mode 100644 index 0000000000..30008f94ea --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/red_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:red_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/red_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/red_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/red_table_cloth.json new file mode 100644 index 0000000000..8132ffe194 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/red_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:red_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/red_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/redstone_requester.json b/src/generated/resources/data/create/loot_tables/blocks/redstone_requester.json new file mode 100644 index 0000000000..29fe85b8ec --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/redstone_requester.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:redstone_requester" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/redstone_requester" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/repackager.json b/src/generated/resources/data/create/loot_tables/blocks/repackager.json new file mode 100644 index 0000000000..b541c71ed8 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/repackager.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:repackager" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/repackager" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/stock_link.json b/src/generated/resources/data/create/loot_tables/blocks/stock_link.json new file mode 100644 index 0000000000..e41b77898f --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/stock_link.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:stock_link" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/stock_link" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/stock_ticker.json b/src/generated/resources/data/create/loot_tables/blocks/stock_ticker.json new file mode 100644 index 0000000000..033168cdcc --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/stock_ticker.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:stock_ticker" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/stock_ticker" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_block.json b/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_block.json new file mode 100644 index 0000000000..a17ac769e5 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:weathered_iron_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/weathered_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_window.json b/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_window.json new file mode 100644 index 0000000000..eacfb06c5e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_window.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:weathered_iron_window" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/weathered_iron_window" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_window_pane.json b/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_window_pane.json new file mode 100644 index 0000000000..59be15f4ad --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/weathered_iron_window_pane.json @@ -0,0 +1,31 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:weathered_iron_window_pane" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/weathered_iron_window_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/white_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/white_postbox.json new file mode 100644 index 0000000000..f5f6f92553 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/white_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:white_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/white_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/white_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/white_table_cloth.json new file mode 100644 index 0000000000..43d3518de4 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/white_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:white_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/white_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/yellow_postbox.json b/src/generated/resources/data/create/loot_tables/blocks/yellow_postbox.json new file mode 100644 index 0000000000..ffcf660c29 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/yellow_postbox.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:yellow_postbox" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/yellow_postbox" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/yellow_table_cloth.json b/src/generated/resources/data/create/loot_tables/blocks/yellow_table_cloth.json new file mode 100644 index 0000000000..e36894d645 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/yellow_table_cloth.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:yellow_table_cloth" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/yellow_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/andesite_table_cloth_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/recipes/andesite_table_cloth_from_andesite_alloy_stonecutting.json new file mode 100644 index 0000000000..01d9083f3e --- /dev/null +++ b/src/generated/resources/data/create/recipes/andesite_table_cloth_from_andesite_alloy_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "item": "create:andesite_alloy" + }, + "result": "create:andesite_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/bamboo_window.json b/src/generated/resources/data/create/recipes/bamboo_window.json new file mode 100644 index 0000000000..f88d802f5b --- /dev/null +++ b/src/generated/resources/data/create/recipes/bamboo_window.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "minecraft:bamboo_planks" + }, + "X": { + "tag": "forge:glass/colorless" + } + }, + "pattern": [ + " # ", + "#X#" + ], + "result": { + "count": 2, + "item": "create:bamboo_window" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/bamboo_window_pane.json b/src/generated/resources/data/create/recipes/bamboo_window_pane.json new file mode 100644 index 0000000000..3dd1289f99 --- /dev/null +++ b/src/generated/resources/data/create/recipes/bamboo_window_pane.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "create:bamboo_window" + } + }, + "pattern": [ + "###", + "###" + ], + "result": { + "count": 16, + "item": "create:bamboo_window_pane" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/brass_table_cloth_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/recipes/brass_table_cloth_from_ingots_brass_stonecutting.json new file mode 100644 index 0000000000..5953f95720 --- /dev/null +++ b/src/generated/resources/data/create/recipes/brass_table_cloth_from_ingots_brass_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/brass" + }, + "result": "create:brass_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cherry_window.json b/src/generated/resources/data/create/recipes/cherry_window.json new file mode 100644 index 0000000000..cbd29ee9c1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/cherry_window.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "minecraft:cherry_planks" + }, + "X": { + "tag": "forge:glass/colorless" + } + }, + "pattern": [ + " # ", + "#X#" + ], + "result": { + "count": 2, + "item": "create:cherry_window" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cherry_window_pane.json b/src/generated/resources/data/create/recipes/cherry_window_pane.json new file mode 100644 index 0000000000..a13694b665 --- /dev/null +++ b/src/generated/resources/data/create/recipes/cherry_window_pane.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "create:cherry_window" + } + }, + "pattern": [ + "###", + "###" + ], + "result": { + "count": 16, + "item": "create:cherry_window_pane" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_table_cloth_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_table_cloth_from_ingots_copper_stonecutting.json new file mode 100644 index 0000000000..868b7ddac8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/copper_table_cloth_from_ingots_copper_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/copper" + }, + "result": "create:copper_table_cloth" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/book.json b/src/generated/resources/data/create/recipes/crafting/appliances/book.json new file mode 100644 index 0000000000..be59b14cda --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/book.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:cardboard" + }, + { + "item": "minecraft:paper" + }, + { + "item": "minecraft:paper" + }, + { + "item": "minecraft:paper" + } + ], + "result": { + "item": "minecraft:book" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_boots.json b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_boots.json new file mode 100644 index 0000000000..89886731af --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_boots.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "P": { + "item": "create:cardboard" + } + }, + "pattern": [ + "P P", + "P P" + ], + "result": { + "item": "create:cardboard_boots" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_chestplate.json b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_chestplate.json new file mode 100644 index 0000000000..7a60c3c079 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_chestplate.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "P": { + "item": "create:cardboard" + } + }, + "pattern": [ + "P P", + "PPP", + "PPP" + ], + "result": { + "item": "create:cardboard_chestplate" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_helmet.json b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_helmet.json new file mode 100644 index 0000000000..c2e2046380 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_helmet.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "P": { + "item": "create:cardboard" + } + }, + "pattern": [ + "PPP", + "P P" + ], + "result": { + "item": "create:cardboard_helmet" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_leggings.json b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_leggings.json new file mode 100644 index 0000000000..e3ee002600 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_leggings.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "P": { + "item": "create:cardboard" + } + }, + "pattern": [ + "PPP", + "P P", + "P P" + ], + "result": { + "item": "create:cardboard_leggings" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_sword.json b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_sword.json new file mode 100644 index 0000000000..9bab6b2faa --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/cardboard_sword.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "P": { + "item": "create:cardboard" + }, + "S": { + "tag": "forge:rods/wooden" + } + }, + "pattern": [ + "P", + "P", + "S" + ], + "result": { + "item": "create:cardboard_sword" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/chain_from_zinc.json b/src/generated/resources/data/create/recipes/crafting/appliances/chain_from_zinc.json new file mode 100644 index 0000000000..5808314ab5 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/chain_from_zinc.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "C": { + "tag": "forge:ingots/zinc" + }, + "S": { + "tag": "forge:nuggets/zinc" + } + }, + "pattern": [ + "S", + "C", + "S" + ], + "result": { + "item": "minecraft:chain" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/item_frame.json b/src/generated/resources/data/create/recipes/crafting/appliances/item_frame.json new file mode 100644 index 0000000000..e1965b6aaf --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/item_frame.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "P": { + "item": "create:cardboard" + }, + "S": { + "tag": "forge:rods/wooden" + } + }, + "pattern": [ + "SSS", + "SPS", + "SSS" + ], + "result": { + "item": "minecraft:item_frame" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/name_tag.json b/src/generated/resources/data/create/recipes/crafting/appliances/name_tag.json new file mode 100644 index 0000000000..55d6978281 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/name_tag.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "forge:dyes/black" + }, + { + "tag": "forge:string" + }, + { + "item": "create:cardboard" + } + ], + "result": { + "item": "minecraft:name_tag" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/package_filter_clear.json b/src/generated/resources/data/create/recipes/crafting/appliances/package_filter_clear.json new file mode 100644 index 0000000000..84869a32f6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/package_filter_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:package_filter" + } + ], + "result": { + "item": "create:package_filter" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/curiosities/item_copying.json b/src/generated/resources/data/create/recipes/crafting/curiosities/item_copying.json new file mode 100644 index 0000000000..81fc0b7fd6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/curiosities/item_copying.json @@ -0,0 +1,4 @@ +{ + "type": "create:item_copying", + "category": "misc" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/chain_conveyor.json b/src/generated/resources/data/create/recipes/crafting/kinetics/chain_conveyor.json new file mode 100644 index 0000000000..2e3e3d9099 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/chain_conveyor.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "create:large_cogwheel" + }, + "C": { + "item": "create:andesite_casing" + } + }, + "pattern": [ + " C ", + "CAC", + " C " + ], + "result": { + "count": 2, + "item": "create:chain_conveyor" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/encased_chain_drive_from_zinc.json b/src/generated/resources/data/create/recipes/crafting/kinetics/encased_chain_drive_from_zinc.json new file mode 100644 index 0000000000..500568d052 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/encased_chain_drive_from_zinc.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:andesite_casing" + }, + { + "tag": "forge:nuggets/zinc" + }, + { + "tag": "forge:nuggets/zinc" + }, + { + "tag": "forge:nuggets/zinc" + } + ], + "result": { + "item": "create:encased_chain_drive" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/gearboxfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/gearbox_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/gearboxfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/gearbox_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/linear_chassisfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/linear_chassis_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/linear_chassisfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/linear_chassis_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/package_filter.json b/src/generated/resources/data/create/recipes/crafting/kinetics/package_filter.json new file mode 100644 index 0000000000..d87d953a39 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/package_filter.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "tag": "forge:nuggets/zinc" + }, + "S": { + "tag": "minecraft:wool" + } + }, + "pattern": [ + "ASA" + ], + "result": { + "item": "create:package_filter" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/sail_framefrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/sail_frame_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/sail_framefrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/sail_frame_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/secondary_linear_chassisfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/secondary_linear_chassis_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/secondary_linear_chassisfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/secondary_linear_chassis_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/speedometerfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/speedometer_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/speedometerfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/speedometer_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/stressometerfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/stressometer_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/stressometerfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/stressometer_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/vertical_gearboxfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/vertical_gearbox_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/vertical_gearboxfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/vertical_gearbox_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/white_sailfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/kinetics/white_sail_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/white_sailfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/white_sail_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/andesite_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/andesite_table_cloth_clear.json new file mode 100644 index 0000000000..b3464448a6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/andesite_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:andesite_table_cloth" + } + ], + "result": { + "item": "create:andesite_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/black_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/black_postbox.json new file mode 100644 index 0000000000..ffce897af1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/black_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/black" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:black_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/black_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/black_postbox_from_other_postbox.json new file mode 100644 index 0000000000..4f035cfc6a --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/black_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/black" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:black_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth.json new file mode 100644 index 0000000000..d38d7e9257 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:black_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:black_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth_clear.json new file mode 100644 index 0000000000..26f12a1e8f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:black_table_cloth" + } + ], + "result": { + "item": "create:black_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..cea95f2e43 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/black_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/black" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:black_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/blue_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/blue_postbox.json new file mode 100644 index 0000000000..761fa1d4bb --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/blue_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/blue" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:blue_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/blue_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/blue_postbox_from_other_postbox.json new file mode 100644 index 0000000000..4948ec4fb7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/blue_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/blue" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:blue_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth.json new file mode 100644 index 0000000000..93adf3511c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:blue_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:blue_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth_clear.json new file mode 100644 index 0000000000..9aa16db25f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:blue_table_cloth" + } + ], + "result": { + "item": "create:blue_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..0a3e3131b3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/blue_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/blue" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:blue_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/brass_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/brass_table_cloth_clear.json new file mode 100644 index 0000000000..2e472384a7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/brass_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:brass_table_cloth" + } + ], + "result": { + "item": "create:brass_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/brown_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/brown_postbox.json new file mode 100644 index 0000000000..4b99a08c94 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/brown_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/brown" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:brown_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/brown_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/brown_postbox_from_other_postbox.json new file mode 100644 index 0000000000..72a84beab9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/brown_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/brown" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:brown_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth.json new file mode 100644 index 0000000000..86519c9865 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:brown_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:brown_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth_clear.json new file mode 100644 index 0000000000..61788e6d84 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:brown_table_cloth" + } + ], + "result": { + "item": "create:brown_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..196afdd360 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/brown_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/brown" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:brown_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/copper_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/copper_table_cloth_clear.json new file mode 100644 index 0000000000..e2122b765e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/copper_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:copper_table_cloth" + } + ], + "result": { + "item": "create:copper_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/cyan_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_postbox.json new file mode 100644 index 0000000000..28e498e393 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/cyan" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:cyan_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/cyan_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_postbox_from_other_postbox.json new file mode 100644 index 0000000000..2d8f0948be --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/cyan" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:cyan_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth.json new file mode 100644 index 0000000000..fadf7feb36 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:cyan_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:cyan_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth_clear.json new file mode 100644 index 0000000000..b2944a9512 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:cyan_table_cloth" + } + ], + "result": { + "item": "create:cyan_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..15e0877f1d --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/cyan_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/cyan" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:cyan_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/desk_bell.json b/src/generated/resources/data/create/recipes/crafting/logistics/desk_bell.json new file mode 100644 index 0000000000..50dd659c6f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/desk_bell.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:andesite_casing" + }, + { + "tag": "forge:plates/gold" + } + ], + "result": { + "item": "create:desk_bell" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/display_link.json b/src/generated/resources/data/create/recipes/crafting/logistics/display_link.json index 9ee5795ace..66e5df6b98 100644 --- a/src/generated/resources/data/create/recipes/crafting/logistics/display_link.json +++ b/src/generated/resources/data/create/recipes/crafting/logistics/display_link.json @@ -2,11 +2,8 @@ "type": "minecraft:crafting_shaped", "category": "misc", "key": { - "A": { - "tag": "forge:plates/copper" - }, "C": { - "item": "minecraft:redstone_torch" + "item": "create:transmitter" }, "S": { "item": "create:brass_casing" @@ -14,8 +11,7 @@ }, "pattern": [ "C", - "S", - "A" + "S" ], "result": { "item": "create:display_link" diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/factory_gauge.json b/src/generated/resources/data/create/recipes/crafting/logistics/factory_gauge.json new file mode 100644 index 0000000000..3b322bb65a --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/factory_gauge.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:stock_link" + }, + { + "item": "create:precision_mechanism" + } + ], + "result": { + "count": 2, + "item": "create:factory_gauge" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/factory_gauge_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/factory_gauge_clear.json new file mode 100644 index 0000000000..256575f2b3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/factory_gauge_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:factory_gauge" + } + ], + "result": { + "item": "create:factory_gauge" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/gray_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/gray_postbox.json new file mode 100644 index 0000000000..6051a24b72 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/gray_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/gray" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:gray_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/gray_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/gray_postbox_from_other_postbox.json new file mode 100644 index 0000000000..a360c12759 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/gray_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/gray" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:gray_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth.json new file mode 100644 index 0000000000..86a484fe1c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:gray_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:gray_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth_clear.json new file mode 100644 index 0000000000..9142cc8fd8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:gray_table_cloth" + } + ], + "result": { + "item": "create:gray_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..ddb17f2877 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/gray_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/gray" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:gray_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/green_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/green_postbox.json new file mode 100644 index 0000000000..78610f80cf --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/green_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/green" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:green_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/green_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/green_postbox_from_other_postbox.json new file mode 100644 index 0000000000..2de4f3edc7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/green_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/green" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:green_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth.json new file mode 100644 index 0000000000..bf535b5f7e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:green_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:green_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth_clear.json new file mode 100644 index 0000000000..53926f8e5c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:green_table_cloth" + } + ], + "result": { + "item": "create:green_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..eade701d34 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/green_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/green" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:green_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/item_hatch.json b/src/generated/resources/data/create/recipes/crafting/logistics/item_hatch.json new file mode 100644 index 0000000000..e8551b281f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/item_hatch.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:andesite_alloy" + }, + { + "item": "minecraft:iron_trapdoor" + } + ], + "result": { + "item": "create:item_hatch" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_postbox.json new file mode 100644 index 0000000000..1f7dbded3e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/light_blue" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:light_blue_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_postbox_from_other_postbox.json new file mode 100644 index 0000000000..8873226dc6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/light_blue" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:light_blue_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth.json new file mode 100644 index 0000000000..c4724abc94 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:light_blue_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:light_blue_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth_clear.json new file mode 100644 index 0000000000..4bcc6e7636 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:light_blue_table_cloth" + } + ], + "result": { + "item": "create:light_blue_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..70f2f233ca --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_blue_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/light_blue" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:light_blue_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_postbox.json new file mode 100644 index 0000000000..7f6cd8b075 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/light_gray" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:light_gray_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_postbox_from_other_postbox.json new file mode 100644 index 0000000000..3c557a9de5 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/light_gray" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:light_gray_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth.json new file mode 100644 index 0000000000..6f661b8e5e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:light_gray_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:light_gray_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth_clear.json new file mode 100644 index 0000000000..1247175e3e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:light_gray_table_cloth" + } + ], + "result": { + "item": "create:light_gray_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..14bc7acf4a --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/light_gray_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/light_gray" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:light_gray_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/lime_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/lime_postbox.json new file mode 100644 index 0000000000..fcc3b9a8c1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/lime_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/lime" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:lime_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/lime_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/lime_postbox_from_other_postbox.json new file mode 100644 index 0000000000..0cf86b05f8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/lime_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/lime" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:lime_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth.json new file mode 100644 index 0000000000..1fc64203d4 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:lime_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:lime_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth_clear.json new file mode 100644 index 0000000000..c86168830f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:lime_table_cloth" + } + ], + "result": { + "item": "create:lime_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..9468e4d977 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/lime_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/lime" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:lime_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/magenta_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_postbox.json new file mode 100644 index 0000000000..42a7a90806 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/magenta" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:magenta_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/magenta_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_postbox_from_other_postbox.json new file mode 100644 index 0000000000..20b372938b --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/magenta" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:magenta_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth.json new file mode 100644 index 0000000000..d8a46169fd --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:magenta_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:magenta_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth_clear.json new file mode 100644 index 0000000000..b671d67f97 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:magenta_table_cloth" + } + ], + "result": { + "item": "create:magenta_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..74a693e884 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/magenta_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/magenta" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:magenta_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/orange_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/orange_postbox.json new file mode 100644 index 0000000000..9036d90c49 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/orange_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/orange" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:orange_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/orange_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/orange_postbox_from_other_postbox.json new file mode 100644 index 0000000000..0fad6790dd --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/orange_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/orange" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:orange_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth.json new file mode 100644 index 0000000000..87f85bc00c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:orange_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:orange_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth_clear.json new file mode 100644 index 0000000000..1d5b3419d9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:orange_table_cloth" + } + ], + "result": { + "item": "create:orange_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..3432a92c60 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/orange_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/orange" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:orange_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/package_frogport.json b/src/generated/resources/data/create/recipes/crafting/logistics/package_frogport.json new file mode 100644 index 0000000000..478d820f42 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/package_frogport.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "create:item_vault" + }, + "B": { + "tag": "forge:slimeballs" + }, + "C": { + "item": "create:andesite_alloy" + } + }, + "pattern": [ + "B", + "A", + "C" + ], + "result": { + "item": "create:package_frogport" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/packager.json b/src/generated/resources/data/create/recipes/crafting/logistics/packager.json new file mode 100644 index 0000000000..ded5731192 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/packager.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "create:cardboard_block" + }, + "C": { + "tag": "forge:ingots/iron" + }, + "R": { + "tag": "forge:dusts/redstone" + } + }, + "pattern": [ + " C ", + "CAC", + "RCR" + ], + "result": { + "item": "create:packager" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/packager_from_conversion.json b/src/generated/resources/data/create/recipes/crafting/logistics/packager_from_conversion.json new file mode 100644 index 0000000000..2d68d2e8f8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/packager_from_conversion.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:repackager" + } + ], + "result": { + "item": "create:packager" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/pink_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/pink_postbox.json new file mode 100644 index 0000000000..7a6dd0f2a9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/pink_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/pink" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:pink_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/pink_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/pink_postbox_from_other_postbox.json new file mode 100644 index 0000000000..5f406728fe --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/pink_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/pink" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:pink_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth.json new file mode 100644 index 0000000000..f7e3ca05c2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:pink_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:pink_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth_clear.json new file mode 100644 index 0000000000..9211cadc57 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:pink_table_cloth" + } + ], + "result": { + "item": "create:pink_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..28e6476ac5 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/pink_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/pink" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:pink_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/pulse_timer.json b/src/generated/resources/data/create/recipes/crafting/logistics/pulse_timer.json new file mode 100644 index 0000000000..6a49256b22 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/pulse_timer.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "C": { + "tag": "forge:plates/brass" + }, + "R": { + "item": "minecraft:amethyst_shard" + }, + "S": { + "tag": "forge:stone" + }, + "T": { + "item": "minecraft:redstone_torch" + } + }, + "pattern": [ + "RCT", + "SSS" + ], + "result": { + "item": "create:pulse_timer" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/purple_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/purple_postbox.json new file mode 100644 index 0000000000..27ea357ced --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/purple_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/purple" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:purple_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/purple_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/purple_postbox_from_other_postbox.json new file mode 100644 index 0000000000..29677aa06d --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/purple_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/purple" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:purple_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth.json new file mode 100644 index 0000000000..891011b6b9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:purple_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:purple_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth_clear.json new file mode 100644 index 0000000000..62a9651f69 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:purple_table_cloth" + } + ], + "result": { + "item": "create:purple_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..1bc8c9ef24 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/purple_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/purple" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:purple_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/red_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/red_postbox.json new file mode 100644 index 0000000000..dbb97a7020 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/red_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/red" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:red_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/red_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/red_postbox_from_other_postbox.json new file mode 100644 index 0000000000..8d36060325 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/red_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/red" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:red_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth.json new file mode 100644 index 0000000000..bdec39f0f4 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:red_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:red_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth_clear.json new file mode 100644 index 0000000000..cf50fc4af2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:red_table_cloth" + } + ], + "result": { + "item": "create:red_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..2ecc377857 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/red_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/red" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:red_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/redstone_link.json b/src/generated/resources/data/create/recipes/crafting/logistics/redstone_link.json index 6ec28f426c..b952b1dcd3 100644 --- a/src/generated/resources/data/create/recipes/crafting/logistics/redstone_link.json +++ b/src/generated/resources/data/create/recipes/crafting/logistics/redstone_link.json @@ -3,10 +3,10 @@ "category": "misc", "key": { "C": { - "item": "minecraft:redstone_torch" + "item": "create:transmitter" }, "S": { - "item": "create:brass_casing" + "item": "create:andesite_casing" } }, "pattern": [ diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/redstone_requester.json b/src/generated/resources/data/create/recipes/crafting/logistics/redstone_requester.json new file mode 100644 index 0000000000..d79d381032 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/redstone_requester.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "create:stock_link" + }, + "B": { + "tag": "forge:ingots/iron" + }, + "C": { + "tag": "forge:dusts/redstone" + } + }, + "pattern": [ + "C", + "A", + "B" + ], + "result": { + "item": "create:redstone_requester" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/redstone_requester_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/redstone_requester_clear.json new file mode 100644 index 0000000000..ac00a575b8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/redstone_requester_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:redstone_requester" + } + ], + "result": { + "item": "create:redstone_requester" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/repackager_from_conversion.json b/src/generated/resources/data/create/recipes/crafting/logistics/repackager_from_conversion.json new file mode 100644 index 0000000000..32d8ce6133 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/repackager_from_conversion.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:packager" + } + ], + "result": { + "item": "create:repackager" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/stock_link.json b/src/generated/resources/data/create/recipes/crafting/logistics/stock_link.json new file mode 100644 index 0000000000..cf862beb7c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/stock_link.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "B": { + "item": "create:item_vault" + }, + "C": { + "item": "create:transmitter" + } + }, + "pattern": [ + "C", + "B" + ], + "result": { + "item": "create:stock_link" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/stock_link_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/stock_link_clear.json new file mode 100644 index 0000000000..f527b6de23 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/stock_link_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:stock_link" + } + ], + "result": { + "item": "create:stock_link" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/stock_ticker.json b/src/generated/resources/data/create/recipes/crafting/logistics/stock_ticker.json new file mode 100644 index 0000000000..35c438462e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/stock_ticker.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "create:stock_link" + }, + "B": { + "tag": "forge:ingots/gold" + }, + "C": { + "tag": "forge:glass" + } + }, + "pattern": [ + "C", + "A", + "B" + ], + "result": { + "item": "create:stock_ticker" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/stock_ticker_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/stock_ticker_clear.json new file mode 100644 index 0000000000..cdd6dcb113 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/stock_ticker_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:stock_ticker" + } + ], + "result": { + "item": "create:stock_ticker" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/white_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/white_postbox.json new file mode 100644 index 0000000000..ffb9a6c2c7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/white_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/white" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:white_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/white_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/white_postbox_from_other_postbox.json new file mode 100644 index 0000000000..7467a76ef1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/white_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/white" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:white_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth.json new file mode 100644 index 0000000000..5371e1d780 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:white_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:white_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth_clear.json new file mode 100644 index 0000000000..64a1cbf4fc --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:white_table_cloth" + } + ], + "result": { + "item": "create:white_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..ad1f97dd6c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/white_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/white" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:white_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/yellow_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_postbox.json new file mode 100644 index 0000000000..658d8dc1c9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_postbox.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "B": { + "item": "minecraft:barrel" + }, + "D": { + "tag": "forge:dyes/yellow" + } + }, + "pattern": [ + "D", + "B", + "A" + ], + "result": { + "item": "create:yellow_postbox" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/yellow_postbox_from_other_postbox.json b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_postbox_from_other_postbox.json new file mode 100644 index 0000000000..1b3d6866bb --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_postbox_from_other_postbox.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/yellow" + }, + { + "tag": "create:postboxes" + } + ], + "result": { + "item": "create:yellow_postbox" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth.json new file mode 100644 index 0000000000..abe0aae4f1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "minecraft:yellow_wool" + }, + { + "item": "create:andesite_alloy" + } + ], + "result": { + "count": 2, + "item": "create:yellow_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth_clear.json b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth_clear.json new file mode 100644 index 0000000000..e8a2a99a0a --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:yellow_table_cloth" + } + ], + "result": { + "item": "create:yellow_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json new file mode 100644 index 0000000000..fcfeb4243b --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/yellow_table_cloth_from_other_table_cloth.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "tag": "forge:dyes/yellow" + }, + { + "tag": "create:dyed_table_cloths" + } + ], + "result": { + "item": "create:yellow_table_cloth" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/bound_cardboard_block.json b/src/generated/resources/data/create/recipes/crafting/materials/bound_cardboard_block.json new file mode 100644 index 0000000000..c3082c7c73 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/bound_cardboard_block.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:cardboard_block" + }, + { + "item": "minecraft:string" + } + ], + "result": { + "item": "create:bound_cardboard_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/cardboard_block.json b/src/generated/resources/data/create/recipes/crafting/materials/cardboard_block.json new file mode 100644 index 0000000000..1bc4b517f3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/cardboard_block.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "C": { + "item": "create:cardboard" + } + }, + "pattern": [ + "CC", + "CC" + ], + "result": { + "item": "create:cardboard_block" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/cardboard_from_block.json b/src/generated/resources/data/create/recipes/crafting/materials/cardboard_from_block.json new file mode 100644 index 0000000000..8a7ef79073 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/cardboard_from_block.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:cardboard_block" + } + ], + "result": { + "count": 4, + "item": "create:cardboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/cardboard_from_bound_block.json b/src/generated/resources/data/create/recipes/crafting/materials/cardboard_from_bound_block.json new file mode 100644 index 0000000000..b65f25e251 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/cardboard_from_bound_block.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:bound_cardboard_block" + } + ], + "result": { + "count": 4, + "item": "create:cardboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/rose_quartz_tilesfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/materials/rose_quartz_tiles_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/materials/rose_quartz_tilesfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/materials/rose_quartz_tiles_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/materials/small_rose_quartz_tilesfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/materials/small_rose_quartz_tiles_from_conversion.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/materials/small_rose_quartz_tilesfrom_conversion.json rename to src/generated/resources/data/create/recipes/crafting/materials/small_rose_quartz_tiles_from_conversion.json diff --git a/src/generated/resources/data/create/recipes/crafting/materials/transmitter.json b/src/generated/resources/data/create/recipes/crafting/materials/transmitter.json new file mode 100644 index 0000000000..773daf2aad --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/transmitter.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "L": { + "tag": "forge:plates/copper" + }, + "N": { + "item": "minecraft:lightning_rod" + }, + "R": { + "tag": "forge:dusts/redstone" + } + }, + "pattern": [ + " N ", + "LLL", + " R " + ], + "result": { + "item": "create:transmitter" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/coal_coke.json b/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/coal_coke.json new file mode 100644 index 0000000000..13bd0f682f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/coal_coke.json @@ -0,0 +1,20 @@ +{ + "type": "create:crushing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "immersiveengineering:coal_coke" + } + ], + "processingTime": 200, + "results": [ + { + "item": "immersiveengineering:dust_coke" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/coke_block.json b/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/coke_block.json new file mode 100644 index 0000000000..b20f9375c9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/coke_block.json @@ -0,0 +1,21 @@ +{ + "type": "create:crushing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "immersiveengineering:coke" + } + ], + "processingTime": 200, + "results": [ + { + "count": 9, + "item": "immersiveengineering:dust_coke" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/slag.json b/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/slag.json new file mode 100644 index 0000000000..bb6ea9091f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crushing/compat/immersiveengineering/slag.json @@ -0,0 +1,20 @@ +{ + "type": "create:crushing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "immersiveengineering:slag" + } + ], + "processingTime": 200, + "results": [ + { + "item": "immersiveengineering:slag_gravel" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/acacia_log.json b/src/generated/resources/data/create/recipes/cutting/acacia_log.json deleted file mode 100644 index 180bfe30a4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/acacia_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:acacia_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_acacia_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/acacia_wood.json b/src/generated/resources/data/create/recipes/cutting/acacia_wood.json deleted file mode 100644 index 1832e3b5f6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/acacia_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:acacia_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_acacia_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/birch_log.json b/src/generated/resources/data/create/recipes/cutting/birch_log.json deleted file mode 100644 index 9aae8a8c29..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/birch_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:birch_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_birch_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/birch_wood.json b/src/generated/resources/data/create/recipes/cutting/birch_wood.json deleted file mode 100644 index 727e50fefb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/birch_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:birch_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_birch_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/cherry_log.json b/src/generated/resources/data/create/recipes/cutting/cherry_log.json deleted file mode 100644 index d413e30679..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/cherry_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:cherry_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_cherry_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/cherry_wood.json b/src/generated/resources/data/create/recipes/cutting/cherry_wood.json deleted file mode 100644 index 373d7d143a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/cherry_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:cherry_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_cherry_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/stripped_twisted_log.json b/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/stripped_twisted_log.json deleted file mode 100644 index b956d8920e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/stripped_twisted_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "architects_palette" - } - ], - "ingredients": [ - { - "item": "architects_palette:stripped_twisted_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "architects_palette:twisted_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/stripped_twisted_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/stripped_twisted_wood.json deleted file mode 100644 index a4e1df53f8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/stripped_twisted_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "architects_palette" - } - ], - "ingredients": [ - { - "item": "architects_palette:stripped_twisted_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "architects_palette:twisted_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/twisted_log.json b/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/twisted_log.json deleted file mode 100644 index 154c98ca9c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/twisted_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "architects_palette" - } - ], - "ingredients": [ - { - "item": "architects_palette:twisted_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "architects_palette:stripped_twisted_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/twisted_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/twisted_wood.json deleted file mode 100644 index 039d74fdf7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/architects_palette/twisted_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "architects_palette" - } - ], - "ingredients": [ - { - "item": "architects_palette:twisted_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "architects_palette:stripped_twisted_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/aspen_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/aspen_log.json deleted file mode 100644 index 7373ae8e45..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/aspen_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:aspen_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_aspen_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/aspen_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/aspen_wood.json deleted file mode 100644 index 1d978775a1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/aspen_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:aspen_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_aspen_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/grimwood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/grimwood.json deleted file mode 100644 index 648d0a5535..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/grimwood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:grimwood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_grimwood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/grimwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/grimwood_log.json deleted file mode 100644 index e47ba69889..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/grimwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:grimwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_grimwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/kousa_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/kousa_log.json deleted file mode 100644 index aa56e9cb01..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/kousa_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:kousa_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_kousa_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/kousa_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/kousa_wood.json deleted file mode 100644 index 4958a4087d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/kousa_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:kousa_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_kousa_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/morado_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/morado_log.json deleted file mode 100644 index d10d4088bd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/morado_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:morado_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_morado_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/morado_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/morado_wood.json deleted file mode 100644 index 6747e0e199..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/morado_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:morado_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_morado_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/rosewood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/rosewood.json deleted file mode 100644 index 41ddadb916..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/rosewood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:rosewood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_rosewood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/rosewood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/rosewood_log.json deleted file mode 100644 index f68192b89f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/rosewood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:rosewood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_rosewood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_aspen_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_aspen_log.json deleted file mode 100644 index b43591e2ac..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_aspen_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_aspen_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:aspen_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_aspen_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_aspen_wood.json deleted file mode 100644 index 9c8566ead7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_aspen_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_aspen_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:aspen_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_grimwood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_grimwood.json deleted file mode 100644 index b9fbdc7e10..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_grimwood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_grimwood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:grimwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_grimwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_grimwood_log.json deleted file mode 100644 index 4724283d87..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_grimwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_grimwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:grimwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_kousa_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_kousa_log.json deleted file mode 100644 index 9c56af6677..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_kousa_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_kousa_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:kousa_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_kousa_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_kousa_wood.json deleted file mode 100644 index f6ea5c27bd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_kousa_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_kousa_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:kousa_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_morado_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_morado_log.json deleted file mode 100644 index 0dfb1cd985..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_morado_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_morado_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:morado_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_morado_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_morado_wood.json deleted file mode 100644 index 143a190419..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_morado_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_morado_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:morado_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_rosewood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_rosewood.json deleted file mode 100644 index 23de676707..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_rosewood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_rosewood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:rosewood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_rosewood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_rosewood_log.json deleted file mode 100644 index 10a905f8fa..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_rosewood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_rosewood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:rosewood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_yucca_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_yucca_log.json deleted file mode 100644 index 89f13128b2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_yucca_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_yucca_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:yucca_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_yucca_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_yucca_wood.json deleted file mode 100644 index 065d11f408..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/stripped_yucca_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:stripped_yucca_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "atmospheric:yucca_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/yucca_log.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/yucca_log.json deleted file mode 100644 index 4b247132bf..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/yucca_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:yucca_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_yucca_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/yucca_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/yucca_wood.json deleted file mode 100644 index 456bd0973d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/atmospheric/yucca_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "atmospheric" - } - ], - "ingredients": [ - { - "item": "atmospheric:yucca_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "atmospheric:stripped_yucca_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/autumnity/maple_log.json deleted file mode 100644 index 04a37d560d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/maple_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "autumnity" - } - ], - "ingredients": [ - { - "item": "autumnity:maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "autumnity:stripped_maple_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/autumnity/maple_wood.json deleted file mode 100644 index c62d6a50ae..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/maple_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "autumnity" - } - ], - "ingredients": [ - { - "item": "autumnity:maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "autumnity:stripped_maple_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/sappy_maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/autumnity/sappy_maple_log.json deleted file mode 100644 index c6e57a9317..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/sappy_maple_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "autumnity" - } - ], - "ingredients": [ - { - "item": "autumnity:sappy_maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "autumnity:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/sappy_maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/autumnity/sappy_maple_wood.json deleted file mode 100644 index 6986e9d7d9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/sappy_maple_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "autumnity" - } - ], - "ingredients": [ - { - "item": "autumnity:sappy_maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "autumnity:sappy_maple_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/stripped_maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/autumnity/stripped_maple_log.json deleted file mode 100644 index 1257ace064..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/stripped_maple_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "autumnity" - } - ], - "ingredients": [ - { - "item": "autumnity:stripped_maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "autumnity:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/stripped_maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/autumnity/stripped_maple_wood.json deleted file mode 100644 index d0b66d0db1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/autumnity/stripped_maple_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "autumnity" - } - ], - "ingredients": [ - { - "item": "autumnity:stripped_maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "autumnity:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/dead_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/dead_log.json deleted file mode 100644 index b3615b45f8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/dead_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:dead_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_dead_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/dead_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/dead_wood.json deleted file mode 100644 index 5022a39a5b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/dead_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:dead_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_dead_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/fir_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/fir_log.json deleted file mode 100644 index d7ee6f9959..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/fir_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:fir_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_fir_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/fir_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/fir_wood.json deleted file mode 100644 index 1848e65b5f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/fir_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:fir_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_fir_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/hellbark_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/hellbark_log.json deleted file mode 100644 index d5cbcd748f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/hellbark_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:hellbark_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_hellbark_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/hellbark_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/hellbark_wood.json deleted file mode 100644 index 4f38f736d2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/hellbark_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:hellbark_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_hellbark_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/jacaranda_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/jacaranda_log.json deleted file mode 100644 index 681a55c1e8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/jacaranda_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:jacaranda_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_jacaranda_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/jacaranda_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/jacaranda_wood.json deleted file mode 100644 index 23a4f5d343..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/jacaranda_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:jacaranda_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_jacaranda_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/magic_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/magic_log.json deleted file mode 100644 index 237abded87..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/magic_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:magic_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_magic_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/magic_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/magic_wood.json deleted file mode 100644 index 2528982b36..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/magic_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:magic_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_magic_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/mahogany_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/mahogany_log.json deleted file mode 100644 index 4a1e5deda5..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/mahogany_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:mahogany_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_mahogany_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/mahogany_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/mahogany_wood.json deleted file mode 100644 index 332666981b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/mahogany_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:mahogany_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_mahogany_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/palm_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/palm_log.json deleted file mode 100644 index 86fa921923..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/palm_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:palm_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_palm_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/palm_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/palm_wood.json deleted file mode 100644 index 39ffc171e9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/palm_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:palm_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_palm_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/redwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/redwood_log.json deleted file mode 100644 index 2c754fc51c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/redwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:redwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_redwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/redwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/redwood_wood.json deleted file mode 100644 index eaa8ac592c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/redwood_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:redwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_redwood_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_log.json deleted file mode 100644 index 90ebc73a61..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_dead_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:dead_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_wood.json deleted file mode 100644 index 1493e8265e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_dead_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_dead_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:dead_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_log.json deleted file mode 100644 index 10c5538977..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_fir_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:fir_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_wood.json deleted file mode 100644 index 8c6b76bdea..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_fir_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_fir_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:fir_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_log.json deleted file mode 100644 index 1c44191003..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_hellbark_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:hellbark_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_wood.json deleted file mode 100644 index 75a5356c84..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_hellbark_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_hellbark_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:hellbark_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_log.json deleted file mode 100644 index 32c8fc6868..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_jacaranda_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:jacaranda_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_wood.json deleted file mode 100644 index 279204ec72..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_jacaranda_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_jacaranda_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:jacaranda_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_log.json deleted file mode 100644 index 26618e2932..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_magic_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:magic_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_wood.json deleted file mode 100644 index 10f02907cf..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_magic_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_magic_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:magic_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_log.json deleted file mode 100644 index 39bcfc2e7e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_mahogany_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:mahogany_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_wood.json deleted file mode 100644 index 5a9a5c86fb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_mahogany_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_mahogany_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:mahogany_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_log.json deleted file mode 100644 index cde979e13d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_palm_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:palm_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_wood.json deleted file mode 100644 index 8b13809543..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_palm_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_palm_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:palm_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_log.json deleted file mode 100644 index 8536b80e8a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_redwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:redwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_wood.json deleted file mode 100644 index dd6241be57..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_redwood_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_redwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:redwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_log.json deleted file mode 100644 index c5f63f05bb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_umbran_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:umbran_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_wood.json deleted file mode 100644 index 9aca280726..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_umbran_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_umbran_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:umbran_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_log.json deleted file mode 100644 index b192aebc2f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_wood.json deleted file mode 100644 index eef0c2313a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/stripped_willow_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:stripped_willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "biomesoplenty:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/umbran_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/umbran_log.json deleted file mode 100644 index a02692be37..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/umbran_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:umbran_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_umbran_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/umbran_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/umbran_wood.json deleted file mode 100644 index 629bce7c5d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/umbran_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:umbran_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_umbran_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/willow_log.json deleted file mode 100644 index 38ee3bc682..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/willow_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_willow_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/willow_wood.json deleted file mode 100644 index 2bcf4650cb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/biomesoplenty/willow_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "biomesoplenty" - } - ], - "ingredients": [ - { - "item": "biomesoplenty:willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "biomesoplenty:stripped_willow_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/bluebright_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/bluebright_log.json deleted file mode 100644 index 5b531994e4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/bluebright_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:bluebright_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_bluebright_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/bluebright_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/bluebright_wood.json deleted file mode 100644 index e8bc9e7954..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/bluebright_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:bluebright_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_bluebright_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/crystallized_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/crystallized_log.json deleted file mode 100644 index 64e4db8f5f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/crystallized_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:crystallized_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:crystallized_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/crystallized_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/crystallized_wood.json deleted file mode 100644 index 96d0e1b032..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/crystallized_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:crystallized_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:crystallized_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/dusk_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/dusk_log.json deleted file mode 100644 index 5cac874ea5..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/dusk_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:dusk_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_dusk_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/dusk_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/dusk_wood.json deleted file mode 100644 index 480fa95760..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/dusk_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:dusk_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_dusk_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/frostbright_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/frostbright_log.json deleted file mode 100644 index 949c81e6d8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/frostbright_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:frostbright_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_frostbright_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/frostbright_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/frostbright_wood.json deleted file mode 100644 index 644b93ef58..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/frostbright_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:frostbright_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_frostbright_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/lunar_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/lunar_log.json deleted file mode 100644 index d592df227e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/lunar_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:lunar_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_lunar_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/lunar_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/lunar_wood.json deleted file mode 100644 index 2f0771e71a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/lunar_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:lunar_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_lunar_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/maple_log.json deleted file mode 100644 index 2e81668852..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/maple_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_maple_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/maple_wood.json deleted file mode 100644 index b1121cd1f8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/maple_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_maple_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/starlit_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/starlit_log.json deleted file mode 100644 index 886c89a38c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/starlit_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:starlit_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_starlit_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/starlit_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/starlit_wood.json deleted file mode 100644 index 1e46281116..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/starlit_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:starlit_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "blue_skies:stripped_starlit_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_log.json deleted file mode 100644 index 4af14fe8dd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_bluebright_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:bluebright_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_wood.json deleted file mode 100644 index 55e85cbbc6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_bluebright_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_bluebright_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:bluebright_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_dusk_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_dusk_log.json deleted file mode 100644 index dce73b8958..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_dusk_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_dusk_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:dusk_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_dusk_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_dusk_wood.json deleted file mode 100644 index 39f1907122..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_dusk_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_dusk_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:dusk_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_log.json deleted file mode 100644 index 94bedaf647..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_frostbright_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:frostbright_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_wood.json deleted file mode 100644 index 0b04be828a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_frostbright_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_frostbright_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:frostbright_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_lunar_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_lunar_log.json deleted file mode 100644 index 84520fdc31..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_lunar_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_lunar_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:lunar_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_lunar_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_lunar_wood.json deleted file mode 100644 index 06dd123880..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_lunar_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_lunar_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:lunar_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_maple_log.json deleted file mode 100644 index 6f9b9b8165..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_maple_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_maple_wood.json deleted file mode 100644 index fecc4dd4f6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_maple_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_starlit_log.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_starlit_log.json deleted file mode 100644 index e56362453d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_starlit_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_starlit_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:starlit_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_starlit_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_starlit_wood.json deleted file mode 100644 index 36fad622f9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/blue_skies/stripped_starlit_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "blue_skies" - } - ], - "ingredients": [ - { - "item": "blue_skies:stripped_starlit_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "blue_skies:starlit_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/dreamwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/dreamwood.json deleted file mode 100644 index 5615d862ff..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/dreamwood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:dreamwood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:stripped_dreamwood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/dreamwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/dreamwood_log.json deleted file mode 100644 index d58105eaf1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/dreamwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:dreamwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:stripped_dreamwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_dreamwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_dreamwood.json deleted file mode 100644 index 7a56cc7992..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_dreamwood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_dreamwood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:glimmering_stripped_dreamwood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_dreamwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_dreamwood_log.json deleted file mode 100644 index 62b83d4bb2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_dreamwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_dreamwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:glimmering_stripped_dreamwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_livingwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_livingwood.json deleted file mode 100644 index 175d5c86f0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_livingwood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_livingwood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:glimmering_stripped_livingwood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_livingwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_livingwood_log.json deleted file mode 100644 index 406e393eae..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_livingwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_livingwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:glimmering_stripped_livingwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood.json deleted file mode 100644 index d3820d7ac1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_stripped_dreamwood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:dreamwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood_log.json deleted file mode 100644 index 3dc8ea13c5..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_dreamwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_stripped_dreamwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:dreamwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood.json deleted file mode 100644 index 8b89443935..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_stripped_livingwood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:livingwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood_log.json deleted file mode 100644 index de57b7c843..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/glimmering_stripped_livingwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:glimmering_stripped_livingwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:livingwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/livingwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/livingwood.json deleted file mode 100644 index 9b82792484..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/livingwood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:livingwood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:stripped_livingwood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/livingwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/livingwood_log.json deleted file mode 100644 index 485759f46c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/livingwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:livingwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "botania:stripped_livingwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_dreamwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_dreamwood.json deleted file mode 100644 index 954b1f5c7f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_dreamwood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:stripped_dreamwood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:dreamwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_dreamwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_dreamwood_log.json deleted file mode 100644 index de771deef9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_dreamwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:stripped_dreamwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:dreamwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_livingwood.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_livingwood.json deleted file mode 100644 index 78bf75fe6b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_livingwood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:stripped_livingwood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:livingwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_livingwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_livingwood_log.json deleted file mode 100644 index 91539af7b8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/botania/stripped_livingwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "botania" - } - ], - "ingredients": [ - { - "item": "botania:stripped_livingwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "botania:livingwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/aspen_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/aspen_log.json deleted file mode 100644 index 38ac271757..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/aspen_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:aspen_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_aspen_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/aspen_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/aspen_wood.json deleted file mode 100644 index bb8419cec5..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/aspen_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:aspen_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_aspen_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/baobab_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/baobab_log.json deleted file mode 100644 index e4a71eebaf..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/baobab_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:baobab_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_baobab_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/baobab_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/baobab_wood.json deleted file mode 100644 index bcac7e7d99..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/baobab_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:baobab_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_baobab_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/blue_enchanted_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/blue_enchanted_log.json deleted file mode 100644 index d5b4776223..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/blue_enchanted_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:blue_enchanted_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_blue_enchanted_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/blue_enchanted_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/blue_enchanted_wood.json deleted file mode 100644 index d6b369036c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/blue_enchanted_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:blue_enchanted_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_blue_enchanted_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/bulbis_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/bulbis_stem.json deleted file mode 100644 index 9d95a5c010..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/bulbis_stem.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:bulbis_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_bulbis_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/bulbis_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/bulbis_wood.json deleted file mode 100644 index 349a4f7fb6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/bulbis_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:bulbis_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_bulbis_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/cika_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/cika_log.json deleted file mode 100644 index f6f2a625f1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/cika_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:cika_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_cika_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/cika_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/cika_wood.json deleted file mode 100644 index d41bf162b8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/cika_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:cika_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_cika_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/cypress_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/cypress_log.json deleted file mode 100644 index 726a5aabf3..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/cypress_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:cypress_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_cypress_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/cypress_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/cypress_wood.json deleted file mode 100644 index e9a187c885..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/cypress_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:cypress_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_cypress_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/ebony_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/ebony_log.json deleted file mode 100644 index c06c7f964e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/ebony_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:ebony_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_ebony_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/ebony_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/ebony_wood.json deleted file mode 100644 index 8e7e009132..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/ebony_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:ebony_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_ebony_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/ether_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/ether_log.json deleted file mode 100644 index 3bc2e1565d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/ether_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:ether_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_ether_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/ether_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/ether_wood.json deleted file mode 100644 index 7dfcdc18d0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/ether_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:ether_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_ether_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/fir_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/fir_log.json deleted file mode 100644 index 212d415c72..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/fir_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:fir_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_fir_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/fir_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/fir_wood.json deleted file mode 100644 index d93e8c277e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/fir_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:fir_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_fir_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/fungal_imparius_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/fungal_imparius_hyphae.json deleted file mode 100644 index 38220ef5b6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/fungal_imparius_hyphae.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:fungal_imparius_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:imparius_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/fungal_imparius_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/fungal_imparius_stem.json deleted file mode 100644 index 20e12e1c39..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/fungal_imparius_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:fungal_imparius_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:imparius_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/green_enchanted_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/green_enchanted_log.json deleted file mode 100644 index 2d6e1749e0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/green_enchanted_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:green_enchanted_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_green_enchanted_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/green_enchanted_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/green_enchanted_wood.json deleted file mode 100644 index 855cc1bb52..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/green_enchanted_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:green_enchanted_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_green_enchanted_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/holly_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/holly_log.json deleted file mode 100644 index d0ecaf51d0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/holly_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:holly_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_holly_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/holly_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/holly_wood.json deleted file mode 100644 index 1192769b2d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/holly_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:holly_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_holly_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/imparius_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/imparius_hyphae.json deleted file mode 100644 index 07d330aad6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/imparius_hyphae.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:imparius_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:imparius_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/imparius_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/imparius_stem.json deleted file mode 100644 index 702991b5ef..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/imparius_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:imparius_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:imparius_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/jacaranda_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/jacaranda_log.json deleted file mode 100644 index 4a4277f7be..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/jacaranda_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:jacaranda_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_jacaranda_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/jacaranda_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/jacaranda_wood.json deleted file mode 100644 index c59c82607d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/jacaranda_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:jacaranda_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_jacaranda_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/lament_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/lament_log.json deleted file mode 100644 index d1e9771136..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/lament_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:lament_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_lament_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/lament_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/lament_wood.json deleted file mode 100644 index 42e55d2b90..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/lament_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:lament_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_lament_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/mahogany_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/mahogany_log.json deleted file mode 100644 index cc6480a7d2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/mahogany_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:mahogany_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_mahogany_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/mahogany_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/mahogany_wood.json deleted file mode 100644 index 1b0a2777fe..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/mahogany_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:mahogany_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_mahogany_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/maple_log.json deleted file mode 100644 index cd46fac058..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/maple_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_maple_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/maple_wood.json deleted file mode 100644 index 19a873bd25..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/maple_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_maple_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/nightshade_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/nightshade_log.json deleted file mode 100644 index 6678c7b053..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/nightshade_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:nightshade_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_nightshade_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/nightshade_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/nightshade_wood.json deleted file mode 100644 index 1e1525a9d4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/nightshade_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:nightshade_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_nightshade_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/palm_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/palm_log.json deleted file mode 100644 index 6f7181eb3a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/palm_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:palm_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_palm_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/palm_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/palm_wood.json deleted file mode 100644 index f4b764e06c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/palm_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:palm_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_palm_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/palo_verde_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/palo_verde_log.json deleted file mode 100644 index 6e1efc0fe3..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/palo_verde_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:palo_verde_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_palo_verde_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/palo_verde_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/palo_verde_wood.json deleted file mode 100644 index fba40199c8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/palo_verde_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:palo_verde_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_palo_verde_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/pine_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/pine_log.json deleted file mode 100644 index e61d51c101..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/pine_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:pine_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_pine_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/pine_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/pine_wood.json deleted file mode 100644 index ba190ecff0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/pine_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:pine_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_pine_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_log.json deleted file mode 100644 index 0af3ef3709..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:rainbow_eucalyptus_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_rainbow_eucalyptus_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_wood.json deleted file mode 100644 index 60c72f3302..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/rainbow_eucalyptus_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:rainbow_eucalyptus_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_rainbow_eucalyptus_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/redwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/redwood_log.json deleted file mode 100644 index 8bdf07ae92..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/redwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:redwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_redwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/redwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/redwood_wood.json deleted file mode 100644 index c7235f1262..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/redwood_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:redwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_redwood_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/skyris_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/skyris_log.json deleted file mode 100644 index d1f37be95e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/skyris_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:skyris_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_skyris_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/skyris_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/skyris_wood.json deleted file mode 100644 index 473946580b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/skyris_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:skyris_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_skyris_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_aspen_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_aspen_log.json deleted file mode 100644 index cca3ab802c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_aspen_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_aspen_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:aspen_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_aspen_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_aspen_wood.json deleted file mode 100644 index b2f679fac0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_aspen_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_aspen_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:aspen_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_baobab_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_baobab_log.json deleted file mode 100644 index ffc8c1dcbb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_baobab_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_baobab_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:baobab_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_baobab_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_baobab_wood.json deleted file mode 100644 index 3eb03b0d6f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_baobab_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_baobab_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:baobab_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_log.json deleted file mode 100644 index f91b3c6df7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_blue_enchanted_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:blue_enchanted_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_wood.json deleted file mode 100644 index 2c1450fa94..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_blue_enchanted_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_blue_enchanted_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:blue_enchanted_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_bulbis_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_bulbis_stem.json deleted file mode 100644 index 4336a89882..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_bulbis_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_bulbis_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:bulbis_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_bulbis_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_bulbis_wood.json deleted file mode 100644 index 8a9856965b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_bulbis_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_bulbis_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:bulbis_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cika_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cika_log.json deleted file mode 100644 index 56d5314433..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cika_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_cika_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:cika_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cika_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cika_wood.json deleted file mode 100644 index b17ca3f5c0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cika_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_cika_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:cika_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cypress_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cypress_log.json deleted file mode 100644 index b9c88f7000..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cypress_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_cypress_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:cypress_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cypress_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cypress_wood.json deleted file mode 100644 index 9682334294..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_cypress_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_cypress_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:cypress_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ebony_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ebony_log.json deleted file mode 100644 index 0b858bc86d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ebony_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_ebony_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:ebony_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ebony_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ebony_wood.json deleted file mode 100644 index 89c855237f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ebony_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_ebony_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:ebony_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ether_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ether_log.json deleted file mode 100644 index d934c094ad..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ether_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_ether_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:ether_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ether_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ether_wood.json deleted file mode 100644 index c1a7142073..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_ether_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_ether_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:ether_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_fir_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_fir_log.json deleted file mode 100644 index fef32165d5..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_fir_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_fir_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:fir_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_fir_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_fir_wood.json deleted file mode 100644 index d16eede3b9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_fir_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_fir_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:fir_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_green_enchanted_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_green_enchanted_log.json deleted file mode 100644 index f6dfcd2bb4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_green_enchanted_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_green_enchanted_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:green_enchanted_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_green_enchanted_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_green_enchanted_wood.json deleted file mode 100644 index c9d6a595f6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_green_enchanted_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_green_enchanted_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:green_enchanted_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_holly_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_holly_log.json deleted file mode 100644 index fcd99fa620..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_holly_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_holly_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:holly_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_holly_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_holly_wood.json deleted file mode 100644 index 5ee1551cd7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_holly_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_holly_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:holly_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_jacaranda_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_jacaranda_log.json deleted file mode 100644 index 902745e370..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_jacaranda_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_jacaranda_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:jacaranda_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_jacaranda_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_jacaranda_wood.json deleted file mode 100644 index 4b8ba0caeb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_jacaranda_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_jacaranda_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:jacaranda_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_lament_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_lament_log.json deleted file mode 100644 index 6ef18abe89..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_lament_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_lament_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:lament_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_lament_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_lament_wood.json deleted file mode 100644 index 4dee034e15..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_lament_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_lament_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:lament_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mahogany_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mahogany_log.json deleted file mode 100644 index 2c9b10a420..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mahogany_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_mahogany_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:mahogany_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mahogany_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mahogany_wood.json deleted file mode 100644 index c07aa2a49b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mahogany_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_mahogany_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:mahogany_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_maple_log.json deleted file mode 100644 index e6110edcf7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_maple_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_maple_wood.json deleted file mode 100644 index c5ba863802..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_maple_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_nightshade_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_nightshade_log.json deleted file mode 100644 index d059a6709b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_nightshade_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_nightshade_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:nightshade_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_nightshade_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_nightshade_wood.json deleted file mode 100644 index 2f6e73d19b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_nightshade_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_nightshade_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:nightshade_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_palm_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_palm_log.json deleted file mode 100644 index 2127276be4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_palm_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_palm_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:palm_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_palm_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_palm_wood.json deleted file mode 100644 index c290027927..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_palm_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_palm_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:palm_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_pine_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_pine_log.json deleted file mode 100644 index e513a123de..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_pine_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_pine_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:pine_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_pine_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_pine_wood.json deleted file mode 100644 index fb67fe0cd7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_pine_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_pine_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:pine_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_log.json deleted file mode 100644 index dd69ef7b0c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_rainbow_eucalyptus_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:rainbow_eucalyptus_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_wood.json deleted file mode 100644 index 222e1e3bc8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_rainbow_eucalyptus_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_rainbow_eucalyptus_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:rainbow_eucalyptus_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_redwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_redwood_log.json deleted file mode 100644 index c274d9971b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_redwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_redwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:redwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_redwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_redwood_wood.json deleted file mode 100644 index f4f1e121ef..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_redwood_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_redwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:redwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_skyris_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_skyris_log.json deleted file mode 100644 index 4034a1c7b6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_skyris_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_skyris_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:skyris_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_skyris_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_skyris_wood.json deleted file mode 100644 index 6b90fabf0e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_skyris_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_skyris_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:skyris_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_willow_log.json deleted file mode 100644 index 793ba2cc4c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_willow_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_willow_wood.json deleted file mode 100644 index 271fae9b28..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_willow_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_witch_hazel_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_witch_hazel_log.json deleted file mode 100644 index 8e0ef4f46a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_witch_hazel_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_witch_hazel_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:witch_hazel_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_witch_hazel_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_witch_hazel_wood.json deleted file mode 100644 index 5f55d0b129..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_witch_hazel_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_witch_hazel_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:witch_hazel_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_zelkova_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_zelkova_log.json deleted file mode 100644 index 5d9890c3ea..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_zelkova_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_zelkova_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:zelkova_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_zelkova_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_zelkova_wood.json deleted file mode 100644 index cdb6c3031d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_zelkova_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_zelkova_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:zelkova_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/willow_log.json deleted file mode 100644 index ae0353481a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/willow_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_willow_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/willow_wood.json deleted file mode 100644 index e5b0799584..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/willow_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_willow_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/witch_hazel_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/witch_hazel_log.json deleted file mode 100644 index 9170e87c7a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/witch_hazel_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:witch_hazel_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_witch_hazel_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/witch_hazel_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/witch_hazel_wood.json deleted file mode 100644 index 0c745044b4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/witch_hazel_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:witch_hazel_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_witch_hazel_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/zelkova_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/zelkova_log.json deleted file mode 100644 index 39f2bc7ed2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/zelkova_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:zelkova_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_zelkova_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/zelkova_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/zelkova_wood.json deleted file mode 100644 index 2b7f8fc9e6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/zelkova_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:zelkova_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_zelkova_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/azalea_log.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/azalea_log.json deleted file mode 100644 index 33dd82f5d6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/azalea_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:azalea_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_azalea_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/azalea_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/azalea_wood.json deleted file mode 100644 index 11d149a17d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/azalea_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:azalea_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_azalea_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/coconut_log.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/coconut_log.json deleted file mode 100644 index 01cb069601..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/coconut_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:coconut_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_coconut_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/coconut_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/coconut_wood.json deleted file mode 100644 index a2d89906e0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/coconut_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:coconut_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_coconut_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/flowering_azalea_log.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/flowering_azalea_log.json deleted file mode 100644 index 92dd72d170..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/flowering_azalea_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:flowering_azalea_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_azalea_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/flowering_azalea_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/flowering_azalea_wood.json deleted file mode 100644 index 083c7efb33..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/flowering_azalea_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:flowering_azalea_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_azalea_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_azalea_log.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_azalea_log.json deleted file mode 100644 index b3f912a44f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_azalea_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:stripped_azalea_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "ecologics:azalea_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_azalea_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_azalea_wood.json deleted file mode 100644 index 2b21a5ad0e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_azalea_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:stripped_azalea_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "ecologics:azalea_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_coconut_log.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_coconut_log.json deleted file mode 100644 index e1f9ee5341..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_coconut_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:stripped_coconut_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "ecologics:coconut_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_coconut_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_coconut_wood.json deleted file mode 100644 index 5cd8b05da1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_coconut_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:stripped_coconut_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "ecologics:coconut_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_walnut_log.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_walnut_log.json deleted file mode 100644 index f32e747d37..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_walnut_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:stripped_walnut_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "ecologics:walnut_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_walnut_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_walnut_wood.json deleted file mode 100644 index 15e0c23e75..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/stripped_walnut_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:stripped_walnut_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "ecologics:walnut_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/walnut_log.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/walnut_log.json deleted file mode 100644 index 77a1366aa3..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/walnut_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:walnut_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_walnut_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/walnut_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/ecologics/walnut_wood.json deleted file mode 100644 index b385aa9365..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/ecologics/walnut_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "ecologics" - } - ], - "ingredients": [ - { - "item": "ecologics:walnut_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "ecologics:stripped_walnut_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/endergetic/poise_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/endergetic/poise_stem.json deleted file mode 100644 index 512a1a3b1f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/endergetic/poise_stem.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "endergetic" - } - ], - "ingredients": [ - { - "item": "endergetic:poise_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "endergetic:stripped_poise_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/endergetic/stripped_poise_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/endergetic/stripped_poise_stem.json deleted file mode 100644 index 2e7133393e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/endergetic/stripped_poise_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "endergetic" - } - ], - "ingredients": [ - { - "item": "endergetic:stripped_poise_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "endergetic:poise_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/cherry_log.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/cherry_log.json deleted file mode 100644 index bda9bed091..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/cherry_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:cherry_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "environmental:stripped_cherry_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/cherry_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/cherry_wood.json deleted file mode 100644 index 51f682484e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/cherry_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:cherry_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "environmental:stripped_cherry_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_cherry_log.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_cherry_log.json deleted file mode 100644 index 43d753bcfe..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_cherry_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:stripped_cherry_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "environmental:cherry_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_cherry_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_cherry_wood.json deleted file mode 100644 index 887f1ef540..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_cherry_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:stripped_cherry_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "environmental:cherry_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_willow_log.json deleted file mode 100644 index e38effb695..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_willow_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:stripped_willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "environmental:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_willow_wood.json deleted file mode 100644 index f326983c34..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_willow_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:stripped_willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "environmental:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_wisteria_log.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_wisteria_log.json deleted file mode 100644 index 27d94422b9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_wisteria_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:stripped_wisteria_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "environmental:wisteria_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_wisteria_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_wisteria_wood.json deleted file mode 100644 index 2a6b8a2338..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/stripped_wisteria_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:stripped_wisteria_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "environmental:wisteria_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/willow_log.json deleted file mode 100644 index 94404afcd0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/willow_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "environmental:stripped_willow_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/willow_wood.json deleted file mode 100644 index fde447308e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/willow_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "environmental:stripped_willow_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/wisteria_log.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/wisteria_log.json deleted file mode 100644 index b5d06e6ffe..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/wisteria_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:wisteria_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "environmental:stripped_wisteria_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/environmental/wisteria_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/environmental/wisteria_wood.json deleted file mode 100644 index 0ac29cdef9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/environmental/wisteria_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "environmental" - } - ], - "ingredients": [ - { - "item": "environmental:wisteria_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "environmental:stripped_wisteria_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/aurum_log.json b/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/aurum_log.json deleted file mode 100644 index c64a7f6231..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/aurum_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "forbidden_arcanus" - } - ], - "ingredients": [ - { - "item": "forbidden_arcanus:aurum_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "forbidden_arcanus:stripped_aurum_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/aurum_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/aurum_wood.json deleted file mode 100644 index d0bd2d0595..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/aurum_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "forbidden_arcanus" - } - ], - "ingredients": [ - { - "item": "forbidden_arcanus:aurum_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "forbidden_arcanus:stripped_aurum_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_log.json b/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_log.json deleted file mode 100644 index 1d33c25579..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "forbidden_arcanus" - } - ], - "ingredients": [ - { - "item": "forbidden_arcanus:stripped_aurum_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "forbidden_arcanus:aurum_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_wood.json deleted file mode 100644 index ba72b3de8e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/forbidden_arcanus/stripped_aurum_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "forbidden_arcanus" - } - ], - "ingredients": [ - { - "item": "forbidden_arcanus:stripped_aurum_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "forbidden_arcanus:aurum_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/cypress_log.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/cypress_log.json deleted file mode 100644 index 9bf7bae194..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/cypress_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:cypress_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "goodending:stripped_cypress_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/cypress_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/cypress_wood.json deleted file mode 100644 index a79fd9ee4e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/cypress_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:cypress_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "goodending:stripped_cypress_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/muddy_oak_log.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/muddy_oak_log.json deleted file mode 100644 index f51850831e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/muddy_oak_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:muddy_oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "goodending:stripped_muddy_oak_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/muddy_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/muddy_oak_wood.json deleted file mode 100644 index d4b59beafe..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/muddy_oak_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:muddy_oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "goodending:stripped_muddy_oak_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_cypress_log.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_cypress_log.json deleted file mode 100644 index 9cf45d2bd6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_cypress_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:stripped_cypress_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "goodending:cypress_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_cypress_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_cypress_wood.json deleted file mode 100644 index 627e3bbbac..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_cypress_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:stripped_cypress_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "goodending:cypress_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_log.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_log.json deleted file mode 100644 index b87c794689..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:stripped_muddy_oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "goodending:muddy_oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_wood.json deleted file mode 100644 index fa4e87410f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/goodending/stripped_muddy_oak_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "goodending" - } - ], - "ingredients": [ - { - "item": "goodending:stripped_muddy_oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "goodending:muddy_oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/edified_log.json b/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/edified_log.json deleted file mode 100644 index 2caaf5516d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/edified_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "hexcasting" - } - ], - "ingredients": [ - { - "item": "hexcasting:edified_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "hexcasting:stripped_edified_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/edified_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/edified_wood.json deleted file mode 100644 index ccb3794265..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/edified_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "hexcasting" - } - ], - "ingredients": [ - { - "item": "hexcasting:edified_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "hexcasting:stripped_edified_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/stripped_edified_log.json b/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/stripped_edified_log.json deleted file mode 100644 index 6dc80b52df..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/stripped_edified_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "hexcasting" - } - ], - "ingredients": [ - { - "item": "hexcasting:stripped_edified_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "hexcasting:edified_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/stripped_edified_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/stripped_edified_wood.json deleted file mode 100644 index 2757bd0c49..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/hexcasting/stripped_edified_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "hexcasting" - } - ], - "ingredients": [ - { - "item": "hexcasting:stripped_edified_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "hexcasting:edified_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_aluminum.json b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_aluminum.json new file mode 100644 index 0000000000..c3971d308b --- /dev/null +++ b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_aluminum.json @@ -0,0 +1,21 @@ +{ + "type": "create:cutting", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:plates/aluminum" + } + ], + "processingTime": 50, + "results": [ + { + "count": 2, + "item": "immersiveengineering:wire_aluminum" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_copper.json b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_copper.json new file mode 100644 index 0000000000..711b023d5a --- /dev/null +++ b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_copper.json @@ -0,0 +1,21 @@ +{ + "type": "create:cutting", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:plates/copper" + } + ], + "processingTime": 50, + "results": [ + { + "count": 2, + "item": "immersiveengineering:wire_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_electrum.json b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_electrum.json new file mode 100644 index 0000000000..95264ddf61 --- /dev/null +++ b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_electrum.json @@ -0,0 +1,21 @@ +{ + "type": "create:cutting", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:plates/electrum" + } + ], + "processingTime": 50, + "results": [ + { + "count": 2, + "item": "immersiveengineering:wire_electrum" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_lead.json b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_lead.json new file mode 100644 index 0000000000..f9bb3d81f2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_lead.json @@ -0,0 +1,21 @@ +{ + "type": "create:cutting", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:plates/lead" + } + ], + "processingTime": 50, + "results": [ + { + "count": 2, + "item": "immersiveengineering:wire_lead" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_steel.json b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_steel.json new file mode 100644 index 0000000000..85667c47f7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/cutting/compat/immersiveengineering/wire_steel.json @@ -0,0 +1,21 @@ +{ + "type": "create:cutting", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:plates/steel" + } + ], + "processingTime": 50, + "results": [ + { + "count": 2, + "item": "immersiveengineering:wire_steel" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_log.json b/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_log.json deleted file mode 100644 index 58d743125c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "integrateddynamics" - } - ], - "ingredients": [ - { - "item": "integrateddynamics:menril_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "integrateddynamics:menril_log_stripped" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_log_stripped.json b/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_log_stripped.json deleted file mode 100644 index b3ae38d0f5..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_log_stripped.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "integrateddynamics" - } - ], - "ingredients": [ - { - "item": "integrateddynamics:menril_log_stripped" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "integrateddynamics:menril_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_wood.json deleted file mode 100644 index 09ede5a795..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "integrateddynamics" - } - ], - "ingredients": [ - { - "item": "integrateddynamics:menril_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "integrateddynamics:menril_wood_stripped" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_wood_stripped.json b/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_wood_stripped.json deleted file mode 100644 index 2fc49fd838..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/integrateddynamics/menril_wood_stripped.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "integrateddynamics" - } - ], - "ingredients": [ - { - "item": "integrateddynamics:menril_wood_stripped" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "integrateddynamics:menril_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/jabuticaba_log.json b/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/jabuticaba_log.json deleted file mode 100644 index 67048eb060..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/jabuticaba_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "nethers_exoticism" - } - ], - "ingredients": [ - { - "item": "nethers_exoticism:jabuticaba_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "nethers_exoticism:stripped_jabuticaba_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_log.json b/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_log.json deleted file mode 100644 index ea9a148efc..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "nethers_exoticism" - } - ], - "ingredients": [ - { - "item": "nethers_exoticism:ramboutan_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "nethers_exoticism:stripped_ramboutan_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_wood.json deleted file mode 100644 index 1f2c939275..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/ramboutan_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "nethers_exoticism" - } - ], - "ingredients": [ - { - "item": "nethers_exoticism:ramboutan_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "nethers_exoticism:stripped_ramboutan_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_jabuticaba_log.json b/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_jabuticaba_log.json deleted file mode 100644 index 39f83ac1f2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_jabuticaba_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "nethers_exoticism" - } - ], - "ingredients": [ - { - "item": "nethers_exoticism:stripped_jabuticaba_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "nethers_exoticism:jabuticaba_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_log.json b/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_log.json deleted file mode 100644 index 5d070556c7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "nethers_exoticism" - } - ], - "ingredients": [ - { - "item": "nethers_exoticism:stripped_ramboutan_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "nethers_exoticism:ramboutan_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_wood.json deleted file mode 100644 index 4e27eacc95..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/nethers_exoticism/stripped_ramboutan_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "nethers_exoticism" - } - ], - "ingredients": [ - { - "item": "nethers_exoticism:stripped_ramboutan_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "nethers_exoticism:ramboutan_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/ancient_log.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/ancient_log.json deleted file mode 100644 index f8c7732a1c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/ancient_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:ancient_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "quark:stripped_ancient_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/ancient_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/ancient_wood.json deleted file mode 100644 index 79654adb92..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/ancient_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:ancient_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "quark:stripped_ancient_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/azalea_log.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/azalea_log.json deleted file mode 100644 index 016d074acf..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/azalea_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:azalea_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "quark:stripped_azalea_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/azalea_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/azalea_wood.json deleted file mode 100644 index bba137f8dc..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/azalea_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:azalea_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "quark:stripped_azalea_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/blossom_log.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/blossom_log.json deleted file mode 100644 index 8a7bc6e8e6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/blossom_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:blossom_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "quark:stripped_blossom_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/blossom_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/blossom_wood.json deleted file mode 100644 index ebd796db37..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/blossom_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:blossom_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "quark:stripped_blossom_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_ancient_log.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_ancient_log.json deleted file mode 100644 index 75de73d79e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_ancient_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:stripped_ancient_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "quark:ancient_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_ancient_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_ancient_wood.json deleted file mode 100644 index 7cdcf9a09b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_ancient_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:stripped_ancient_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "quark:ancient_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_azalea_log.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_azalea_log.json deleted file mode 100644 index f7276bef07..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_azalea_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:stripped_azalea_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "quark:azalea_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_azalea_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_azalea_wood.json deleted file mode 100644 index fc5ee7e387..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_azalea_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:stripped_azalea_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "quark:azalea_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_blossom_log.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_blossom_log.json deleted file mode 100644 index 5ae6d6b1fd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_blossom_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:stripped_blossom_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "quark:blossom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_blossom_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_blossom_wood.json deleted file mode 100644 index ec05738d80..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/quark/stripped_blossom_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "quark" - } - ], - "ingredients": [ - { - "item": "quark:stripped_blossom_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "quark:blossom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/alpha_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/alpha_log.json deleted file mode 100644 index 3d04818d91..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/alpha_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:alpha_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:alpha_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/ashen_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/ashen_log.json deleted file mode 100644 index 9b9ccde889..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/ashen_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:ashen_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_dead_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/ashen_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/ashen_wood.json deleted file mode 100644 index 64268cea6e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/ashen_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:ashen_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_dead_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/baobab_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/baobab_log.json deleted file mode 100644 index 9e5f04c458..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/baobab_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:baobab_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_baobab_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/baobab_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/baobab_wood.json deleted file mode 100644 index 034f89d1d0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/baobab_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:baobab_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_baobab_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blackwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blackwood_log.json deleted file mode 100644 index 6c1b242780..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blackwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:blackwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_blackwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blackwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blackwood_wood.json deleted file mode 100644 index d91cfe4e3a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blackwood_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:blackwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_blackwood_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_hyphae.json deleted file mode 100644 index 0b3d52d45d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_hyphae.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:blue_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_blue_bioshroom_hyphae" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_stem.json deleted file mode 100644 index 7df03fde09..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/blue_bioshroom_stem.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:blue_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_blue_bioshroom_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_log.json deleted file mode 100644 index aa4e9ee8af..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:brimwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_brimwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_log_magma.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_log_magma.json deleted file mode 100644 index 73bd278db8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_log_magma.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:brimwood_log_magma" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_brimwood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_wood.json deleted file mode 100644 index b36f4e44fc..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/brimwood_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:brimwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_brimwood_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cobalt_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cobalt_log.json deleted file mode 100644 index f5641872af..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cobalt_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:cobalt_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_cobalt_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cobalt_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cobalt_wood.json deleted file mode 100644 index 5f96985fdf..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cobalt_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:cobalt_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_cobalt_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cypress_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cypress_log.json deleted file mode 100644 index e50d931841..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cypress_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:cypress_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_cypress_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cypress_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cypress_wood.json deleted file mode 100644 index a174c2e272..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/cypress_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:cypress_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_cypress_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/dead_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/dead_log.json deleted file mode 100644 index 4e4aba0c6a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/dead_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:dead_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_dead_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/dead_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/dead_wood.json deleted file mode 100644 index f4332d2f5b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/dead_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:dead_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_dead_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_log.json deleted file mode 100644 index 2dff2a3c45..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:eucalyptus_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_eucalyptus_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_wood.json deleted file mode 100644 index ebdd4b7285..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/eucalyptus_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:eucalyptus_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_eucalyptus_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_hyphae.json deleted file mode 100644 index 5641504577..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_hyphae.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:green_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_green_bioshroom_hyphae" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_stem.json deleted file mode 100644 index 234350483b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/green_bioshroom_stem.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:green_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_green_bioshroom_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/joshua_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/joshua_log.json deleted file mode 100644 index 943136f337..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/joshua_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:joshua_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_joshua_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/joshua_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/joshua_wood.json deleted file mode 100644 index c574d98ae4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/joshua_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:joshua_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_joshua_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/kapok_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/kapok_log.json deleted file mode 100644 index 348e470855..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/kapok_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:kapok_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_kapok_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/kapok_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/kapok_wood.json deleted file mode 100644 index 18e2c1e26d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/kapok_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:kapok_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_kapok_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/larch_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/larch_log.json deleted file mode 100644 index 58907cf1a9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/larch_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:larch_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_larch_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/larch_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/larch_wood.json deleted file mode 100644 index 33b9b29422..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/larch_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:larch_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_larch_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/magnolia_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/magnolia_log.json deleted file mode 100644 index 3cb32bcdd4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/magnolia_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:magnolia_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_magnolia_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/magnolia_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/magnolia_wood.json deleted file mode 100644 index b5e032f811..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/magnolia_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:magnolia_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_magnolia_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/maple_log.json deleted file mode 100644 index cdef2d2678..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/maple_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_maple_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/maple_wood.json deleted file mode 100644 index 05e1fd89be..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/maple_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_maple_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/mauve_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/mauve_log.json deleted file mode 100644 index 1d0ac841d0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/mauve_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:mauve_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_mauve_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/mauve_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/mauve_wood.json deleted file mode 100644 index 14b4dbd837..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/mauve_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:mauve_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_mauve_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/palm_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/palm_log.json deleted file mode 100644 index 922d92e8ed..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/palm_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:palm_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_palm_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/palm_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/palm_wood.json deleted file mode 100644 index 023a3ff258..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/palm_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:palm_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_palm_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pine_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pine_log.json deleted file mode 100644 index afcb9dc625..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pine_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:pine_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_pine_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pine_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pine_wood.json deleted file mode 100644 index 6e288f7c23..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pine_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:pine_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_pine_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_hyphae.json deleted file mode 100644 index a5a5291adb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_hyphae.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:pink_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_pink_bioshroom_hyphae" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_stem.json deleted file mode 100644 index 19a098d281..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/pink_bioshroom_stem.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:pink_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_pink_bioshroom_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/redwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/redwood_log.json deleted file mode 100644 index 31008d1ed7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/redwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:redwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_redwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/redwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/redwood_wood.json deleted file mode 100644 index c9c7162ddd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/redwood_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:redwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_redwood_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/socotra_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/socotra_log.json deleted file mode 100644 index d22f1fd6b3..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/socotra_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:socotra_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_socotra_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/socotra_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/socotra_wood.json deleted file mode 100644 index 5327031226..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/socotra_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:socotra_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_socotra_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_log.json deleted file mode 100644 index 01b71b9e06..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_baobab_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:baobab_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_wood.json deleted file mode 100644 index 01bda3ec0b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_baobab_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_baobab_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:baobab_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_log.json deleted file mode 100644 index 9a2d679f1e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_blackwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:blackwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_wood.json deleted file mode 100644 index 917489959b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blackwood_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_blackwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:blackwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_hyphae.json deleted file mode 100644 index 844eaa8c20..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_hyphae.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_blue_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:blue_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_stem.json deleted file mode 100644 index 855ce4cd59..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_blue_bioshroom_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_blue_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:blue_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_log.json deleted file mode 100644 index 314a6de49b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_brimwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:brimwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_wood.json deleted file mode 100644 index e98b1096fd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_brimwood_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_brimwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:brimwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_log.json deleted file mode 100644 index 2d90168d8f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_cobalt_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:cobalt_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_wood.json deleted file mode 100644 index a77efb06ba..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cobalt_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_cobalt_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:cobalt_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_log.json deleted file mode 100644 index 1e77886df1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_cypress_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:cypress_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_wood.json deleted file mode 100644 index caf0f65cd3..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_cypress_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_cypress_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:cypress_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_log.json deleted file mode 100644 index c7361c156c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_dead_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:dead_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_wood.json deleted file mode 100644 index c36ee981ad..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_dead_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_dead_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:dead_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_log.json deleted file mode 100644 index e74e93eb2b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_eucalyptus_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:eucalyptus_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_wood.json deleted file mode 100644 index 118682cd15..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_eucalyptus_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_eucalyptus_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:eucalyptus_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_hyphae.json deleted file mode 100644 index 636f61ba23..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_hyphae.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_green_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:green_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_stem.json deleted file mode 100644 index d39b9c4c90..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_green_bioshroom_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_green_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:green_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_log.json deleted file mode 100644 index 96f010d62d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_joshua_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:joshua_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_wood.json deleted file mode 100644 index 117837e722..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_joshua_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_joshua_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:joshua_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_log.json deleted file mode 100644 index b315cd0df9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_kapok_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:kapok_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_wood.json deleted file mode 100644 index 32714d2e26..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_kapok_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_kapok_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:kapok_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_log.json deleted file mode 100644 index f877366642..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_larch_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:larch_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_wood.json deleted file mode 100644 index ec88a46692..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_larch_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_larch_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:larch_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_log.json deleted file mode 100644 index 66d70dbba9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_magnolia_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:magnolia_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_wood.json deleted file mode 100644 index c7e3952d38..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_magnolia_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_magnolia_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:magnolia_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_log.json deleted file mode 100644 index de7f7a4cc4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_maple_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_wood.json deleted file mode 100644 index e619940c25..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_maple_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_maple_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:maple_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_log.json deleted file mode 100644 index 9eea85ca82..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_mauve_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:mauve_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_wood.json deleted file mode 100644 index fb1ac0903b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_mauve_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_mauve_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:mauve_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_log.json deleted file mode 100644 index 94f43d9a98..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_palm_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:palm_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_wood.json deleted file mode 100644 index 67c9c53097..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_palm_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_palm_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:palm_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_log.json deleted file mode 100644 index 8fdf7ffba4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_pine_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:pine_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_wood.json deleted file mode 100644 index 046785afb0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pine_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_pine_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:pine_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_hyphae.json deleted file mode 100644 index f40e22a958..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_hyphae.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_pink_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:pink_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_stem.json deleted file mode 100644 index d04fec2404..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_pink_bioshroom_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_pink_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:pink_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_log.json deleted file mode 100644 index 04125ad336..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_redwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:redwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_wood.json deleted file mode 100644 index 326f0a86fd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_redwood_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_redwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:redwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_log.json deleted file mode 100644 index eed513e95a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_socotra_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:socotra_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_wood.json deleted file mode 100644 index 7d82d94839..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_socotra_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_socotra_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:socotra_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_log.json deleted file mode 100644 index c86252926b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_wood.json deleted file mode 100644 index 09554a5075..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_willow_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:willow_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_hyphae.json deleted file mode 100644 index b9d2efd2ef..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_hyphae.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_yellow_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:yellow_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_stem.json deleted file mode 100644 index ef5af31c2b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/stripped_yellow_bioshroom_stem.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:stripped_yellow_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "regions_unexplored:yellow_bioshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/willow_log.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/willow_log.json deleted file mode 100644 index 2b368bc077..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/willow_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:willow_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_willow_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/willow_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/willow_wood.json deleted file mode 100644 index 1ccced84f4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/willow_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:willow_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_willow_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_hyphae.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_hyphae.json deleted file mode 100644 index 17320770fe..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_hyphae.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:yellow_bioshroom_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_yellow_bioshroom_hyphae" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_stem.json b/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_stem.json deleted file mode 100644 index 75ff49841f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/regions_unexplored/yellow_bioshroom_stem.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "regions_unexplored" - } - ], - "ingredients": [ - { - "item": "regions_unexplored:yellow_bioshroom_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "regions_unexplored:stripped_yellow_bioshroom_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/netherwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/silentgear/netherwood_log.json deleted file mode 100644 index 3186af2426..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/netherwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "silentgear" - } - ], - "ingredients": [ - { - "item": "silentgear:netherwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "silentgear:stripped_netherwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/netherwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/silentgear/netherwood_wood.json deleted file mode 100644 index 375090f72d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/netherwood_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "silentgear" - } - ], - "ingredients": [ - { - "item": "silentgear:netherwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "silentgear:stripped_netherwood_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/stripped_netherwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/silentgear/stripped_netherwood_log.json deleted file mode 100644 index 17aa616812..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/stripped_netherwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "silentgear" - } - ], - "ingredients": [ - { - "item": "silentgear:stripped_netherwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "silentgear:netherwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/stripped_netherwood_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/silentgear/stripped_netherwood_wood.json deleted file mode 100644 index c52fc33de5..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/silentgear/stripped_netherwood_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "silentgear" - } - ], - "ingredients": [ - { - "item": "silentgear:stripped_netherwood_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "silentgear:netherwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/bloodshroom_log.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/bloodshroom_log.json deleted file mode 100644 index e6464015c8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/bloodshroom_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:bloodshroom_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "tconstruct:stripped_bloodshroom_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/bloodshroom_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/bloodshroom_wood.json deleted file mode 100644 index e4cbfd9178..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/bloodshroom_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:bloodshroom_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "tconstruct:stripped_bloodshroom_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/greenheart_log.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/greenheart_log.json deleted file mode 100644 index 7bfb20b446..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/greenheart_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:greenheart_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "tconstruct:stripped_greenheart_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/greenheart_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/greenheart_wood.json deleted file mode 100644 index a85deb49f4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/greenheart_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:greenheart_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "tconstruct:stripped_greenheart_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/skyroot_log.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/skyroot_log.json deleted file mode 100644 index 8e5f3943aa..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/skyroot_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:skyroot_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "tconstruct:stripped_skyroot_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/skyroot_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/skyroot_wood.json deleted file mode 100644 index ee4a40d2ba..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/skyroot_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:skyroot_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "tconstruct:stripped_skyroot_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_log.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_log.json deleted file mode 100644 index 533a17f146..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:stripped_bloodshroom_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "tconstruct:bloodshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_wood.json deleted file mode 100644 index a617bc9078..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_bloodshroom_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:stripped_bloodshroom_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "tconstruct:bloodshroom_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_log.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_log.json deleted file mode 100644 index a0aecfa9df..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:stripped_greenheart_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "tconstruct:greenheart_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_wood.json deleted file mode 100644 index 50ecd35181..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_greenheart_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:stripped_greenheart_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "tconstruct:greenheart_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_log.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_log.json deleted file mode 100644 index 4a77a6619f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:stripped_skyroot_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "tconstruct:skyroot_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_wood.json deleted file mode 100644 index b19bb73aa2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/tconstruct/stripped_skyroot_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "tconstruct" - } - ], - "ingredients": [ - { - "item": "tconstruct:stripped_skyroot_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "tconstruct:skyroot_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/chromatic_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/chromatic_log.json deleted file mode 100644 index a78141a809..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/chromatic_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:chromatic_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "the_vault:stripped_chromatic_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/driftwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/driftwood_log.json deleted file mode 100644 index 32604c3dcf..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/driftwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:driftwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "the_vault:stripped_driftwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/overgrown_wooden_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/overgrown_wooden_log.json deleted file mode 100644 index 2f920cc0f8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/overgrown_wooden_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:overgrown_wooden_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "the_vault:stripped_overgrown_wooden_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_chromatic_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_chromatic_log.json deleted file mode 100644 index 6f2a23b239..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_chromatic_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:stripped_chromatic_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 4, - "item": "the_vault:chromatic_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_driftwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_driftwood_log.json deleted file mode 100644 index 801f599b0d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_driftwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:stripped_driftwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 4, - "item": "the_vault:driftwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_overgrown_wooden_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_overgrown_wooden_log.json deleted file mode 100644 index 22849dec92..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_overgrown_wooden_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:stripped_overgrown_wooden_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 4, - "item": "the_vault:overgrown_wooden_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_wooden_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_wooden_log.json deleted file mode 100644 index 16e1b02316..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/stripped_wooden_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:stripped_wooden_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 4, - "item": "the_vault:wooden_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/wooden_log.json b/src/generated/resources/data/create/recipes/cutting/compat/the_vault/wooden_log.json deleted file mode 100644 index afc355e096..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/the_vault/wooden_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "the_vault" - } - ], - "ingredients": [ - { - "item": "the_vault:wooden_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "the_vault:stripped_wooden_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/canopy_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/canopy_log.json deleted file mode 100644 index 4579174595..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/canopy_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:canopy_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_canopy_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/canopy_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/canopy_wood.json deleted file mode 100644 index 72091dde87..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/canopy_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:canopy_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_canopy_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/dark_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/dark_log.json deleted file mode 100644 index ee9a643903..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/dark_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:dark_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_dark_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/dark_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/dark_wood.json deleted file mode 100644 index 97f5cd0790..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/dark_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:dark_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_dark_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mangrove_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mangrove_log.json deleted file mode 100644 index 4f111257f1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mangrove_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:mangrove_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_mangrove_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mangrove_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mangrove_wood.json deleted file mode 100644 index 3f08971bef..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mangrove_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:mangrove_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_mangrove_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mining_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mining_log.json deleted file mode 100644 index d4765bc65c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mining_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:mining_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_mining_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mining_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mining_wood.json deleted file mode 100644 index 17c5ba4a8e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/mining_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:mining_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_mining_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/sorting_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/sorting_log.json deleted file mode 100644 index bb622c9edc..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/sorting_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:sorting_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_sorting_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/sorting_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/sorting_wood.json deleted file mode 100644 index 1510ed2e84..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/sorting_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:sorting_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_sorting_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_canopy_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_canopy_log.json deleted file mode 100644 index 7aa4f32fd3..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_canopy_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_canopy_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:canopy_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_canopy_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_canopy_wood.json deleted file mode 100644 index 8869d89135..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_canopy_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_canopy_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:canopy_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_dark_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_dark_log.json deleted file mode 100644 index 1fd4679e48..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_dark_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_dark_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:dark_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_dark_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_dark_wood.json deleted file mode 100644 index c177affed6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_dark_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_dark_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:dark_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_log.json deleted file mode 100644 index 9643574c29..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_mangrove_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:mangrove_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_wood.json deleted file mode 100644 index 108a00a422..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mangrove_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_mangrove_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:mangrove_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mining_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mining_log.json deleted file mode 100644 index 42c8cd84b1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mining_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_mining_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:mining_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mining_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mining_wood.json deleted file mode 100644 index 91ee2ff568..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_mining_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_mining_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:mining_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_sorting_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_sorting_log.json deleted file mode 100644 index 1ad0b02926..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_sorting_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_sorting_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:sorting_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_sorting_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_sorting_wood.json deleted file mode 100644 index 08898a47bb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_sorting_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_sorting_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:sorting_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_time_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_time_log.json deleted file mode 100644 index 084bf94eb0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_time_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_time_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:time_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_time_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_time_wood.json deleted file mode 100644 index 4e10fe9a98..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_time_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_time_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:time_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_transformation_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_transformation_log.json deleted file mode 100644 index 9cb7472504..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_transformation_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_transformation_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:transformation_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_transformation_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_transformation_wood.json deleted file mode 100644 index 2a205236f6..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_transformation_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_transformation_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:transformation_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_log.json deleted file mode 100644 index 793d8b76ea..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_twilight_oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:twilight_oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_wood.json deleted file mode 100644 index a3ddb2fa30..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/stripped_twilight_oak_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:stripped_twilight_oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "twilightforest:twilight_oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/time_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/time_log.json deleted file mode 100644 index 05fef47890..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/time_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:time_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_time_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/time_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/time_wood.json deleted file mode 100644 index c9f3d20e6c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/time_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:time_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_time_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/transformation_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/transformation_log.json deleted file mode 100644 index 11c7ae694e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/transformation_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:transformation_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_transformation_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/transformation_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/transformation_wood.json deleted file mode 100644 index e17c52aae4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/transformation_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:transformation_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_transformation_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/twilight_oak_log.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/twilight_oak_log.json deleted file mode 100644 index 40ec9a7775..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/twilight_oak_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:twilight_oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_twilight_oak_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/twilight_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/twilight_oak_wood.json deleted file mode 100644 index 07d815e465..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/twilightforest/twilight_oak_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "twilightforest" - } - ], - "ingredients": [ - { - "item": "twilightforest:twilight_oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "twilightforest:stripped_twilight_oak_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/driftwood.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/driftwood.json deleted file mode 100644 index 8c3cd6348b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/driftwood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:driftwood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "upgrade_aquatic:stripped_driftwood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/driftwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/driftwood_log.json deleted file mode 100644 index d8860f677f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/driftwood_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:driftwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "upgrade_aquatic:stripped_driftwood_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/river_log.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/river_log.json deleted file mode 100644 index 08073a48fe..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/river_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:river_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "upgrade_aquatic:stripped_river_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/river_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/river_wood.json deleted file mode 100644 index 2b5f0b892f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/river_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:river_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "upgrade_aquatic:stripped_river_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood.json deleted file mode 100644 index 85a92d2b39..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:stripped_driftwood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "upgrade_aquatic:driftwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood_log.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood_log.json deleted file mode 100644 index 61e26e351d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_driftwood_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:stripped_driftwood_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "upgrade_aquatic:driftwood_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_log.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_log.json deleted file mode 100644 index 6f79119606..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:stripped_river_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "upgrade_aquatic:river_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_wood.json deleted file mode 100644 index 7ae737510d..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/upgrade_aquatic/stripped_river_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "upgrade_aquatic" - } - ], - "ingredients": [ - { - "item": "upgrade_aquatic:stripped_river_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "upgrade_aquatic:river_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/chestnut_log.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/chestnut_log.json deleted file mode 100644 index ec333925e7..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/chestnut_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:chestnut_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "windswept:stripped_chestnut_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/chestnut_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/chestnut_wood.json deleted file mode 100644 index 965afa048f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/chestnut_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:chestnut_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "windswept:stripped_chestnut_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/holly_log.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/holly_log.json deleted file mode 100644 index 65e94f9382..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/holly_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:holly_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "windswept:stripped_holly_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/holly_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/holly_wood.json deleted file mode 100644 index a82a608d40..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/holly_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:holly_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "windswept:stripped_holly_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_chestnut_log.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_chestnut_log.json deleted file mode 100644 index 01780d0c08..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_chestnut_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:stripped_chestnut_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "windswept:chestnut_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_chestnut_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_chestnut_wood.json deleted file mode 100644 index d37badef6f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_chestnut_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:stripped_chestnut_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "windswept:chestnut_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_holly_log.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_holly_log.json deleted file mode 100644 index 167c4f8507..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_holly_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:stripped_holly_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "windswept:holly_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_holly_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_holly_wood.json deleted file mode 100644 index 316c524efd..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/windswept/stripped_holly_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "windswept" - } - ], - "ingredients": [ - { - "item": "windswept:stripped_holly_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "windswept:holly_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/crimson_hyphae.json b/src/generated/resources/data/create/recipes/cutting/crimson_hyphae.json deleted file mode 100644 index b21c061783..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/crimson_hyphae.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:crimson_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_crimson_hyphae" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/crimson_stem.json b/src/generated/resources/data/create/recipes/cutting/crimson_stem.json deleted file mode 100644 index 1b01540571..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/crimson_stem.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:crimson_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_crimson_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/dark_oak_log.json b/src/generated/resources/data/create/recipes/cutting/dark_oak_log.json deleted file mode 100644 index f487973f98..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/dark_oak_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:dark_oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_dark_oak_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/dark_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/dark_oak_wood.json deleted file mode 100644 index d427cd9762..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/dark_oak_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:dark_oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_dark_oak_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/jungle_log.json b/src/generated/resources/data/create/recipes/cutting/jungle_log.json deleted file mode 100644 index 4b50fd5396..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/jungle_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:jungle_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_jungle_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/jungle_wood.json b/src/generated/resources/data/create/recipes/cutting/jungle_wood.json deleted file mode 100644 index 3192c1488e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/jungle_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:jungle_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_jungle_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/mangrove_log.json b/src/generated/resources/data/create/recipes/cutting/mangrove_log.json deleted file mode 100644 index a21afe6e5a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/mangrove_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:mangrove_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_mangrove_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/mangrove_wood.json b/src/generated/resources/data/create/recipes/cutting/mangrove_wood.json deleted file mode 100644 index 63f7a1e9c2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/mangrove_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:mangrove_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_mangrove_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/oak_log.json b/src/generated/resources/data/create/recipes/cutting/oak_log.json deleted file mode 100644 index 7b144262c4..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/oak_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_oak_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/oak_wood.json b/src/generated/resources/data/create/recipes/cutting/oak_wood.json deleted file mode 100644 index 67e805f35e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/oak_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_oak_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/spruce_log.json b/src/generated/resources/data/create/recipes/cutting/spruce_log.json deleted file mode 100644 index c3d2404e81..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/spruce_log.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:spruce_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_spruce_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/spruce_wood.json b/src/generated/resources/data/create/recipes/cutting/spruce_wood.json deleted file mode 100644 index dc51b9db76..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/spruce_wood.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:spruce_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_spruce_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_acacia_log.json deleted file mode 100644 index ec91b0d934..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_acacia_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:acacia_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_acacia_wood.json deleted file mode 100644 index a70d781848..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_acacia_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_acacia_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:acacia_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_birch_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_birch_log.json deleted file mode 100644 index 600ac2e8e9..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_birch_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_birch_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:birch_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_birch_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_birch_wood.json deleted file mode 100644 index 573f915ab2..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_birch_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_birch_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:birch_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_cherry_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_cherry_log.json deleted file mode 100644 index a18f6116ba..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_cherry_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_cherry_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:cherry_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_cherry_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_cherry_wood.json deleted file mode 100644 index 03ed47cfdc..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_cherry_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_cherry_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:cherry_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_hyphae.json b/src/generated/resources/data/create/recipes/cutting/stripped_crimson_hyphae.json deleted file mode 100644 index 4de07e2ab8..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_hyphae.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_crimson_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:crimson_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_stem.json b/src/generated/resources/data/create/recipes/cutting/stripped_crimson_stem.json deleted file mode 100644 index 8398ebb1a0..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_crimson_stem.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_crimson_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:crimson_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_log.json deleted file mode 100644 index 6776a3694f..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_dark_oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:dark_oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_wood.json deleted file mode 100644 index a2c28047df..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_dark_oak_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_dark_oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:dark_oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_jungle_log.json deleted file mode 100644 index b6ba3bbf8a..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_jungle_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:jungle_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_jungle_wood.json deleted file mode 100644 index 49c81da966..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_jungle_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_jungle_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:jungle_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_mangrove_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_mangrove_log.json deleted file mode 100644 index 753258cb3b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_mangrove_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_mangrove_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:mangrove_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_mangrove_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_mangrove_wood.json deleted file mode 100644 index 99c6cc88c1..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_mangrove_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_mangrove_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:mangrove_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_oak_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_oak_log.json deleted file mode 100644 index a76c5db55b..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_oak_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_oak_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_oak_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_oak_wood.json deleted file mode 100644 index 9e9f35a301..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_oak_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_oak_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:oak_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_log.json b/src/generated/resources/data/create/recipes/cutting/stripped_spruce_log.json deleted file mode 100644 index 8e986bdb9c..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_log.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_spruce_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:spruce_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_wood.json b/src/generated/resources/data/create/recipes/cutting/stripped_spruce_wood.json deleted file mode 100644 index 34e0ba2354..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_spruce_wood.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_spruce_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:spruce_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_warped_hyphae.json b/src/generated/resources/data/create/recipes/cutting/stripped_warped_hyphae.json deleted file mode 100644 index 6e01df1272..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_warped_hyphae.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_warped_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:warped_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/stripped_warped_stem.json b/src/generated/resources/data/create/recipes/cutting/stripped_warped_stem.json deleted file mode 100644 index cbdc4026bb..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/stripped_warped_stem.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:stripped_warped_stem" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "minecraft:warped_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/warped_hyphae.json b/src/generated/resources/data/create/recipes/cutting/warped_hyphae.json deleted file mode 100644 index 0f8519d621..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/warped_hyphae.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:warped_hyphae" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_warped_hyphae" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/warped_stem.json b/src/generated/resources/data/create/recipes/cutting/warped_stem.json deleted file mode 100644 index da21a0e47e..0000000000 --- a/src/generated/resources/data/create/recipes/cutting/warped_stem.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "type": "create:cutting", - "ingredients": [ - { - "item": "minecraft:warped_stem" - } - ], - "processingTime": 50, - "results": [ - { - "item": "minecraft:stripped_warped_stem" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_block_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/copper_block_from_deoxidising.json new file mode 100644 index 0000000000..b98c2df616 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_block_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:exposed_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:copper_block" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_block_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/copper_block_from_removing_wax.json new file mode 100644 index 0000000000..d7acf9128e --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_block_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_copper_block" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:copper_block" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_shingle_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/copper_shingle_slab_from_deoxidising.json new file mode 100644 index 0000000000..a78a939684 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_shingle_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:exposed_copper_shingle_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_shingle_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_shingle_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/copper_shingle_slab_from_removing_wax.json new file mode 100644 index 0000000000..d60b47feb9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_shingle_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_copper_shingle_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_shingle_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_shingle_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/copper_shingle_stairs_from_deoxidising.json new file mode 100644 index 0000000000..671245227b --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_shingle_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:exposed_copper_shingle_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_shingle_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_shingle_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/copper_shingle_stairs_from_removing_wax.json new file mode 100644 index 0000000000..06cafdc1a6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_shingle_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_copper_shingle_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_shingle_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_shingles_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/copper_shingles_from_deoxidising.json new file mode 100644 index 0000000000..f945478c7c --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_shingles_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:exposed_copper_shingles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_shingles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_shingles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/copper_shingles_from_removing_wax.json new file mode 100644 index 0000000000..ee276f8771 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_shingles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_copper_shingles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_shingles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_tile_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/copper_tile_slab_from_deoxidising.json new file mode 100644 index 0000000000..eb01726735 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_tile_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:exposed_copper_tile_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_tile_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_tile_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/copper_tile_slab_from_removing_wax.json new file mode 100644 index 0000000000..24260a76b8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_tile_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_copper_tile_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_tile_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_tile_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/copper_tile_stairs_from_deoxidising.json new file mode 100644 index 0000000000..2b7164a368 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_tile_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:exposed_copper_tile_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_tile_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_tile_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/copper_tile_stairs_from_removing_wax.json new file mode 100644 index 0000000000..640cc6d18d --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_tile_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_copper_tile_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_tile_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_tiles_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/copper_tiles_from_deoxidising.json new file mode 100644 index 0000000000..b98e016345 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_tiles_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:exposed_copper_tiles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_tiles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/copper_tiles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/copper_tiles_from_removing_wax.json new file mode 100644 index 0000000000..a19edbd111 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/copper_tiles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_copper_tiles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:copper_tiles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/cut_copper_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/cut_copper_from_deoxidising.json new file mode 100644 index 0000000000..30d6a00b11 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/cut_copper_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:exposed_cut_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:cut_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/cut_copper_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/cut_copper_from_removing_wax.json new file mode 100644 index 0000000000..55d3b26076 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/cut_copper_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_cut_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:cut_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/cut_copper_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/cut_copper_slab_from_deoxidising.json new file mode 100644 index 0000000000..6ee7a38231 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/cut_copper_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:exposed_cut_copper_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:cut_copper_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/cut_copper_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/cut_copper_slab_from_removing_wax.json new file mode 100644 index 0000000000..5de927285f --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/cut_copper_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_cut_copper_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:cut_copper_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/cut_copper_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/cut_copper_stairs_from_deoxidising.json new file mode 100644 index 0000000000..10a16d0afd --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/cut_copper_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:exposed_cut_copper_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:cut_copper_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/cut_copper_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/cut_copper_stairs_from_removing_wax.json new file mode 100644 index 0000000000..ba1393e4b8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/cut_copper_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_cut_copper_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:cut_copper_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_from_deoxidising.json new file mode 100644 index 0000000000..310fac2ff2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:weathered_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_from_removing_wax.json new file mode 100644 index 0000000000..5f9f6e0090 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_exposed_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_slab_from_deoxidising.json new file mode 100644 index 0000000000..4b5c26fc4d --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:weathered_copper_shingle_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_shingle_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_slab_from_removing_wax.json new file mode 100644 index 0000000000..1aefcef554 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_exposed_copper_shingle_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_shingle_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_stairs_from_deoxidising.json new file mode 100644 index 0000000000..ffb2f84ef7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:weathered_copper_shingle_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_shingle_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_stairs_from_removing_wax.json new file mode 100644 index 0000000000..578666b0c9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingle_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_exposed_copper_shingle_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_shingle_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingles_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingles_from_deoxidising.json new file mode 100644 index 0000000000..787f694610 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingles_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:weathered_copper_shingles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_shingles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingles_from_removing_wax.json new file mode 100644 index 0000000000..c9b9d0fa80 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_shingles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_exposed_copper_shingles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_shingles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_slab_from_deoxidising.json new file mode 100644 index 0000000000..aa09f58dc7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:weathered_copper_tile_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_tile_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_slab_from_removing_wax.json new file mode 100644 index 0000000000..fafb438bc4 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_exposed_copper_tile_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_tile_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_stairs_from_deoxidising.json new file mode 100644 index 0000000000..73e1ea72c5 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:weathered_copper_tile_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_tile_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_stairs_from_removing_wax.json new file mode 100644 index 0000000000..6e3efe241b --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tile_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_exposed_copper_tile_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_tile_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_tiles_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tiles_from_deoxidising.json new file mode 100644 index 0000000000..d393fad7f1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tiles_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:weathered_copper_tiles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_tiles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_copper_tiles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tiles_from_removing_wax.json new file mode 100644 index 0000000000..54effad934 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_copper_tiles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_exposed_copper_tiles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:exposed_copper_tiles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_from_deoxidising.json new file mode 100644 index 0000000000..623604a53f --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:weathered_cut_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_cut_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_from_removing_wax.json new file mode 100644 index 0000000000..6a07ad1f62 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_exposed_cut_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_cut_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_slab_from_deoxidising.json new file mode 100644 index 0000000000..918a15fbc3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:weathered_cut_copper_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_cut_copper_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_slab_from_removing_wax.json new file mode 100644 index 0000000000..cbe8c6a27e --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_exposed_cut_copper_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_cut_copper_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_stairs_from_deoxidising.json new file mode 100644 index 0000000000..90302f445f --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:weathered_cut_copper_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_cut_copper_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_stairs_from_removing_wax.json new file mode 100644 index 0000000000..5b3fca39c0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/exposed_cut_copper_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_exposed_cut_copper_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:exposed_cut_copper_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_copper_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_from_removing_wax.json new file mode 100644 index 0000000000..8c227c104b --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_oxidized_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:oxidized_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingle_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingle_slab_from_removing_wax.json new file mode 100644 index 0000000000..b26fc86a0e --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingle_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_oxidized_copper_shingle_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:oxidized_copper_shingle_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingle_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingle_stairs_from_removing_wax.json new file mode 100644 index 0000000000..57e210ed0b --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingle_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_oxidized_copper_shingle_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:oxidized_copper_shingle_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingles_from_removing_wax.json new file mode 100644 index 0000000000..b2beffc051 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_shingles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_oxidized_copper_shingles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:oxidized_copper_shingles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tile_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tile_slab_from_removing_wax.json new file mode 100644 index 0000000000..94f14510e0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tile_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_oxidized_copper_tile_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:oxidized_copper_tile_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tile_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tile_stairs_from_removing_wax.json new file mode 100644 index 0000000000..921f7c7a4f --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tile_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_oxidized_copper_tile_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:oxidized_copper_tile_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tiles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tiles_from_removing_wax.json new file mode 100644 index 0000000000..9faa5ac27c --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_copper_tiles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_oxidized_copper_tiles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:oxidized_copper_tiles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_from_removing_wax.json new file mode 100644 index 0000000000..53159d4731 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_oxidized_cut_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:oxidized_cut_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_slab_from_removing_wax.json new file mode 100644 index 0000000000..dbe01a3623 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_oxidized_cut_copper_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:oxidized_cut_copper_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_stairs_from_removing_wax.json new file mode 100644 index 0000000000..578c8eba0b --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/oxidized_cut_copper_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_oxidized_cut_copper_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:oxidized_cut_copper_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_from_deoxidising.json new file mode 100644 index 0000000000..d43be8aa7b --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:oxidized_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_from_removing_wax.json new file mode 100644 index 0000000000..8b6614f98c --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_weathered_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_slab_from_deoxidising.json new file mode 100644 index 0000000000..4789309de2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:oxidized_copper_shingle_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_shingle_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_slab_from_removing_wax.json new file mode 100644 index 0000000000..d9c74b8822 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_weathered_copper_shingle_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_shingle_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_stairs_from_deoxidising.json new file mode 100644 index 0000000000..403a03f899 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:oxidized_copper_shingle_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_shingle_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_stairs_from_removing_wax.json new file mode 100644 index 0000000000..0473633323 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingle_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_weathered_copper_shingle_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_shingle_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingles_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingles_from_deoxidising.json new file mode 100644 index 0000000000..aeeb95322a --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingles_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:oxidized_copper_shingles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_shingles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingles_from_removing_wax.json new file mode 100644 index 0000000000..1f8d8ddebe --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_shingles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_weathered_copper_shingles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_shingles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_slab_from_deoxidising.json new file mode 100644 index 0000000000..0b1c722735 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:oxidized_copper_tile_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_tile_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_slab_from_removing_wax.json new file mode 100644 index 0000000000..7cdc9e39ff --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_weathered_copper_tile_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_tile_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_stairs_from_deoxidising.json new file mode 100644 index 0000000000..0cc6b887c3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:oxidized_copper_tile_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_tile_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_stairs_from_removing_wax.json new file mode 100644 index 0000000000..4a30a19137 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tile_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_weathered_copper_tile_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_tile_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_tiles_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tiles_from_deoxidising.json new file mode 100644 index 0000000000..1d6d8992a6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tiles_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:oxidized_copper_tiles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_tiles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_copper_tiles_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tiles_from_removing_wax.json new file mode 100644 index 0000000000..059590fb82 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_copper_tiles_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "create:waxed_weathered_copper_tiles" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "create:weathered_copper_tiles" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_from_deoxidising.json new file mode 100644 index 0000000000..386e68cbec --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:oxidized_cut_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_cut_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_from_removing_wax.json new file mode 100644 index 0000000000..c4523d63ec --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_weathered_cut_copper" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_cut_copper" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_slab_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_slab_from_deoxidising.json new file mode 100644 index 0000000000..1cadb4594f --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_slab_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:oxidized_cut_copper_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_cut_copper_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_slab_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_slab_from_removing_wax.json new file mode 100644 index 0000000000..9d7ade1662 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_slab_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_weathered_cut_copper_slab" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_cut_copper_slab" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_stairs_from_deoxidising.json b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_stairs_from_deoxidising.json new file mode 100644 index 0000000000..fbb33f17c1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_stairs_from_deoxidising.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:oxidized_cut_copper_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_cut_copper_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_stairs_from_removing_wax.json b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_stairs_from_removing_wax.json new file mode 100644 index 0000000000..09a7a29ff8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deploying/weathered_cut_copper_stairs_from_removing_wax.json @@ -0,0 +1,17 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "minecraft:waxed_weathered_cut_copper_stairs" + }, + { + "tag": "minecraft:axes" + } + ], + "keepHeldItem": true, + "results": [ + { + "item": "minecraft:weathered_cut_copper_stairs" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/filling/compat/immersiveengineering/treated_wood_in_spout.json b/src/generated/resources/data/create/recipes/filling/compat/immersiveengineering/treated_wood_in_spout.json new file mode 100644 index 0000000000..f8497dcb5d --- /dev/null +++ b/src/generated/resources/data/create/recipes/filling/compat/immersiveengineering/treated_wood_in_spout.json @@ -0,0 +1,23 @@ +{ + "type": "create:filling", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "minecraft:planks" + }, + { + "amount": 125, + "fluidTag": "forge:creosote" + } + ], + "results": [ + { + "item": "immersiveengineering:treated_wood_horizontal" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/framed_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/recipes/framed_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..e71a272c86 --- /dev/null +++ b/src/generated/resources/data/create/recipes/framed_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "forge:glass_panes/colorless" + }, + "result": "create:framed_glass_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/recipes/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..2335716473 --- /dev/null +++ b/src/generated/resources/data/create/recipes/horizontal_framed_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "forge:glass_panes/colorless" + }, + "result": "create:horizontal_framed_glass_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/industrial_iron_window.json b/src/generated/resources/data/create/recipes/industrial_iron_window.json new file mode 100644 index 0000000000..d126e944f0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/industrial_iron_window.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "create:industrial_iron_block" + }, + "X": { + "tag": "forge:glass/colorless" + } + }, + "pattern": [ + " # ", + "#X#" + ], + "result": { + "count": 2, + "item": "create:industrial_iron_window" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/industrial_iron_window_pane.json b/src/generated/resources/data/create/recipes/industrial_iron_window_pane.json new file mode 100644 index 0000000000..7b7e4869a6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/industrial_iron_window_pane.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "create:industrial_iron_window" + } + }, + "pattern": [ + "###", + "###" + ], + "result": { + "count": 16, + "item": "create:industrial_iron_window_pane" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/item_application/bound_cardboard_inworld.json b/src/generated/resources/data/create/recipes/item_application/bound_cardboard_inworld.json new file mode 100644 index 0000000000..01db281a27 --- /dev/null +++ b/src/generated/resources/data/create/recipes/item_application/bound_cardboard_inworld.json @@ -0,0 +1,16 @@ +{ + "type": "create:item_application", + "ingredients": [ + { + "item": "create:cardboard_block" + }, + { + "tag": "forge:string" + } + ], + "results": [ + { + "item": "create:bound_cardboard_block" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mixing/cardboard_pulp.json b/src/generated/resources/data/create/recipes/mixing/cardboard_pulp.json new file mode 100644 index 0000000000..e79f9ddf5e --- /dev/null +++ b/src/generated/resources/data/create/recipes/mixing/cardboard_pulp.json @@ -0,0 +1,27 @@ +{ + "type": "create:mixing", + "ingredients": [ + { + "tag": "create:pulpifiable" + }, + { + "tag": "create:pulpifiable" + }, + { + "tag": "create:pulpifiable" + }, + { + "tag": "create:pulpifiable" + }, + { + "amount": 250, + "fluid": "minecraft:water", + "nbt": {} + } + ], + "results": [ + { + "item": "create:pulp" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/cardboard.json b/src/generated/resources/data/create/recipes/pressing/cardboard.json new file mode 100644 index 0000000000..6222e2cc86 --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/cardboard.json @@ -0,0 +1,13 @@ +{ + "type": "create:pressing", + "ingredients": [ + { + "item": "create:pulp" + } + ], + "results": [ + { + "item": "create:cardboard" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/betterendforge/end_mycelium_path.json b/src/generated/resources/data/create/recipes/pressing/compat/betterendforge/end_mycelium_path.json new file mode 100644 index 0000000000..ed24b21116 --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/betterendforge/end_mycelium_path.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "ingredients": [ + { + "item": "betterendforge:end_mycelium" + } + ], + "results": [ + { + "item": "betterendforge:end_mycelium_path" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/betterendforge/end_myclium_path.json b/src/generated/resources/data/create/recipes/pressing/compat/betterendforge/end_myclium_path.json deleted file mode 100644 index 744bdef32a..0000000000 --- a/src/generated/resources/data/create/recipes/pressing/compat/betterendforge/end_myclium_path.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "create:pressing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "betterendforge" - } - ], - "ingredients": [ - { - "item": "betterendforge:end_myclium" - } - ], - "results": [ - { - "item": "betterendforge:end_myclium_path" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_aluminum.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_aluminum.json new file mode 100644 index 0000000000..00c4a3a5c2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_aluminum.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/aluminum" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_aluminum" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_constantan.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_constantan.json new file mode 100644 index 0000000000..bb6ba9c6ea --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_constantan.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/constantan" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_constantan" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_electrum.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_electrum.json new file mode 100644 index 0000000000..c0fdc28800 --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_electrum.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/electrum" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_electrum" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_lead.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_lead.json new file mode 100644 index 0000000000..a5fcad040a --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_lead.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/lead" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_lead" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_nickel.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_nickel.json new file mode 100644 index 0000000000..2a42008cca --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_nickel.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/nickel" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_nickel" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_silver.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_silver.json new file mode 100644 index 0000000000..fff08ca945 --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_silver.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/silver" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_silver" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_steel.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_steel.json new file mode 100644 index 0000000000..2dd8cdf1ad --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_steel.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/steel" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_steel" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_uranium.json b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_uranium.json new file mode 100644 index 0000000000..2172141edc --- /dev/null +++ b/src/generated/resources/data/create/recipes/pressing/compat/immersiveengineering/plate_uranium.json @@ -0,0 +1,19 @@ +{ + "type": "create:pressing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "tag": "forge:ingots/uranium" + } + ], + "results": [ + { + "item": "immersiveengineering:plate_uranium" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/industrial_iron_block.json b/src/generated/resources/data/create/recipes/splashing/industrial_iron_block.json new file mode 100644 index 0000000000..52a2aa5cf6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/industrial_iron_block.json @@ -0,0 +1,13 @@ +{ + "type": "create:splashing", + "ingredients": [ + { + "item": "create:industrial_iron_block" + } + ], + "results": [ + { + "item": "create:weathered_iron_block" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/industrial_iron_window.json b/src/generated/resources/data/create/recipes/splashing/industrial_iron_window.json new file mode 100644 index 0000000000..01250ef1a3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/industrial_iron_window.json @@ -0,0 +1,13 @@ +{ + "type": "create:splashing", + "ingredients": [ + { + "item": "create:industrial_iron_window" + } + ], + "results": [ + { + "item": "create:weathered_iron_window" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/industrial_iron_window_pane.json b/src/generated/resources/data/create/recipes/splashing/industrial_iron_window_pane.json new file mode 100644 index 0000000000..7ccbc88881 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/industrial_iron_window_pane.json @@ -0,0 +1,13 @@ +{ + "type": "create:splashing", + "ingredients": [ + { + "item": "create:industrial_iron_window_pane" + } + ], + "results": [ + { + "item": "create:weathered_iron_window_pane" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/recipes/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..1d6eacf2e5 --- /dev/null +++ b/src/generated/resources/data/create/recipes/tiled_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "forge:glass_panes/colorless" + }, + "result": "create:tiled_glass_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json b/src/generated/resources/data/create/recipes/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json new file mode 100644 index 0000000000..bd6b3f2303 --- /dev/null +++ b/src/generated/resources/data/create/recipes/vertical_framed_glass_pane_from_glass_panes_colorless_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "forge:glass_panes/colorless" + }, + "result": "create:vertical_framed_glass_pane" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/weathered_iron_block_from_ingots_iron_stonecutting.json b/src/generated/resources/data/create/recipes/weathered_iron_block_from_ingots_iron_stonecutting.json new file mode 100644 index 0000000000..66caa8bb5d --- /dev/null +++ b/src/generated/resources/data/create/recipes/weathered_iron_block_from_ingots_iron_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/iron" + }, + "result": "create:weathered_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/weathered_iron_window.json b/src/generated/resources/data/create/recipes/weathered_iron_window.json new file mode 100644 index 0000000000..78014a9503 --- /dev/null +++ b/src/generated/resources/data/create/recipes/weathered_iron_window.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "create:weathered_iron_block" + }, + "X": { + "tag": "forge:glass/colorless" + } + }, + "pattern": [ + " # ", + "#X#" + ], + "result": { + "count": 2, + "item": "create:weathered_iron_window" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/weathered_iron_window_pane.json b/src/generated/resources/data/create/recipes/weathered_iron_window_pane.json new file mode 100644 index 0000000000..773c390796 --- /dev/null +++ b/src/generated/resources/data/create/recipes/weathered_iron_window_pane.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "create:weathered_iron_window" + } + }, + "pattern": [ + "###", + "###" + ], + "result": { + "count": 16, + "item": "create:weathered_iron_window_pane" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/chest_mounted_storage.json b/src/generated/resources/data/create/tags/blocks/chest_mounted_storage.json new file mode 100644 index 0000000000..86533f935b --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/chest_mounted_storage.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:chest", + "minecraft:trapped_chest" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/contraption_inventory_deny.json b/src/generated/resources/data/create/tags/blocks/fallback_mounted_storage_blacklist.json similarity index 100% rename from src/generated/resources/data/create/tags/blocks/contraption_inventory_deny.json rename to src/generated/resources/data/create/tags/blocks/fallback_mounted_storage_blacklist.json diff --git a/src/generated/resources/data/create/tags/blocks/non_breakable.json b/src/generated/resources/data/create/tags/blocks/non_breakable.json new file mode 100644 index 0000000000..f72d209df7 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/non_breakable.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/non_harvestable.json b/src/generated/resources/data/create/tags/blocks/non_harvestable.json new file mode 100644 index 0000000000..1cc3798345 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/non_harvestable.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:fire" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/postboxes.json b/src/generated/resources/data/create/tags/blocks/postboxes.json new file mode 100644 index 0000000000..c5c54b8fbc --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/postboxes.json @@ -0,0 +1,20 @@ +{ + "values": [ + "create:white_postbox", + "create:orange_postbox", + "create:magenta_postbox", + "create:light_blue_postbox", + "create:yellow_postbox", + "create:lime_postbox", + "create:pink_postbox", + "create:gray_postbox", + "create:light_gray_postbox", + "create:cyan_postbox", + "create:purple_postbox", + "create:blue_postbox", + "create:brown_postbox", + "create:green_postbox", + "create:red_postbox", + "create:black_postbox" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/safe_nbt.json b/src/generated/resources/data/create/tags/blocks/safe_nbt.json index 04e710d060..68cd07f316 100644 --- a/src/generated/resources/data/create/tags/blocks/safe_nbt.json +++ b/src/generated/resources/data/create/tags/blocks/safe_nbt.json @@ -22,6 +22,7 @@ "create:analog_lever", "create:pulse_repeater", "create:pulse_extender", + "create:pulse_timer", "create:clipboard", "#minecraft:banners", "#minecraft:all_signs" diff --git a/src/generated/resources/data/create/tags/blocks/simple_mounted_storage.json b/src/generated/resources/data/create/tags/blocks/simple_mounted_storage.json new file mode 100644 index 0000000000..93f3ee349c --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/simple_mounted_storage.json @@ -0,0 +1,22 @@ +{ + "values": [ + "minecraft:barrel", + "minecraft:shulker_box", + "minecraft:white_shulker_box", + "minecraft:orange_shulker_box", + "minecraft:magenta_shulker_box", + "minecraft:light_blue_shulker_box", + "minecraft:yellow_shulker_box", + "minecraft:lime_shulker_box", + "minecraft:pink_shulker_box", + "minecraft:gray_shulker_box", + "minecraft:light_gray_shulker_box", + "minecraft:cyan_shulker_box", + "minecraft:purple_shulker_box", + "minecraft:blue_shulker_box", + "minecraft:brown_shulker_box", + "minecraft:green_shulker_box", + "minecraft:red_shulker_box", + "minecraft:black_shulker_box" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/table_cloths.json b/src/generated/resources/data/create/tags/blocks/table_cloths.json new file mode 100644 index 0000000000..20c8f0ada5 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/table_cloths.json @@ -0,0 +1,23 @@ +{ + "values": [ + "create:white_table_cloth", + "create:orange_table_cloth", + "create:magenta_table_cloth", + "create:light_blue_table_cloth", + "create:yellow_table_cloth", + "create:lime_table_cloth", + "create:pink_table_cloth", + "create:gray_table_cloth", + "create:light_gray_table_cloth", + "create:cyan_table_cloth", + "create:purple_table_cloth", + "create:blue_table_cloth", + "create:brown_table_cloth", + "create:green_table_cloth", + "create:red_table_cloth", + "create:black_table_cloth", + "create:andesite_table_cloth", + "create:brass_table_cloth", + "create:copper_table_cloth" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/wrench_pickup.json b/src/generated/resources/data/create/tags/blocks/wrench_pickup.json index 6037359262..7ca0a5284e 100644 --- a/src/generated/resources/data/create/tags/blocks/wrench_pickup.json +++ b/src/generated/resources/data/create/tags/blocks/wrench_pickup.json @@ -4,10 +4,12 @@ "create:brass_bars", "create:copper_bars", "create:industrial_iron_block", + "create:weathered_iron_block", "minecraft:redstone_wire", "minecraft:redstone_torch", "minecraft:repeater", "minecraft:lever", + "minecraft:redstone_lamp", "minecraft:comparator", "minecraft:observer", "minecraft:redstone_wall_torch", diff --git a/src/generated/resources/data/create/tags/create/contraption_type/opens_controls.json b/src/generated/resources/data/create/tags/create/contraption_type/opens_controls.json new file mode 100644 index 0000000000..cbc32877ea --- /dev/null +++ b/src/generated/resources/data/create/tags/create/contraption_type/opens_controls.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:carriage" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/create/contraption_type/requires_vehicle_for_render.json b/src/generated/resources/data/create/tags/create/contraption_type/requires_vehicle_for_render.json new file mode 100644 index 0000000000..27ce966101 --- /dev/null +++ b/src/generated/resources/data/create/tags/create/contraption_type/requires_vehicle_for_render.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:mounted" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json new file mode 100644 index 0000000000..99eb273fe1 --- /dev/null +++ b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/fuel_blacklist.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:vault" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/create/mounted_item_storage_type/internal.json b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/internal.json new file mode 100644 index 0000000000..f91fe16551 --- /dev/null +++ b/src/generated/resources/data/create/tags/create/mounted_item_storage_type/internal.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:dispenser" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/chain_rideable.json b/src/generated/resources/data/create/tags/items/chain_rideable.json new file mode 100644 index 0000000000..5cb6cb4b6e --- /dev/null +++ b/src/generated/resources/data/create/tags/items/chain_rideable.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#forge:tools/wrench" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/dispense_behavior_wrap_blacklist.json b/src/generated/resources/data/create/tags/items/dispense_behavior_wrap_blacklist.json new file mode 100644 index 0000000000..f72d209df7 --- /dev/null +++ b/src/generated/resources/data/create/tags/items/dispense_behavior_wrap_blacklist.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/dyed_table_cloths.json b/src/generated/resources/data/create/tags/items/dyed_table_cloths.json new file mode 100644 index 0000000000..08032250b4 --- /dev/null +++ b/src/generated/resources/data/create/tags/items/dyed_table_cloths.json @@ -0,0 +1,20 @@ +{ + "values": [ + "create:white_table_cloth", + "create:orange_table_cloth", + "create:magenta_table_cloth", + "create:light_blue_table_cloth", + "create:yellow_table_cloth", + "create:lime_table_cloth", + "create:pink_table_cloth", + "create:gray_table_cloth", + "create:light_gray_table_cloth", + "create:cyan_table_cloth", + "create:purple_table_cloth", + "create:blue_table_cloth", + "create:brown_table_cloth", + "create:green_table_cloth", + "create:red_table_cloth", + "create:black_table_cloth" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/invalid_for_track_paving.json b/src/generated/resources/data/create/tags/items/invalid_for_track_paving.json new file mode 100644 index 0000000000..1f658f8b9a --- /dev/null +++ b/src/generated/resources/data/create/tags/items/invalid_for_track_paving.json @@ -0,0 +1,6 @@ +{ + "values": [ + "create:wooden_bracket", + "create:metal_bracket" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/packages.json b/src/generated/resources/data/create/tags/items/packages.json new file mode 100644 index 0000000000..3dac74ee02 --- /dev/null +++ b/src/generated/resources/data/create/tags/items/packages.json @@ -0,0 +1,18 @@ +{ + "values": [ + "create:cardboard_package_12x12", + "create:cardboard_package_10x12", + "create:cardboard_package_10x8", + "create:cardboard_package_12x10", + "create:rare_creeper_package", + "create:rare_darcy_package", + "create:rare_evan_package", + "create:rare_jinx_package", + "create:rare_kryppers_package", + "create:rare_simi_package", + "create:rare_starlotte_package", + "create:rare_thunder_package", + "create:rare_up_package", + "create:rare_vector_package" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/postboxes.json b/src/generated/resources/data/create/tags/items/postboxes.json new file mode 100644 index 0000000000..c5c54b8fbc --- /dev/null +++ b/src/generated/resources/data/create/tags/items/postboxes.json @@ -0,0 +1,20 @@ +{ + "values": [ + "create:white_postbox", + "create:orange_postbox", + "create:magenta_postbox", + "create:light_blue_postbox", + "create:yellow_postbox", + "create:lime_postbox", + "create:pink_postbox", + "create:gray_postbox", + "create:light_gray_postbox", + "create:cyan_postbox", + "create:purple_postbox", + "create:blue_postbox", + "create:brown_postbox", + "create:green_postbox", + "create:red_postbox", + "create:black_postbox" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/pulpifiable.json b/src/generated/resources/data/create/tags/items/pulpifiable.json new file mode 100644 index 0000000000..ecbbc85abf --- /dev/null +++ b/src/generated/resources/data/create/tags/items/pulpifiable.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:bamboo", + "minecraft:sugar_cane", + "#minecraft:saplings" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/table_cloths.json b/src/generated/resources/data/create/tags/items/table_cloths.json new file mode 100644 index 0000000000..20c8f0ada5 --- /dev/null +++ b/src/generated/resources/data/create/tags/items/table_cloths.json @@ -0,0 +1,23 @@ +{ + "values": [ + "create:white_table_cloth", + "create:orange_table_cloth", + "create:magenta_table_cloth", + "create:light_blue_table_cloth", + "create:yellow_table_cloth", + "create:lime_table_cloth", + "create:pink_table_cloth", + "create:gray_table_cloth", + "create:light_gray_table_cloth", + "create:cyan_table_cloth", + "create:purple_table_cloth", + "create:blue_table_cloth", + "create:brown_table_cloth", + "create:green_table_cloth", + "create:red_table_cloth", + "create:black_table_cloth", + "create:andesite_table_cloth", + "create:brass_table_cloth", + "create:copper_table_cloth" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/glass_panes.json b/src/generated/resources/data/forge/tags/blocks/glass_panes.json index ec99a30f53..4b82571bf4 100644 --- a/src/generated/resources/data/forge/tags/blocks/glass_panes.json +++ b/src/generated/resources/data/forge/tags/blocks/glass_panes.json @@ -13,6 +13,10 @@ "create:mangrove_window_pane", "create:crimson_window_pane", "create:warped_window_pane", - "create:ornate_iron_window_pane" + "create:cherry_window_pane", + "create:bamboo_window_pane", + "create:ornate_iron_window_pane", + "create:industrial_iron_window_pane", + "create:weathered_iron_window_pane" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/glass_panes/colorless.json b/src/generated/resources/data/forge/tags/blocks/glass_panes/colorless.json new file mode 100644 index 0000000000..ba3df00522 --- /dev/null +++ b/src/generated/resources/data/forge/tags/blocks/glass_panes/colorless.json @@ -0,0 +1,8 @@ +{ + "values": [ + "create:tiled_glass_pane", + "create:framed_glass_pane", + "create:horizontal_framed_glass_pane", + "create:vertical_framed_glass_pane" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/storage_blocks.json b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json index 14641f4514..3c03b7b1a9 100644 --- a/src/generated/resources/data/forge/tags/blocks/storage_blocks.json +++ b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json @@ -4,6 +4,7 @@ "create:zinc_block", "create:andesite_alloy_block", "create:brass_block", + "create:cardboard_block", "create:experience_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/storage_blocks/cardboard.json b/src/generated/resources/data/forge/tags/blocks/storage_blocks/cardboard.json new file mode 100644 index 0000000000..10452a5013 --- /dev/null +++ b/src/generated/resources/data/forge/tags/blocks/storage_blocks/cardboard.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:cardboard_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/armors/boots.json b/src/generated/resources/data/forge/tags/items/armors/boots.json index 892f0dd355..a12039a291 100644 --- a/src/generated/resources/data/forge/tags/items/armors/boots.json +++ b/src/generated/resources/data/forge/tags/items/armors/boots.json @@ -1,6 +1,7 @@ { "values": [ "create:copper_diving_boots", - "create:netherite_diving_boots" + "create:netherite_diving_boots", + "create:cardboard_boots" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/armors/chestplate.json b/src/generated/resources/data/forge/tags/items/armors/chestplate.json new file mode 100644 index 0000000000..706bfa2f56 --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/armors/chestplate.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:cardboard_chestplate" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/armors/helmet.json b/src/generated/resources/data/forge/tags/items/armors/helmet.json new file mode 100644 index 0000000000..9217784ddc --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/armors/helmet.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:cardboard_helmet" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/armors/leggings.json b/src/generated/resources/data/forge/tags/items/armors/leggings.json new file mode 100644 index 0000000000..551ee16974 --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/armors/leggings.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:cardboard_leggings" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/glass_panes.json b/src/generated/resources/data/forge/tags/items/glass_panes.json index ec99a30f53..4b82571bf4 100644 --- a/src/generated/resources/data/forge/tags/items/glass_panes.json +++ b/src/generated/resources/data/forge/tags/items/glass_panes.json @@ -13,6 +13,10 @@ "create:mangrove_window_pane", "create:crimson_window_pane", "create:warped_window_pane", - "create:ornate_iron_window_pane" + "create:cherry_window_pane", + "create:bamboo_window_pane", + "create:ornate_iron_window_pane", + "create:industrial_iron_window_pane", + "create:weathered_iron_window_pane" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/glass_panes/colorless.json b/src/generated/resources/data/forge/tags/items/glass_panes/colorless.json new file mode 100644 index 0000000000..ba3df00522 --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/glass_panes/colorless.json @@ -0,0 +1,8 @@ +{ + "values": [ + "create:tiled_glass_pane", + "create:framed_glass_pane", + "create:horizontal_framed_glass_pane", + "create:vertical_framed_glass_pane" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/plates/cardboard.json b/src/generated/resources/data/forge/tags/items/plates/cardboard.json new file mode 100644 index 0000000000..1563fbdd85 --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/plates/cardboard.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:cardboard" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/storage_blocks.json b/src/generated/resources/data/forge/tags/items/storage_blocks.json index 14641f4514..3c03b7b1a9 100644 --- a/src/generated/resources/data/forge/tags/items/storage_blocks.json +++ b/src/generated/resources/data/forge/tags/items/storage_blocks.json @@ -4,6 +4,7 @@ "create:zinc_block", "create:andesite_alloy_block", "create:brass_block", + "create:cardboard_block", "create:experience_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/storage_blocks/cardboard.json b/src/generated/resources/data/forge/tags/items/storage_blocks/cardboard.json new file mode 100644 index 0000000000..10452a5013 --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/storage_blocks/cardboard.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:cardboard_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/combination_step_sound_blocks.json b/src/generated/resources/data/minecraft/tags/blocks/combination_step_sound_blocks.json new file mode 100644 index 0000000000..08032250b4 --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/blocks/combination_step_sound_blocks.json @@ -0,0 +1,20 @@ +{ + "values": [ + "create:white_table_cloth", + "create:orange_table_cloth", + "create:magenta_table_cloth", + "create:light_blue_table_cloth", + "create:yellow_table_cloth", + "create:lime_table_cloth", + "create:pink_table_cloth", + "create:gray_table_cloth", + "create:light_gray_table_cloth", + "create:cyan_table_cloth", + "create:purple_table_cloth", + "create:blue_table_cloth", + "create:brown_table_cloth", + "create:green_table_cloth", + "create:red_table_cloth", + "create:black_table_cloth" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/impermeable.json b/src/generated/resources/data/minecraft/tags/blocks/impermeable.json index f6c6369fb4..7397212c94 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/impermeable.json +++ b/src/generated/resources/data/minecraft/tags/blocks/impermeable.json @@ -13,6 +13,10 @@ "create:mangrove_window", "create:crimson_window", "create:warped_window", - "create:ornate_iron_window" + "create:cherry_window", + "create:bamboo_window", + "create:ornate_iron_window", + "create:industrial_iron_window", + "create:weathered_iron_window" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/inside_step_sound_blocks.json b/src/generated/resources/data/minecraft/tags/blocks/inside_step_sound_blocks.json new file mode 100644 index 0000000000..757307ecda --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/blocks/inside_step_sound_blocks.json @@ -0,0 +1,7 @@ +{ + "values": [ + "create:andesite_table_cloth", + "create:brass_table_cloth", + "create:copper_table_cloth" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json index 488344a68c..9189599f80 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json @@ -15,6 +15,7 @@ "create:encased_chain_drive", "create:adjustable_chain_gearshift", "create:belt", + "create:chain_conveyor", "create:water_wheel", "create:large_water_wheel", "create:water_wheel_structure", @@ -89,6 +90,23 @@ "create:content_observer", "create:stockpile_switch", "create:creative_crate", + "create:white_postbox", + "create:orange_postbox", + "create:magenta_postbox", + "create:light_blue_postbox", + "create:yellow_postbox", + "create:lime_postbox", + "create:pink_postbox", + "create:gray_postbox", + "create:light_gray_postbox", + "create:cyan_postbox", + "create:purple_postbox", + "create:blue_postbox", + "create:brown_postbox", + "create:green_postbox", + "create:red_postbox", + "create:black_postbox", + "create:stock_ticker", "create:display_link", "create:redstone_link", "create:analog_lever", @@ -111,6 +129,8 @@ "create:brown_seat", "create:green_seat", "create:red_seat", - "create:black_seat" + "create:black_seat", + "create:cardboard_block", + "create:bound_cardboard_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index 82f9abcb25..07d3648425 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -17,6 +17,7 @@ "create:encased_chain_drive", "create:adjustable_chain_gearshift", "create:belt", + "create:chain_conveyor", "create:creative_motor", "create:water_wheel", "create:large_water_wheel", @@ -120,7 +121,6 @@ "create:small_bogey", "create:large_bogey", "create:controls", - "create:item_vault", "create:andesite_funnel", "create:andesite_belt_funnel", "create:brass_funnel", @@ -130,6 +130,18 @@ "create:content_observer", "create:stockpile_switch", "create:creative_crate", + "create:item_vault", + "create:item_hatch", + "create:packager", + "create:repackager", + "create:package_frogport", + "create:stock_link", + "create:stock_ticker", + "create:redstone_requester", + "create:factory_gauge", + "create:andesite_table_cloth", + "create:brass_table_cloth", + "create:copper_table_cloth", "create:display_link", "create:display_board", "create:nixie_tube", @@ -184,6 +196,7 @@ "create:zinc_block", "create:andesite_alloy_block", "create:industrial_iron_block", + "create:weathered_iron_block", "create:brass_block", "create:experience_block", "create:rose_quartz_block", diff --git a/src/generated/resources/data/minecraft/tags/items/trimmable_armor.json b/src/generated/resources/data/minecraft/tags/items/trimmable_armor.json new file mode 100644 index 0000000000..6f07e7efcb --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/items/trimmable_armor.json @@ -0,0 +1,8 @@ +{ + "values": [ + "create:cardboard_helmet", + "create:cardboard_chestplate", + "create:cardboard_leggings", + "create:cardboard_boots" + ] +} \ No newline at end of file diff --git a/src/main/java-templates/com/simibubi/create/CreateBuildInfo.java.peb b/src/main/java-templates/com/simibubi/create/CreateBuildInfo.java.peb new file mode 100644 index 0000000000..bb1dfd9ebc --- /dev/null +++ b/src/main/java-templates/com/simibubi/create/CreateBuildInfo.java.peb @@ -0,0 +1,6 @@ +package com.simibubi.create; + +public class CreateBuildInfo { + public static String VERSION = "{{ version }}"; + public static String GIT_COMMIT = {{ gitCommit }}; +} diff --git a/src/main/java/com/simibubi/create/AllBlockEntityTypes.java b/src/main/java/com/simibubi/create/AllBlockEntityTypes.java index 74918805a0..72441f238f 100644 --- a/src/main/java/com/simibubi/create/AllBlockEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllBlockEntityTypes.java @@ -1,7 +1,6 @@ package com.simibubi.create; import static com.simibubi.create.Create.REGISTRATE; -import static com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours.assignDataBehaviourBE; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsBlockEntity; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsRenderer; @@ -25,6 +24,7 @@ import com.simibubi.create.content.contraptions.chassis.StickerVisual; import com.simibubi.create.content.contraptions.elevator.ElevatorContactBlockEntity; import com.simibubi.create.content.contraptions.elevator.ElevatorPulleyBlockEntity; import com.simibubi.create.content.contraptions.elevator.ElevatorPulleyRenderer; +import com.simibubi.create.content.contraptions.elevator.ElevatorPulleyVisual; import com.simibubi.create.content.contraptions.gantry.GantryCarriageBlockEntity; import com.simibubi.create.content.contraptions.gantry.GantryCarriageRenderer; import com.simibubi.create.content.contraptions.gantry.GantryCarriageVisual; @@ -44,7 +44,6 @@ import com.simibubi.create.content.decoration.steamWhistle.WhistleBlockEntity; import com.simibubi.create.content.decoration.steamWhistle.WhistleRenderer; import com.simibubi.create.content.equipment.armor.BacktankBlockEntity; import com.simibubi.create.content.equipment.armor.BacktankRenderer; -import com.simibubi.create.content.equipment.armor.BacktankVisual; import com.simibubi.create.content.equipment.bell.BellRenderer; import com.simibubi.create.content.equipment.bell.HauntedBellBlockEntity; import com.simibubi.create.content.equipment.bell.PeculiarBellBlockEntity; @@ -64,33 +63,33 @@ import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlockEntity; import com.simibubi.create.content.fluids.pipes.valve.FluidValveRenderer; import com.simibubi.create.content.fluids.pipes.valve.FluidValveVisual; import com.simibubi.create.content.fluids.pump.PumpBlockEntity; -import com.simibubi.create.content.fluids.pump.PumpCogVisual; import com.simibubi.create.content.fluids.pump.PumpRenderer; import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; import com.simibubi.create.content.fluids.spout.SpoutRenderer; import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; import com.simibubi.create.content.fluids.tank.FluidTankRenderer; -import com.simibubi.create.content.kinetics.base.HalfShaftVisual; -import com.simibubi.create.content.kinetics.base.HorizontalHalfShaftVisual; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.base.OrientedRotatingVisual; import com.simibubi.create.content.kinetics.base.ShaftRenderer; -import com.simibubi.create.content.kinetics.base.ShaftVisual; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; +import com.simibubi.create.content.kinetics.base.SingleAxisRotatingVisual; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltRenderer; import com.simibubi.create.content.kinetics.belt.BeltVisual; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorRenderer; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorVisual; import com.simibubi.create.content.kinetics.chainDrive.ChainGearshiftBlockEntity; import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity; import com.simibubi.create.content.kinetics.clock.CuckooClockRenderer; import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity; import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterRenderer; -import com.simibubi.create.content.kinetics.crafter.ShaftlessCogwheelVisual; import com.simibubi.create.content.kinetics.crank.HandCrankBlockEntity; import com.simibubi.create.content.kinetics.crank.HandCrankRenderer; import com.simibubi.create.content.kinetics.crank.HandCrankVisual; import com.simibubi.create.content.kinetics.crank.ValveHandleBlockEntity; +import com.simibubi.create.content.kinetics.crank.ValveHandleVisual; import com.simibubi.create.content.kinetics.crusher.CrushingWheelBlockEntity; import com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlockEntity; import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity; @@ -98,7 +97,6 @@ import com.simibubi.create.content.kinetics.deployer.DeployerRenderer; import com.simibubi.create.content.kinetics.deployer.DeployerVisual; import com.simibubi.create.content.kinetics.drill.DrillBlockEntity; import com.simibubi.create.content.kinetics.drill.DrillRenderer; -import com.simibubi.create.content.kinetics.drill.DrillVisual; import com.simibubi.create.content.kinetics.fan.EncasedFanBlockEntity; import com.simibubi.create.content.kinetics.fan.EncasedFanRenderer; import com.simibubi.create.content.kinetics.fan.FanVisual; @@ -118,7 +116,6 @@ import com.simibubi.create.content.kinetics.mechanicalArm.ArmBlockEntity; import com.simibubi.create.content.kinetics.mechanicalArm.ArmRenderer; import com.simibubi.create.content.kinetics.mechanicalArm.ArmVisual; import com.simibubi.create.content.kinetics.millstone.MillstoneBlockEntity; -import com.simibubi.create.content.kinetics.millstone.MillstoneCogVisual; import com.simibubi.create.content.kinetics.millstone.MillstoneRenderer; import com.simibubi.create.content.kinetics.mixer.MechanicalMixerBlockEntity; import com.simibubi.create.content.kinetics.mixer.MechanicalMixerRenderer; @@ -163,9 +160,26 @@ import com.simibubi.create.content.logistics.depot.DepotRenderer; import com.simibubi.create.content.logistics.depot.EjectorBlockEntity; import com.simibubi.create.content.logistics.depot.EjectorRenderer; import com.simibubi.create.content.logistics.depot.EjectorVisual; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlockEntity; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelRenderer; import com.simibubi.create.content.logistics.funnel.FunnelBlockEntity; import com.simibubi.create.content.logistics.funnel.FunnelRenderer; import com.simibubi.create.content.logistics.funnel.FunnelVisual; +import com.simibubi.create.content.logistics.itemHatch.ItemHatchBlockEntity; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportBlockEntity; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportRenderer; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportVisual; +import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlockEntity; +import com.simibubi.create.content.logistics.packagePort.postbox.PostboxRenderer; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; +import com.simibubi.create.content.logistics.packager.PackagerRenderer; +import com.simibubi.create.content.logistics.packager.PackagerVisual; +import com.simibubi.create.content.logistics.packager.repackager.RepackagerBlockEntity; +import com.simibubi.create.content.logistics.packagerLink.PackagerLinkBlockEntity; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterBlockEntity; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; +import com.simibubi.create.content.logistics.tableCloth.TableClothBlockEntity; +import com.simibubi.create.content.logistics.tableCloth.TableClothRenderer; import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlockEntity; import com.simibubi.create.content.logistics.tunnel.BeltTunnelRenderer; import com.simibubi.create.content.logistics.tunnel.BeltTunnelVisual; @@ -179,14 +193,15 @@ import com.simibubi.create.content.processing.burner.BlazeBurnerVisual; import com.simibubi.create.content.redstone.analogLever.AnalogLeverBlockEntity; import com.simibubi.create.content.redstone.analogLever.AnalogLeverRenderer; import com.simibubi.create.content.redstone.analogLever.AnalogLeverVisual; +import com.simibubi.create.content.redstone.deskBell.DeskBellBlockEntity; +import com.simibubi.create.content.redstone.deskBell.DeskBellRenderer; import com.simibubi.create.content.redstone.diodes.BrassDiodeRenderer; import com.simibubi.create.content.redstone.diodes.BrassDiodeVisual; import com.simibubi.create.content.redstone.diodes.PulseExtenderBlockEntity; import com.simibubi.create.content.redstone.diodes.PulseRepeaterBlockEntity; +import com.simibubi.create.content.redstone.diodes.PulseTimerBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; -import com.simibubi.create.content.redstone.displayLink.DisplayLinkRenderer; -import com.simibubi.create.content.redstone.displayLink.source.NixieTubeDisplaySource; -import com.simibubi.create.content.redstone.displayLink.target.NixieTubeDisplayTarget; +import com.simibubi.create.content.redstone.displayLink.LinkBulbRenderer; import com.simibubi.create.content.redstone.link.RedstoneLinkBlockEntity; import com.simibubi.create.content.redstone.link.controller.LecternControllerBlockEntity; import com.simibubi.create.content.redstone.link.controller.LecternControllerRenderer; @@ -235,14 +250,14 @@ public class AllBlockEntityTypes { // Kinetics public static final BlockEntityEntry BRACKETED_KINETIC = REGISTRATE .blockEntity("simple_kinetic", BracketedKineticBlockEntity::new) - .visual(() -> BracketedKineticBlockEntityVisual::new, false) + .visual(() -> BracketedKineticBlockEntityVisual::create, false) .validBlocks(AllBlocks.SHAFT, AllBlocks.COGWHEEL, AllBlocks.LARGE_COGWHEEL) .renderer(() -> BracketedKineticBlockEntityRenderer::new) .register(); public static final BlockEntityEntry MOTOR = REGISTRATE .blockEntity("motor", CreativeMotorBlockEntity::new) - .visual(() -> HalfShaftVisual::new, false) + .visual(() -> OrientedRotatingVisual.of(AllPartialModels.SHAFT_HALF), false) .validBlocks(AllBlocks.CREATIVE_MOTOR) .renderer(() -> CreativeMotorRenderer::new) .register(); @@ -256,7 +271,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry ENCASED_SHAFT = REGISTRATE .blockEntity("encased_shaft", KineticBlockEntity::new) - .visual(() -> ShaftVisual::new, false) + .visual(() -> SingleAxisRotatingVisual::shaft, false) .validBlocks(AllBlocks.ANDESITE_ENCASED_SHAFT, AllBlocks.BRASS_ENCASED_SHAFT, AllBlocks.ENCASED_CHAIN_DRIVE, AllBlocks.METAL_GIRDER_ENCASED_SHAFT) .renderer(() -> ShaftRenderer::new) @@ -278,7 +293,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry ADJUSTABLE_CHAIN_GEARSHIFT = REGISTRATE .blockEntity("adjustable_chain_gearshift", ChainGearshiftBlockEntity::new) - .visual(() -> ShaftVisual::new, false) + .visual(() -> SingleAxisRotatingVisual::shaft, false) .validBlocks(AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT) .renderer(() -> ShaftRenderer::new) .register(); @@ -312,7 +327,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry TURNTABLE = REGISTRATE .blockEntity("turntable", TurntableBlockEntity::new) - .visual(() -> SingleRotatingVisual::new, false) + .visual(() -> SingleAxisRotatingVisual.of(AllPartialModels.TURNTABLE), false) .validBlocks(AllBlocks.TURNTABLE) .renderer(() -> KineticBlockEntityRenderer::new) .register(); @@ -326,7 +341,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry VALVE_HANDLE = REGISTRATE .blockEntity("valve_handle", ValveHandleBlockEntity::new) - .visual(() -> HandCrankVisual::new) + .visual(() -> ValveHandleVisual::new) .validBlocks(AllBlocks.COPPER_VALVE_HANDLE) .validBlocks(AllBlocks.DYED_VALVE_HANDLES.toArray()) .renderer(() -> HandCrankRenderer::new) @@ -334,14 +349,14 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry CUCKOO_CLOCK = REGISTRATE .blockEntity("cuckoo_clock", CuckooClockBlockEntity::new) - .visual(() -> HorizontalHalfShaftVisual::new) + .visual(() -> OrientedRotatingVisual.backHorizontal(AllPartialModels.SHAFT_HALF)) .validBlocks(AllBlocks.CUCKOO_CLOCK, AllBlocks.MYSTERIOUS_CUCKOO_CLOCK) .renderer(() -> CuckooClockRenderer::new) .register(); public static final BlockEntityEntry GANTRY_SHAFT = REGISTRATE .blockEntity("gantry_shaft", GantryShaftBlockEntity::new) - .visual(() -> SingleRotatingVisual::new, false) + .visual(() -> OrientedRotatingVisual::gantryShaft, false) .validBlocks(AllBlocks.GANTRY_SHAFT) .renderer(() -> KineticBlockEntityRenderer::new) .register(); @@ -353,9 +368,16 @@ public class AllBlockEntityTypes { .renderer(() -> GantryCarriageRenderer::new) .register(); + public static final BlockEntityEntry CHAIN_CONVEYOR = REGISTRATE + .blockEntity("chain_conveyor", ChainConveyorBlockEntity::new) + .visual(() -> ChainConveyorVisual::new) + .validBlocks(AllBlocks.CHAIN_CONVEYOR) + .renderer(() -> ChainConveyorRenderer::new) + .register(); + public static final BlockEntityEntry MECHANICAL_PUMP = REGISTRATE .blockEntity("mechanical_pump", PumpBlockEntity::new) - .visual(() -> PumpCogVisual::new) + .visual(() -> SingleAxisRotatingVisual.ofZ(AllPartialModels.MECHANICAL_PUMP_COG)) .validBlocks(AllBlocks.MECHANICAL_PUMP) .renderer(() -> PumpRenderer::new) .register(); @@ -465,9 +487,67 @@ public class AllBlockEntityTypes { .validBlocks(AllBlocks.ITEM_VAULT) .register(); + public static final BlockEntityEntry ITEM_HATCH = REGISTRATE + .blockEntity("item_hatch", ItemHatchBlockEntity::new) + .validBlocks(AllBlocks.ITEM_HATCH) + .renderer(() -> SmartBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry PACKAGER = REGISTRATE + .blockEntity("packager", PackagerBlockEntity::new) + .visual(() -> PackagerVisual::new, true) + .validBlocks(AllBlocks.PACKAGER) + .renderer(() -> PackagerRenderer::new) + .register(); + + public static final BlockEntityEntry REPACKAGER = REGISTRATE + .blockEntity("repackager", RepackagerBlockEntity::new) + .visual(() -> PackagerVisual::new, true) + .validBlocks(AllBlocks.REPACKAGER) + .renderer(() -> PackagerRenderer::new) + .register(); + + public static final BlockEntityEntry PACKAGE_FROGPORT = REGISTRATE + .blockEntity("package_frogport", FrogportBlockEntity::new) + .visual(() -> FrogportVisual::new, true) + .validBlocks(AllBlocks.PACKAGE_FROGPORT) + .renderer(() -> FrogportRenderer::new) + .register(); + + public static final BlockEntityEntry PACKAGE_POSTBOX = REGISTRATE + .blockEntity("package_postbox", PostboxBlockEntity::new) + .validBlocks(AllBlocks.PACKAGE_POSTBOXES.toArray()) + .renderer(() -> PostboxRenderer::new) + .register(); + + public static final BlockEntityEntry TABLE_CLOTH = + REGISTRATE.blockEntity("table_cloth", TableClothBlockEntity::new) + .validBlocks(AllBlocks.TABLE_CLOTHS.toArray()) + .validBlock(AllBlocks.ANDESITE_TABLE_CLOTH) + .validBlock(AllBlocks.BRASS_TABLE_CLOTH) + .validBlock(AllBlocks.COPPER_TABLE_CLOTH) + .renderer(() -> TableClothRenderer::new) + .register(); + + public static final BlockEntityEntry PACKAGER_LINK = + REGISTRATE.blockEntity("packager_link", PackagerLinkBlockEntity::new) + .validBlocks(AllBlocks.STOCK_LINK) + .renderer(() -> LinkBulbRenderer::new) + .register(); + + public static final BlockEntityEntry STOCK_TICKER = REGISTRATE + .blockEntity("stock_ticker", StockTickerBlockEntity::new) + .validBlocks(AllBlocks.STOCK_TICKER) + .register(); + + public static final BlockEntityEntry REDSTONE_REQUESTER = REGISTRATE + .blockEntity("redstone_requester", RedstoneRequesterBlockEntity::new) + .validBlocks(AllBlocks.REDSTONE_REQUESTER) + .register(); + public static final BlockEntityEntry MECHANICAL_PISTON = REGISTRATE .blockEntity("mechanical_piston", MechanicalPistonBlockEntity::new) - .visual(() -> ShaftVisual::new, false) + .visual(() -> SingleAxisRotatingVisual::shaft, false) .validBlocks(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) .renderer(() -> MechanicalPistonRenderer::new) .register(); @@ -502,7 +582,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry ELEVATOR_PULLEY = REGISTRATE.blockEntity("elevator_pulley", ElevatorPulleyBlockEntity::new) -// .instance(() -> ElevatorPulleyInstance::new, false) + .visual(() -> ElevatorPulleyVisual::new, false) .validBlocks(AllBlocks.ELEVATOR_PULLEY) .renderer(() -> ElevatorPulleyRenderer::new) .register(); @@ -533,7 +613,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry DRILL = REGISTRATE .blockEntity("drill", DrillBlockEntity::new) - .visual(() -> DrillVisual::new, false) + .visual(() -> OrientedRotatingVisual.of(AllPartialModels.DRILL_HEAD), false) .validBlocks(AllBlocks.MECHANICAL_DRILL) .renderer(() -> DrillRenderer::new) .register(); @@ -588,7 +668,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry POWERED_SHAFT = REGISTRATE .blockEntity("powered_shaft", PoweredShaftBlockEntity::new) - .visual(() -> SingleRotatingVisual::new, false) + .visual(() -> SingleAxisRotatingVisual.of(AllPartialModels.POWERED_SHAFT), false) .validBlocks(AllBlocks.POWERED_SHAFT) .renderer(() -> KineticBlockEntityRenderer::new) .register(); @@ -602,14 +682,14 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry MILLSTONE = REGISTRATE .blockEntity("millstone", MillstoneBlockEntity::new) - .visual(() -> MillstoneCogVisual::new, false) + .visual(() -> SingleAxisRotatingVisual.of(AllPartialModels.MILLSTONE_COG), false) .validBlocks(AllBlocks.MILLSTONE) .renderer(() -> MillstoneRenderer::new) .register(); public static final BlockEntityEntry CRUSHING_WHEEL = REGISTRATE .blockEntity("crushing_wheel", CrushingWheelBlockEntity::new) - .visual(() -> SingleRotatingVisual::new, false) + .visual(() -> SingleAxisRotatingVisual.of(AllPartialModels.CRUSHING_WHEEL), false) .validBlocks(AllBlocks.CRUSHING_WHEEL) .renderer(() -> KineticBlockEntityRenderer::new) .register(); @@ -671,7 +751,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry MECHANICAL_CRAFTER = REGISTRATE .blockEntity("mechanical_crafter", MechanicalCrafterBlockEntity::new) - .visual(() -> ShaftlessCogwheelVisual::new) + .visual(() -> SingleAxisRotatingVisual.of(AllPartialModels.SHAFTLESS_COGWHEEL)) .validBlocks(AllBlocks.MECHANICAL_CRAFTER) .renderer(() -> MechanicalCrafterRenderer::new) .register(); @@ -685,7 +765,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry ROTATION_SPEED_CONTROLLER = REGISTRATE .blockEntity("rotation_speed_controller", SpeedControllerBlockEntity::new) - .visual(() -> ShaftVisual::new) + .visual(() -> SingleAxisRotatingVisual::shaft) .validBlocks(AllBlocks.ROTATION_SPEED_CONTROLLER) .renderer(() -> SpeedControllerRenderer::new) .register(); @@ -717,6 +797,12 @@ public class AllBlockEntityTypes { .renderer(() -> PlacardRenderer::new) .register(); + public static final BlockEntityEntry FACTORY_PANEL = + REGISTRATE.blockEntity("factory_panel", FactoryPanelBlockEntity::new) + .validBlocks(AllBlocks.FACTORY_GAUGE) + .renderer(() -> FactoryPanelRenderer::new) + .register(); + public static final BlockEntityEntry CART_ASSEMBLER = REGISTRATE .blockEntity("cart_assembler", CartAssemblerBlockEntity::new) .validBlocks(AllBlocks.CART_ASSEMBLER) @@ -732,17 +818,17 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry NIXIE_TUBE = REGISTRATE .blockEntity("nixie_tube", NixieTubeBlockEntity::new) + .displaySource(AllDisplaySources.NIXIE_TUBE) + .displayTarget(AllDisplayTargets.NIXIE_TUBE) .validBlocks(AllBlocks.ORANGE_NIXIE_TUBE) .validBlocks(AllBlocks.NIXIE_TUBES.toArray()) .renderer(() -> NixieTubeRenderer::new) - .onRegister(assignDataBehaviourBE(new NixieTubeDisplayTarget())) - .onRegister(assignDataBehaviourBE(new NixieTubeDisplaySource())) .register(); public static final BlockEntityEntry DISPLAY_LINK = REGISTRATE .blockEntity("display_link", DisplayLinkBlockEntity::new) .validBlocks(AllBlocks.DISPLAY_LINK) - .renderer(() -> DisplayLinkRenderer::new) + .renderer(() -> LinkBulbRenderer::new) .register(); public static final BlockEntityEntry THRESHOLD_SWITCH = REGISTRATE @@ -798,6 +884,13 @@ public class AllBlockEntityTypes { .renderer(() -> BrassDiodeRenderer::new) .register(); + public static final BlockEntityEntry PULSE_TIMER = REGISTRATE + .blockEntity("pulse_timer", PulseTimerBlockEntity::new) + .visual(() -> BrassDiodeVisual::new, false) + .validBlocks(AllBlocks.PULSE_TIMER) + .renderer(() -> BrassDiodeRenderer::new) + .register(); + public static final BlockEntityEntry LECTERN_CONTROLLER = REGISTRATE .blockEntity("lectern_controller", LecternControllerBlockEntity::new) .validBlocks(AllBlocks.LECTERN_CONTROLLER) @@ -807,7 +900,7 @@ public class AllBlockEntityTypes { // Curiosities public static final BlockEntityEntry BACKTANK = REGISTRATE .blockEntity("backtank", BacktankBlockEntity::new) - .visual(() -> BacktankVisual::new) + .visual(() -> SingleAxisRotatingVisual::backtank) .validBlocks(AllBlocks.COPPER_BACKTANK, AllBlocks.NETHERITE_BACKTANK) .renderer(() -> BacktankRenderer::new) .register(); @@ -824,6 +917,12 @@ public class AllBlockEntityTypes { .renderer(() -> BellRenderer::new) .register(); + public static final BlockEntityEntry DESK_BELL = REGISTRATE + .blockEntity("desk_bell", DeskBellBlockEntity::new) + .validBlocks(AllBlocks.DESK_BELL) + .renderer(() -> DeskBellRenderer::new) + .register(); + public static final BlockEntityEntry TOOLBOX = REGISTRATE .blockEntity("toolbox", ToolboxBlockEntity::new) .visual(() -> ToolBoxVisual::new, false) @@ -870,7 +969,7 @@ public class AllBlockEntityTypes { public static final BlockEntityEntry FLAP_DISPLAY = REGISTRATE .blockEntity("flap_display", FlapDisplayBlockEntity::new) - .visual(() -> ShaftlessCogwheelVisual::new) + .visual(() -> SingleAxisRotatingVisual.of(AllPartialModels.SHAFTLESS_COGWHEEL)) .renderer(() -> FlapDisplayRenderer::new) .validBlocks(AllBlocks.DISPLAY_BOARD) .register(); diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index bc794ecc36..bc286d0d13 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -1,12 +1,12 @@ package com.simibubi.create; -import static com.simibubi.create.AllInteractionBehaviours.interactionBehaviour; -import static com.simibubi.create.AllMovementBehaviours.movementBehaviour; import static com.simibubi.create.Create.REGISTRATE; - -import com.simibubi.create.api.contraption.train.TrainConductorHandler; - -import static com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours.assignDataBehaviour; +import static com.simibubi.create.api.behaviour.display.DisplaySource.displaySource; +import static com.simibubi.create.api.behaviour.display.DisplayTarget.displayTarget; +import static com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour.interactionBehaviour; +import static com.simibubi.create.api.behaviour.movement.MovementBehaviour.movementBehaviour; +import static com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType.mountedFluidStorage; +import static com.simibubi.create.api.contraption.storage.item.MountedItemStorageType.mountedItemStorage; import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock; import static com.simibubi.create.foundation.data.BlockStateGen.simpleCubeAll; import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; @@ -18,6 +18,8 @@ import static com.simibubi.create.foundation.data.TagGen.tagBlockAndItem; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.api.behaviour.interaction.ConductorBlockInteractionBehavior; +import com.simibubi.create.api.stress.BlockStressValues; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsBlock; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovingInteraction; @@ -57,8 +59,11 @@ import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock; import com.simibubi.create.content.contraptions.piston.MechanicalPistonHeadBlock; import com.simibubi.create.content.contraptions.piston.PistonExtensionPoleBlock; import com.simibubi.create.content.contraptions.pulley.PulleyBlock; +import com.simibubi.create.content.decoration.CardboardBlock; +import com.simibubi.create.content.decoration.CardboardBlockItem; import com.simibubi.create.content.decoration.MetalLadderBlock; import com.simibubi.create.content.decoration.MetalScaffoldingBlock; +import com.simibubi.create.content.decoration.RoofBlockCTBehaviour; import com.simibubi.create.content.decoration.TrainTrapdoorBlock; import com.simibubi.create.content.decoration.TrapdoorCTBehaviour; import com.simibubi.create.content.decoration.bracket.BracketBlock; @@ -105,10 +110,11 @@ import com.simibubi.create.content.fluids.tank.FluidTankBlock; import com.simibubi.create.content.fluids.tank.FluidTankGenerator; import com.simibubi.create.content.fluids.tank.FluidTankItem; import com.simibubi.create.content.fluids.tank.FluidTankModel; -import com.simibubi.create.content.kinetics.BlockStressDefaults; +import com.simibubi.create.content.fluids.tank.FluidTankMovementBehavior; import com.simibubi.create.content.kinetics.belt.BeltBlock; import com.simibubi.create.content.kinetics.belt.BeltGenerator; import com.simibubi.create.content.kinetics.belt.BeltModel; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlock; import com.simibubi.create.content.kinetics.chainDrive.ChainDriveBlock; import com.simibubi.create.content.kinetics.chainDrive.ChainDriveGenerator; import com.simibubi.create.content.kinetics.chainDrive.ChainGearshiftBlock; @@ -168,6 +174,10 @@ import com.simibubi.create.content.logistics.crate.CreativeCrateBlock; import com.simibubi.create.content.logistics.depot.DepotBlock; import com.simibubi.create.content.logistics.depot.EjectorBlock; import com.simibubi.create.content.logistics.depot.EjectorItem; +import com.simibubi.create.content.logistics.depot.MountedDepotInteractionBehaviour; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlockItem; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelModel; import com.simibubi.create.content.logistics.funnel.AndesiteFunnelBlock; import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; import com.simibubi.create.content.logistics.funnel.BeltFunnelGenerator; @@ -175,6 +185,19 @@ import com.simibubi.create.content.logistics.funnel.BrassFunnelBlock; import com.simibubi.create.content.logistics.funnel.FunnelGenerator; import com.simibubi.create.content.logistics.funnel.FunnelItem; import com.simibubi.create.content.logistics.funnel.FunnelMovementBehaviour; +import com.simibubi.create.content.logistics.itemHatch.ItemHatchBlock; +import com.simibubi.create.content.logistics.packagePort.PackagePortItem; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportBlock; +import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlock; +import com.simibubi.create.content.logistics.packager.PackagerBlock; +import com.simibubi.create.content.logistics.packager.repackager.RepackagerBlock; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBlockItem; +import com.simibubi.create.content.logistics.packagerLink.PackagerLinkBlock; +import com.simibubi.create.content.logistics.packagerLink.PackagerLinkGenerator; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterBlock; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterBlockItem; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlock; +import com.simibubi.create.content.logistics.tableCloth.TableClothBlock; import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlock; import com.simibubi.create.content.logistics.tunnel.BrassTunnelCTBehaviour; @@ -188,7 +211,6 @@ import com.simibubi.create.content.processing.basin.BasinGenerator; import com.simibubi.create.content.processing.basin.BasinMovementBehaviour; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlockItem; -import com.simibubi.create.content.processing.burner.BlockBasedTrainConductorInteractionBehaviour; import com.simibubi.create.content.processing.burner.BlazeBurnerMovementBehaviour; import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock; import com.simibubi.create.content.redstone.RoseQuartzLampBlock; @@ -196,6 +218,7 @@ import com.simibubi.create.content.redstone.analogLever.AnalogLeverBlock; import com.simibubi.create.content.redstone.contact.ContactMovementBehaviour; import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; import com.simibubi.create.content.redstone.contact.RedstoneContactItem; +import com.simibubi.create.content.redstone.deskBell.DeskBellBlock; import com.simibubi.create.content.redstone.diodes.AbstractDiodeGenerator; import com.simibubi.create.content.redstone.diodes.BrassDiodeBlock; import com.simibubi.create.content.redstone.diodes.BrassDiodeGenerator; @@ -205,25 +228,6 @@ import com.simibubi.create.content.redstone.diodes.ToggleLatchBlock; import com.simibubi.create.content.redstone.diodes.ToggleLatchGenerator; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockItem; -import com.simibubi.create.content.redstone.displayLink.source.AccumulatedItemCountDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.BoilerDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.CurrentFloorDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.EntityNameDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.FillLevelDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.FluidAmountDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.FluidListDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.ItemCountDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.ItemListDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.ItemNameDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.ItemThroughputDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.KineticSpeedDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.KineticStressDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.ObservedTrainNameSource; -import com.simibubi.create.content.redstone.displayLink.source.StationSummaryDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.StopWatchDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.TimeOfDayDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.TrainStatusDisplaySource; -import com.simibubi.create.content.redstone.displayLink.target.DisplayBoardTarget; import com.simibubi.create.content.redstone.link.RedstoneLinkBlock; import com.simibubi.create.content.redstone.link.RedstoneLinkGenerator; import com.simibubi.create.content.redstone.link.controller.LecternControllerBlock; @@ -264,31 +268,34 @@ import com.simibubi.create.foundation.data.ModelGen; import com.simibubi.create.foundation.data.SharedProperties; import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.UncontainableBlockItem; -import com.simibubi.create.foundation.utility.ColorHandlers; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.DyeHelper; +import com.simibubi.create.infrastructure.config.CStress; import com.tterrag.registrate.providers.RegistrateRecipeProvider; import com.tterrag.registrate.providers.loot.RegistrateBlockLootTables; import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.entry.BlockEntry; +import net.createmod.catnip.data.Couple; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.core.registries.Registries; import net.minecraft.data.loot.BlockLootSubProvider; import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.recipes.ShapelessRecipeBuilder; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.BlockTags; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Items; import net.minecraft.world.item.Rarity; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.IronBarsBlock; +import net.minecraft.world.level.block.RedStoneWireBlock; import net.minecraft.world.level.block.RotatedPillarBlock; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockBehaviour; @@ -307,11 +314,13 @@ import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; + import net.minecraftforge.client.model.generators.ConfiguredModel; import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.common.Tags; import net.minecraftforge.common.util.ForgeSoundType; +@SuppressWarnings("removal") public class AllBlocks { static { @@ -333,7 +342,7 @@ public class AllBlocks { .when(survivesExplosion) .setRolls(ConstantValue.exactly(1)) .add(LootItem.lootTableItem(AllBlocks.SCHEMATICANNON.get() - .asItem()) + .asItem()) .apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) .copy("Options", "BlockEntityTag.Options"))))); }) @@ -344,7 +353,8 @@ public class AllBlocks { public static final BlockEntry SCHEMATIC_TABLE = REGISTRATE.block("schematic_table", SchematicTableBlock::new) .initialProperties(() -> Blocks.LECTERN) - .properties(p -> p.mapColor(MapColor.PODZOL).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.PODZOL) + .forceSolidOn()) .transform(axeOrPickaxe()) .blockstate((ctx, prov) -> prov.horizontalBlock(ctx.getEntry(), prov.models() .getExistingFile(ctx.getId()), 0)) @@ -355,8 +365,8 @@ public class AllBlocks { public static final BlockEntry SHAFT = REGISTRATE.block("shaft", ShaftBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.METAL).forceSolidOn()) - .transform(BlockStressDefaults.setNoImpact()) + .properties(p -> p.mapColor(MapColor.METAL).forceSolidOff()) + .transform(CStress.setNoImpact()) .transform(pickaxeOnly()) .blockstate(BlockStateGen.axisBlockProvider(false)) .onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new)) @@ -365,8 +375,9 @@ public class AllBlocks { public static final BlockEntry COGWHEEL = REGISTRATE.block("cogwheel", CogWheelBlock::small) .initialProperties(SharedProperties::stone) - .properties(p -> p.sound(SoundType.WOOD).mapColor(MapColor.DIRT)) - .transform(BlockStressDefaults.setNoImpact()) + .properties(p -> p.sound(SoundType.WOOD) + .mapColor(MapColor.DIRT)) + .transform(CStress.setNoImpact()) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.axisBlockProvider(false)) .onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new)) @@ -377,9 +388,10 @@ public class AllBlocks { public static final BlockEntry LARGE_COGWHEEL = REGISTRATE.block("large_cogwheel", CogWheelBlock::large) .initialProperties(SharedProperties::stone) - .properties(p -> p.sound(SoundType.WOOD).mapColor(MapColor.DIRT)) + .properties(p -> p.sound(SoundType.WOOD) + .mapColor(MapColor.DIRT)) .transform(axeOrPickaxe()) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .blockstate(BlockStateGen.axisBlockProvider(false)) .onRegister(CreateRegistrate.blockModel(() -> BracketedKineticBlockModel::new)) .item(CogwheelBlockItem::new) @@ -443,8 +455,9 @@ public class AllBlocks { public static final BlockEntry GEARBOX = REGISTRATE.block("gearbox", GearboxBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL)) - .transform(BlockStressDefaults.setNoImpact()) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.PODZOL)) + .transform(CStress.setNoImpact()) .transform(axeOrPickaxe()) .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.ANDESITE_CASING))) .onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, AllSpriteShifts.ANDESITE_CASING, @@ -456,9 +469,10 @@ public class AllBlocks { public static final BlockEntry CLUTCH = REGISTRATE.block("clutch", ClutchBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.PODZOL)) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .transform(axeOrPickaxe()) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, AssetLookup.forPowered(c, p))) .item() @@ -467,9 +481,10 @@ public class AllBlocks { public static final BlockEntry GEARSHIFT = REGISTRATE.block("gearshift", GearshiftBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.PODZOL)) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .transform(axeOrPickaxe()) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, AssetLookup.forPowered(c, p))) .item() @@ -479,8 +494,9 @@ public class AllBlocks { public static final BlockEntry ENCASED_CHAIN_DRIVE = REGISTRATE.block("encased_chain_drive", ChainDriveBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL)) - .transform(BlockStressDefaults.setNoImpact()) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.PODZOL)) + .transform(CStress.setNoImpact()) .transform(axeOrPickaxe()) .blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> p.models() .getExistingFile(p.modLoc("block/" + c.getName() + "/" + suffix))).generate(c, p)) @@ -491,8 +507,9 @@ public class AllBlocks { public static final BlockEntry ADJUSTABLE_CHAIN_GEARSHIFT = REGISTRATE.block("adjustable_chain_gearshift", ChainGearshiftBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.NETHER)) - .transform(BlockStressDefaults.setNoImpact()) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.NETHER)) + .transform(CStress.setNoImpact()) .transform(axeOrPickaxe()) .blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> { String powered = state.getValue(ChainGearshiftBlock.POWERED) ? "_powered" : ""; @@ -514,20 +531,34 @@ public class AllBlocks { .addLayer(() -> RenderType::cutoutMipped) .transform(axeOrPickaxe()) .blockstate(new BeltGenerator()::generate) - .transform(BlockStressDefaults.setImpact(0)) - .onRegister(assignDataBehaviour(new ItemNameDisplaySource(), "combine_item_names")) + .transform(CStress.setNoImpact()) + .transform(displaySource(AllDisplaySources.ITEM_NAMES)) .onRegister(CreateRegistrate.blockModel(() -> BeltModel::new)) .register(); + public static final BlockEntry CHAIN_CONVEYOR = + REGISTRATE.block("chain_conveyor", ChainConveyorBlock::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.PODZOL)) + .transform(axeOrPickaxe()) + .transform(CStress.setImpact(1)) + .transform(CStress.setImpact(1)) + .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) + .item() + .transform(customItemModel()) + .register(); + public static final BlockEntry CREATIVE_MOTOR = REGISTRATE.block("creative_motor", CreativeMotorBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.COLOR_PURPLE).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.COLOR_PURPLE) + .forceSolidOn()) .tag(AllBlockTags.SAFE_NBT.tag) .transform(pickaxeOnly()) .blockstate(new CreativeMotorGenerator()::generate) - .transform(BlockStressDefaults.setCapacity(16384.0)) - .transform(BlockStressDefaults.setGeneratorSpeed(() -> Couple.create(0, 256))) + .transform(CStress.setCapacity(16384.0)) + .onRegister(BlockStressValues.setGeneratorSpeed(256, true)) .item() .properties(p -> p.rarity(Rarity.EPIC)) .transform(customItemModel()) @@ -535,13 +566,14 @@ public class AllBlocks { public static final BlockEntry WATER_WHEEL = REGISTRATE.block("water_wheel", WaterWheelBlock::new) .initialProperties(SharedProperties::wooden) - .properties(p -> p.noOcclusion().mapColor(MapColor.DIRT)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.DIRT)) .transform(axeOrPickaxe()) .blockstate( (c, p) -> BlockStateGen.directionalBlockIgnoresWaterlogged(c, p, s -> AssetLookup.partialBaseModel(c, p))) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setCapacity(32.0)) - .transform(BlockStressDefaults.setGeneratorSpeed(WaterWheelBlock::getSpeedRange)) + .transform(CStress.setCapacity(32)) + .onRegister(BlockStressValues.setGeneratorSpeed(8)) .item() .transform(customItemModel()) .register(); @@ -549,13 +581,14 @@ public class AllBlocks { public static final BlockEntry LARGE_WATER_WHEEL = REGISTRATE.block("large_water_wheel", LargeWaterWheelBlock::new) .initialProperties(SharedProperties::wooden) - .properties(p -> p.noOcclusion().mapColor(MapColor.DIRT)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.DIRT)) .transform(axeOrPickaxe()) .blockstate((c, p) -> axisBlock(c, p, s -> s.getValue(LargeWaterWheelBlock.EXTENSION) ? AssetLookup.partialBaseModel(c, p, "extension") : AssetLookup.partialBaseModel(c, p))) - .transform(BlockStressDefaults.setCapacity(128.0)) - .transform(BlockStressDefaults.setGeneratorSpeed(LargeWaterWheelBlock::getSpeedRange)) + .transform(CStress.setCapacity(128.0)) + .onRegister(BlockStressValues.setGeneratorSpeed(4)) .item(LargeWaterWheelBlockItem::new) .transform(customItemModel()) .register(); @@ -565,7 +598,8 @@ public class AllBlocks { .initialProperties(SharedProperties::wooden) .blockstate((c, p) -> p.getVariantBuilder(c.get()) .forAllStatesExcept(BlockStateGen.mapToAir(p), WaterWheelStructuralBlock.FACING)) - .properties(p -> p.noOcclusion().mapColor(MapColor.DIRT)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.DIRT)) .transform(axeOrPickaxe()) .lang("Large Water Wheel") .register(); @@ -576,7 +610,7 @@ public class AllBlocks { .blockstate(BlockStateGen.directionalBlockProvider(true)) .addLayer(() -> RenderType::cutoutMipped) .transform(axeOrPickaxe()) - .transform(BlockStressDefaults.setImpact(2.0)) + .transform(CStress.setImpact(2.0)) .item() .transform(customItemModel()) .register(); @@ -597,7 +631,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.standardModel(c, p))) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .simpleItem() .register(); @@ -606,8 +640,8 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.directionalBlockProvider(true)) - .transform(BlockStressDefaults.setCapacity(8.0)) - .transform(BlockStressDefaults.setGeneratorSpeed(HandCrankBlock::getSpeedRange)) + .transform(CStress.setCapacity(8.0)) + .onRegister(BlockStressValues.setGeneratorSpeed(32)) .tag(AllBlockTags.BRITTLE.tag) .onRegister(ItemUseOverrides::addBlock) .item() @@ -619,8 +653,8 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .transform(axeOrPickaxe()) .transform(BuilderTransformers.cuckooClock()) - .onRegister(assignDataBehaviour(new TimeOfDayDisplaySource(), "time_of_day")) - .onRegister(assignDataBehaviour(new StopWatchDisplaySource(), "stop_watch")) + .transform(displaySource(AllDisplaySources.TIME_OF_DAY)) + .transform(displaySource(AllDisplaySources.STOPWATCH)) .register(); public static final BlockEntry MYSTERIOUS_CUCKOO_CLOCK = @@ -637,7 +671,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.METAL)) .transform(pickaxeOnly()) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .item() .transform(customItemModel()) .register(); @@ -650,7 +684,7 @@ public class AllBlocks { .transform(pickaxeOnly()) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, s -> AssetLookup.partialBaseModel(c, p))) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setImpact(8.0)) + .transform(CStress.setImpact(8.0)) .item() .transform(customItemModel()) .register(); @@ -670,10 +704,11 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_PRESS = REGISTRATE.block("mechanical_press", MechanicalPressBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(BlockStressDefaults.setImpact(8.0)) + .transform(CStress.setImpact(8.0)) .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); @@ -681,18 +716,20 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_MIXER = REGISTRATE.block("mechanical_mixer", MechanicalMixerBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.STONE)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.STONE)) .transform(axeOrPickaxe()) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); public static final BlockEntry BASIN = REGISTRATE.block("basin", BasinBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.mapColor(MapColor.COLOR_GRAY) + .sound(SoundType.NETHERITE_BLOCK)) .transform(pickaxeOnly()) .blockstate(new BasinGenerator()::generate) .addLayer(() -> RenderType::cutoutMipped) @@ -704,14 +741,16 @@ public class AllBlocks { public static final BlockEntry BLAZE_BURNER = REGISTRATE.block("blaze_burner", BlazeBurnerBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.COLOR_GRAY).lightLevel(BlazeBurnerBlock::getLight)) + .properties(p -> p.mapColor(MapColor.COLOR_GRAY) + .lightLevel(BlazeBurnerBlock::getLight)) .transform(pickaxeOnly()) .addLayer(() -> RenderType::cutoutMipped) - .tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_BLASTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) + .tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_BLASTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, + AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) .loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable())) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour())) - .onRegister(block -> TrainConductorHandler.registerBlazeBurner()) + .onRegister(interactionBehaviour(new ConductorBlockInteractionBehavior.BlazeBurner())) .item(BlazeBurnerBlockItem::withBlaze) .model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze")) .build() @@ -720,18 +759,20 @@ public class AllBlocks { public static final BlockEntry LIT_BLAZE_BURNER = REGISTRATE.block("lit_blaze_burner", LitBlazeBurnerBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.COLOR_LIGHT_GRAY).lightLevel(LitBlazeBurnerBlock::getLight)) + .properties(p -> p.mapColor(MapColor.COLOR_LIGHT_GRAY) + .lightLevel(LitBlazeBurnerBlock::getLight)) .transform(pickaxeOnly()) .addLayer(() -> RenderType::cutoutMipped) - .tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_HAUNTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) + .tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_HAUNTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, + AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) .loot((lt, block) -> lt.dropOther(block, AllItems.EMPTY_BLAZE_BURNER.get())) .blockstate((c, p) -> p.getVariantBuilder(c.get()) .forAllStates(state -> ConfiguredModel.builder() .modelFile(p.models() .getExistingFile(p.modLoc("block/blaze_burner/" + (state.getValue(LitBlazeBurnerBlock.FLAME_TYPE) == LitBlazeBurnerBlock.FlameType.SOUL - ? "block_with_soul_fire" - : "block_with_fire")))) + ? "block_with_soul_fire" + : "block_with_fire")))) .build())) .register(); @@ -740,7 +781,9 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .transform(axeOrPickaxe()) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) - .onRegister(assignDataBehaviour(new ItemNameDisplaySource(), "combine_item_names")) + .transform(displaySource(AllDisplaySources.ITEM_NAMES)) + .onRegister(interactionBehaviour(new MountedDepotInteractionBehaviour())) + .transform(mountedItemStorage(AllMountedStorageTypes.DEPOT)) .item() .transform(customItemModel("_", "block")) .register(); @@ -748,18 +791,23 @@ public class AllBlocks { public static final BlockEntry WEIGHTED_EJECTOR = REGISTRATE.block("weighted_ejector", EjectorBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_GRAY)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.COLOR_GRAY)) .transform(axeOrPickaxe()) .blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180)) - .transform(BlockStressDefaults.setImpact(2.0)) - .onRegister(assignDataBehaviour(new ItemNameDisplaySource(), "combine_item_names")) + .transform(CStress.setImpact(2.0)) + .transform(displaySource(AllDisplaySources.ITEM_NAMES)) .item(EjectorItem::new) .transform(customItemModel()) .register(); public static final BlockEntry CHUTE = REGISTRATE.block("chute", ChuteBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.mapColor(MapColor.COLOR_GRAY) + .sound(SoundType.NETHERITE_BLOCK) + .noOcclusion() + .isSuffocating((level, pos, state) -> false) + .isRedstoneConductor((level, pos, state) -> false)) .transform(pickaxeOnly()) .addLayer(() -> RenderType::cutoutMipped) .blockstate(new ChuteGenerator()::generate) @@ -772,6 +820,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.COLOR_GRAY) .sound(SoundType.NETHERITE_BLOCK) .noOcclusion() + .isSuffocating((level, pos, state) -> false) .isRedstoneConductor((level, pos, state) -> false)) .addLayer(() -> RenderType::cutoutMipped) .transform(pickaxeOnly()) @@ -784,9 +833,9 @@ public class AllBlocks { .initialProperties(SharedProperties::wooden) .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .blockstate(new GaugeGenerator()::generate) - .onRegister(assignDataBehaviour(new KineticSpeedDisplaySource(), "kinetic_speed")) + .transform(displaySource(AllDisplaySources.KINETIC_SPEED)) .item() .transform(ModelGen.customItemModel("gauge", "_", "item")) .register(); @@ -795,9 +844,9 @@ public class AllBlocks { .initialProperties(SharedProperties::wooden) .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .blockstate(new GaugeGenerator()::generate) - .onRegister(assignDataBehaviour(new KineticStressDisplaySource(), "kinetic_stress")) + .transform(displaySource(AllDisplaySources.KINETIC_STRESS)) .item() .transform(ModelGen.customItemModel("gauge", "_", "item")) .register(); @@ -807,6 +856,7 @@ public class AllBlocks { .properties(p -> p.sound(SoundType.SCAFFOLDING)) .transform(axeOrPickaxe()) .item(BracketBlockItem::new) + .tag(AllItemTags.INVALID_FOR_TRACK_PAVING.tag) .transform(BracketGenerator.itemModel("wooden")) .register(); @@ -815,6 +865,7 @@ public class AllBlocks { .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .transform(pickaxeOnly()) .item(BracketBlockItem::new) + .tag(AllItemTags.INVALID_FOR_TRACK_PAVING.tag) .transform(BracketGenerator.itemModel("metal")) .register(); @@ -822,10 +873,10 @@ public class AllBlocks { public static final BlockEntry FLUID_PIPE = REGISTRATE.block("fluid_pipe", FluidPipeBlock::new) .initialProperties(SharedProperties::copperMetal) - .properties(p -> p.forceSolidOn()) + .properties(p -> p.forceSolidOff()) .transform(pickaxeOnly()) .blockstate(BlockStateGen.pipe()) - .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) + .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::withoutAO)) .item() .transform(customItemModel()) .register(); @@ -833,13 +884,14 @@ public class AllBlocks { public static final BlockEntry ENCASED_FLUID_PIPE = REGISTRATE.block("encased_fluid_pipe", p -> new EncasedPipeBlock(p, AllBlocks.COPPER_CASING::get)) .initialProperties(SharedProperties::copperMetal) - .properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_LIGHT_GRAY)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.TERRACOTTA_LIGHT_GRAY)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.encasedPipe()) .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.COPPER_CASING))) .onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, AllSpriteShifts.COPPER_CASING, (s, f) -> !s.getValue(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(f))))) - .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) + .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::withAO)) .loot((p, b) -> p.dropOther(b, FLUID_PIPE.get())) .transform(EncasingRegistry.addVariantTo(AllBlocks.FLUID_PIPE)) .register(); @@ -847,7 +899,7 @@ public class AllBlocks { public static final BlockEntry GLASS_FLUID_PIPE = REGISTRATE.block("glass_fluid_pipe", GlassFluidPipeBlock::new) .initialProperties(SharedProperties::copperMetal) - .properties(p -> p.forceSolidOn()) + .properties(p -> p.noOcclusion()) .addLayer(() -> RenderType::cutoutMipped) .transform(pickaxeOnly()) .blockstate((c, p) -> { @@ -863,7 +915,7 @@ public class AllBlocks { .build(); }, BlockStateProperties.WATERLOGGED); }) - .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) + .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::withoutAO)) .loot((p, b) -> p.dropOther(b, FLUID_PIPE.get())) .register(); @@ -872,8 +924,8 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.STONE)) .transform(pickaxeOnly()) .blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(true)) - .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) - .transform(BlockStressDefaults.setImpact(4.0)) + .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::withoutAO)) + .transform(CStress.setImpact(4.0)) .item() .transform(customItemModel()) .register(); @@ -884,7 +936,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .transform(pickaxeOnly()) .blockstate(new SmartFluidPipeGenerator()::generate) - .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) + .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::withoutAO)) .item() .transform(customItemModel()) .register(); @@ -892,10 +944,11 @@ public class AllBlocks { public static final BlockEntry FLUID_VALVE = REGISTRATE.block("fluid_valve", FluidValveBlock::new) .initialProperties(SharedProperties::copperMetal) .transform(pickaxeOnly()) + .addLayer(() -> RenderType::cutoutMipped) .blockstate((c, p) -> BlockStateGen.directionalAxisBlock(c, p, (state, vertical) -> AssetLookup.partialBaseModel(c, p, vertical ? "vertical" : "horizontal", state.getValue(FluidValveBlock.ENABLED) ? "open" : "closed"))) - .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) + .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::withoutAO)) .item() .transform(customItemModel()) .register(); @@ -904,7 +957,7 @@ public class AllBlocks { REGISTRATE.block("copper_valve_handle", ValveHandleBlock::copper) .transform(pickaxeOnly()) .transform(BuilderTransformers.valveHandle(null)) - .transform(BlockStressDefaults.setCapacity(8.0)) + .transform(CStress.setCapacity(8.0)) .register(); public static final DyedBlockList DYED_VALVE_HANDLES = new DyedBlockList<>(colour -> { @@ -923,11 +976,14 @@ public class AllBlocks { public static final BlockEntry FLUID_TANK = REGISTRATE.block("fluid_tank", FluidTankBlock::regular) .initialProperties(SharedProperties::copperMetal) - .properties(p -> p.noOcclusion().isRedstoneConductor((p1, p2, p3) -> true)) + .properties(p -> p.noOcclusion() + .isRedstoneConductor((p1, p2, p3) -> true)) .transform(pickaxeOnly()) .blockstate(new FluidTankGenerator()::generate) .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard)) - .onRegister(assignDataBehaviour(new BoilerDisplaySource(), "boiler_status")) + .transform(displaySource(AllDisplaySources.BOILER)) + .transform(mountedFluidStorage(AllMountedStorageTypes.FLUID_TANK)) + .onRegister(movementBehaviour(new FluidTankMovementBehavior())) .addLayer(() -> RenderType::cutoutMipped) .item(FluidTankItem::new) .model(AssetLookup.customBlockItemModel("_", "block_single_window")) @@ -937,11 +993,13 @@ public class AllBlocks { public static final BlockEntry CREATIVE_FLUID_TANK = REGISTRATE.block("creative_fluid_tank", FluidTankBlock::creative) .initialProperties(SharedProperties::copperMetal) - .properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_PURPLE)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.COLOR_PURPLE)) .transform(pickaxeOnly()) .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(new FluidTankGenerator("creative_")::generate) .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::creative)) + .transform(mountedFluidStorage(AllMountedStorageTypes.CREATIVE_FLUID_TANK)) .addLayer(() -> RenderType::cutoutMipped) .item(FluidTankItem::new) .properties(p -> p.rarity(Rarity.EPIC)) @@ -957,9 +1015,10 @@ public class AllBlocks { public static final BlockEntry HOSE_PULLEY = REGISTRATE.block("hose_pulley", HosePulleyBlock::new) .initialProperties(SharedProperties::copperMetal) .properties(BlockBehaviour.Properties::noOcclusion) + .addLayer(() -> RenderType::cutoutMipped) .transform(pickaxeOnly()) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .item() .transform(customItemModel()) .register(); @@ -998,8 +1057,8 @@ public class AllBlocks { .initialProperties(SharedProperties::copperMetal) .transform(pickaxeOnly()) .blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.partialBaseModel(c, p))) - .transform(BlockStressDefaults.setCapacity(1024.0)) - .transform(BlockStressDefaults.setGeneratorSpeed(SteamEngineBlock::getSpeedRange)) + .transform(CStress.setCapacity(1024.0)) + .onRegister(BlockStressValues.setGeneratorSpeed(64, true)) .item() .transform(customItemModel()) .register(); @@ -1016,7 +1075,8 @@ public class AllBlocks { public static final BlockEntry STEAM_WHISTLE_EXTENSION = REGISTRATE.block("steam_whistle_extension", WhistleExtenderBlock::new) .initialProperties(SharedProperties::copperMetal) - .properties(p -> p.mapColor(MapColor.GOLD).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.GOLD) + .forceSolidOn()) .transform(pickaxeOnly()) .blockstate(BlockStateGen.whistleExtender()) .register(); @@ -1024,7 +1084,8 @@ public class AllBlocks { public static final BlockEntry POWERED_SHAFT = REGISTRATE.block("powered_shaft", PoweredShaftBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.METAL).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.METAL) + .forceSolidOn()) .transform(pickaxeOnly()) .blockstate(BlockStateGen.axisBlockProvider(false)) .loot((lt, block) -> lt.dropOther(block, AllBlocks.SHAFT.get())) @@ -1051,7 +1112,9 @@ public class AllBlocks { public static final BlockEntry PISTON_EXTENSION_POLE = REGISTRATE.block("piston_extension_pole", PistonExtensionPoleBlock::new) .initialProperties(() -> Blocks.PISTON_HEAD) - .properties(p -> p.sound(SoundType.SCAFFOLDING).mapColor(MapColor.DIRT).forceSolidOn()) + .properties(p -> p.sound(SoundType.SCAFFOLDING) + .mapColor(MapColor.DIRT) + .forceSolidOn()) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(false)) .simpleItem() @@ -1071,7 +1134,8 @@ public class AllBlocks { public static final BlockEntry GANTRY_CARRIAGE = REGISTRATE.block("gantry_carriage", GantryCarriageBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.directionalAxisBlockProvider()) .item() @@ -1081,7 +1145,8 @@ public class AllBlocks { public static final BlockEntry GANTRY_SHAFT = REGISTRATE.block("gantry_shaft", GantryShaftBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.NETHER).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.NETHER) + .forceSolidOn()) .transform(axeOrPickaxe()) .blockstate((c, p) -> p.directionalBlock(c.get(), s -> { boolean isPowered = s.getValue(GantryShaftBlock.POWERED); @@ -1099,7 +1164,7 @@ public class AllBlocks { existing.getLocation()) .texture("2", p.modLoc("block/" + c.getName() + powered + flipped)); })) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .item() .transform(customItemModel("_", "block_single")) .register(); @@ -1109,8 +1174,8 @@ public class AllBlocks { .transform(axeOrPickaxe()) .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(BuilderTransformers.bearing("windmill", "gearbox")) - .transform(BlockStressDefaults.setCapacity(512.0)) - .transform(BlockStressDefaults.setGeneratorSpeed(WindmillBearingBlock::getSpeedRange)) + .transform(CStress.setCapacity(512.0)) + .onRegister(BlockStressValues.setGeneratorSpeed(16, true)) .tag(AllBlockTags.SAFE_NBT.tag) .register(); @@ -1119,7 +1184,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .transform(BuilderTransformers.bearing("mechanical", "gearbox")) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .tag(AllBlockTags.SAFE_NBT.tag) .onRegister(movementBehaviour(new StabilizedBearingMovementBehaviour())) .register(); @@ -1129,17 +1194,19 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN)) .transform(axeOrPickaxe()) .transform(BuilderTransformers.bearing("clockwork", "brass_gearbox")) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .tag(AllBlockTags.SAFE_NBT.tag) .register(); public static final BlockEntry ROPE_PULLEY = REGISTRATE.block("rope_pulley", PulleyBlock::new) .initialProperties(SharedProperties::stone) .properties(p -> p.mapColor(MapColor.PODZOL)) + .properties(p -> p.noOcclusion()) + .addLayer(() -> RenderType::cutoutMipped) .transform(axeOrPickaxe()) .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(BlockStateGen.horizontalAxisBlockProvider(true)) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .item() .transform(customItemModel()) .register(); @@ -1168,7 +1235,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .item() .transform(customItemModel()) .register(); @@ -1176,7 +1243,8 @@ public class AllBlocks { public static final BlockEntry CART_ASSEMBLER = REGISTRATE.block("cart_assembler", CartAssemblerBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_GRAY)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.COLOR_GRAY)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.cartAssembler()) .addLayer(() -> RenderType::cutoutMipped) @@ -1191,7 +1259,8 @@ public class AllBlocks { .transform(pickaxeOnly()) .blockstate(new ControllerRailGenerator()::generate) .addLayer(() -> RenderType::cutoutMipped) - .color(() -> ColorHandlers::getRedstonePower) + .color(() -> () -> (state, world, pos, layer) -> RedStoneWireBlock + .getColorForPower(pos != null && world != null ? state.getValue(BlockStateProperties.POWER) : 0)) .tag(BlockTags.RAILS) .item() .model((c, p) -> p.generated(c, Create.asResource("block/" + c.getName()))) @@ -1271,7 +1340,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.directionalBlockProvider(true)) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .onRegister(movementBehaviour(new DrillMovementBehaviour())) .item() .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) @@ -1284,7 +1353,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate(new SawGenerator()::generate) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .onRegister(movementBehaviour(new SawMovementBehaviour())) .addLayer(() -> RenderType::cutoutMipped) .item() @@ -1297,7 +1366,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.directionalAxisBlockProvider()) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .onRegister(movementBehaviour(new DeployerMovementBehaviour())) .onRegister(interactionBehaviour(new DeployerMovingInteraction())) .item(AssemblyOperatorBlockItem::new) @@ -1332,7 +1401,8 @@ public class AllBlocks { public static final BlockEntry ELEVATOR_CONTACT = REGISTRATE.block("elevator_contact", ElevatorContactBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW).lightLevel(ElevatorContactBlock::getLight)) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW) + .lightLevel(ElevatorContactBlock::getLight)) .transform(axeOrPickaxe()) .blockstate((c, p) -> p.directionalBlock(c.get(), state -> { Boolean calling = state.getValue(ElevatorContactBlock.CALLING); @@ -1341,7 +1411,7 @@ public class AllBlocks { : calling ? AssetLookup.partialBaseModel(c, p, "dim") : AssetLookup.partialBaseModel(c, p); })) .loot((p, b) -> p.dropOther(b, REDSTONE_CONTACT.get())) - .onRegister(assignDataBehaviour(new CurrentFloorDisplaySource(), "current_floor")) + .transform(displaySource(AllDisplaySources.CURRENT_FLOOR)) .item() .transform(customItemModel("_", "block")) .register(); @@ -1349,7 +1419,8 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_HARVESTER = REGISTRATE.block("mechanical_harvester", HarvesterBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.METAL).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.METAL) + .forceSolidOn()) .transform(axeOrPickaxe()) .onRegister(movementBehaviour(new HarvesterMovementBehaviour())) .blockstate(BlockStateGen.horizontalBlockProvider(true)) @@ -1362,7 +1433,8 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_PLOUGH = REGISTRATE.block("mechanical_plough", PloughBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.COLOR_GRAY).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.COLOR_GRAY) + .forceSolidOn()) .transform(axeOrPickaxe()) .onRegister(movementBehaviour(new PloughMovementBehaviour())) .blockstate(BlockStateGen.horizontalBlockProvider(false)) @@ -1442,7 +1514,8 @@ public class AllBlocks { .register(); public static final BlockEntry COPPER_CASING = REGISTRATE.block("copper_casing", CasingBlock::new) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY).sound(SoundType.COPPER)) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY) + .sound(SoundType.COPPER)) .transform(BuilderTransformers.casing(() -> AllSpriteShifts.COPPER_CASING)) .register(); @@ -1464,10 +1537,11 @@ public class AllBlocks { public static final BlockEntry MECHANICAL_CRAFTER = REGISTRATE.block("mechanical_crafter", MechanicalCrafterBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_YELLOW)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.TERRACOTTA_YELLOW)) .transform(axeOrPickaxe()) .blockstate(BlockStateGen.horizontalBlockProvider(true)) - .transform(BlockStressDefaults.setImpact(2.0)) + .transform(CStress.setImpact(2.0)) .onRegister(CreateRegistrate.connectedTextures(CrafterCTBehaviour::new)) .addLayer(() -> RenderType::cutoutMipped) .item() @@ -1481,7 +1555,7 @@ public class AllBlocks { .transform(axeOrPickaxe()) .tag(AllBlockTags.SAFE_NBT.tag) .properties(BlockBehaviour.Properties::noOcclusion) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .blockstate(new SequencedGearshiftGenerator()::generate) .item() .transform(customItemModel()) @@ -1489,9 +1563,10 @@ public class AllBlocks { public static final BlockEntry FLYWHEEL = REGISTRATE.block("flywheel", FlywheelBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_YELLOW)) + .properties(p -> p.noOcclusion() + .mapColor(MapColor.TERRACOTTA_YELLOW)) .transform(axeOrPickaxe()) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .blockstate(BlockStateGen.axisBlockProvider(true)) .item() .transform(customItemModel()) @@ -1503,7 +1578,7 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .transform(axeOrPickaxe()) .tag(AllBlockTags.SAFE_NBT.tag) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .blockstate(BlockStateGen.horizontalAxisBlockProvider(true)) .item() .transform(customItemModel()) @@ -1520,7 +1595,7 @@ public class AllBlocks { .modelFile(AssetLookup.partialBaseModel(c, p)) .rotationX(s.getValue(ArmBlock.CEILING) ? 180 : 0) .build())) - .transform(BlockStressDefaults.setImpact(2.0)) + .transform(CStress.setImpact(2.0)) .item(ArmItem::new) .transform(customItemModel()) .register(); @@ -1559,17 +1634,19 @@ public class AllBlocks { public static final BlockEntry RAILWAY_CASING = REGISTRATE.block("railway_casing", CasingBlock::new) .transform(BuilderTransformers.layeredCasing(() -> AllSpriteShifts.RAILWAY_CASING_SIDE, () -> AllSpriteShifts.RAILWAY_CASING)) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_CYAN).sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_CYAN) + .sound(SoundType.NETHERITE_BLOCK)) .lang("Train Casing") .register(); public static final BlockEntry TRACK_STATION = REGISTRATE.block("track_station", StationBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.PODZOL).sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.mapColor(MapColor.PODZOL) + .sound(SoundType.NETHERITE_BLOCK)) .transform(pickaxeOnly()) .blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p))) - .onRegister(assignDataBehaviour(new StationSummaryDisplaySource(), "station_summary")) - .onRegister(assignDataBehaviour(new TrainStatusDisplaySource(), "train_status")) + .transform(displaySource(AllDisplaySources.STATION_SUMMARY)) + .transform(displaySource(AllDisplaySources.TRAIN_STATUS)) .lang("Train Station") .item(TrackTargetingBlockItem.ofType(EdgePointType.STATION)) .transform(customItemModel()) @@ -1599,7 +1676,7 @@ public class AllBlocks { .sound(SoundType.NETHERITE_BLOCK)) .blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p))) .transform(pickaxeOnly()) - .onRegister(assignDataBehaviour(new ObservedTrainNameSource(), "observed_train_name")) + .transform(displaySource(AllDisplaySources.OBSERVED_TRAIN_NAME)) .lang("Train Observer") .item(TrackTargetingBlockItem.ofType(EdgePointType.OBSERVER)) .transform(customItemModel("_", "block")) @@ -1619,7 +1696,8 @@ public class AllBlocks { public static final BlockEntry TRAIN_CONTROLS = REGISTRATE.block("controls", ControlsBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN) + .sound(SoundType.NETHERITE_BLOCK)) .addLayer(() -> RenderType::cutoutMipped) .transform(pickaxeOnly()) .blockstate((c, p) -> p.horizontalBlock(c.get(), @@ -1632,21 +1710,6 @@ public class AllBlocks { .transform(customItemModel()) .register(); - public static final BlockEntry ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new) - .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE).sound(SoundType.NETHERITE_BLOCK) - .explosionResistance(1200)) - .transform(pickaxeOnly()) - .blockstate((c, p) -> p.getVariantBuilder(c.get()) - .forAllStates(s -> ConfiguredModel.builder() - .modelFile(AssetLookup.standardModel(c, p)) - .rotationY(s.getValue(ItemVaultBlock.HORIZONTAL_AXIS) == Axis.X ? 90 : 0) - .build())) - .onRegister(connectedTextures(ItemVaultCTBehaviour::new)) - .item(ItemVaultItem::new) - .build() - .register(); - public static final BlockEntry ANDESITE_FUNNEL = REGISTRATE.block("andesite_funnel", AndesiteFunnelBlock::new) .addLayer(() -> RenderType::cutoutMipped) @@ -1703,29 +1766,32 @@ public class AllBlocks { REGISTRATE.block("andesite_tunnel", BeltTunnelBlock::new) .properties(p -> p.mapColor(MapColor.STONE)) .transform(BuilderTransformers.beltTunnel("andesite", new ResourceLocation("block/polished_andesite"))) - .onRegister(assignDataBehaviour(new AccumulatedItemCountDisplaySource(), "accumulate_items")) - .onRegister(assignDataBehaviour(new ItemThroughputDisplaySource(), "item_throughput")) + .transform(displaySource(AllDisplaySources.ACCUMULATE_ITEMS)) + .transform(displaySource(AllDisplaySources.ITEM_THROUGHPUT)) .register(); public static final BlockEntry BRASS_TUNNEL = REGISTRATE.block("brass_tunnel", BrassTunnelBlock::new) .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .transform(BuilderTransformers.beltTunnel("brass", Create.asResource("block/brass_block"))) - .onRegister(assignDataBehaviour(new AccumulatedItemCountDisplaySource(), "accumulate_items")) - .onRegister(assignDataBehaviour(new ItemThroughputDisplaySource(), "item_throughput")) + .transform(displaySource(AllDisplaySources.ACCUMULATE_ITEMS)) + .transform(displaySource(AllDisplaySources.ITEM_THROUGHPUT)) .onRegister(connectedTextures(BrassTunnelCTBehaviour::new)) .register(); public static final BlockEntry SMART_OBSERVER = REGISTRATE.block("content_observer", SmartObserverBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).noOcclusion()) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN) + .noOcclusion()) + .properties(p -> p.isRedstoneConductor(($1, $2, $3) -> false)) .transform(axeOrPickaxe()) .blockstate(new SmartObserverGenerator()::generate) - .onRegister(assignDataBehaviour(new ItemCountDisplaySource(), "count_items")) - .onRegister(assignDataBehaviour(new ItemListDisplaySource(), "list_items")) - .onRegister(assignDataBehaviour(new FluidAmountDisplaySource(), "count_fluids")) - .onRegister(assignDataBehaviour(new FluidListDisplaySource(), "list_fluids")) + .transform(displaySource(AllDisplaySources.COUNT_ITEMS)) + .transform(displaySource(AllDisplaySources.LIST_ITEMS)) + .transform(displaySource(AllDisplaySources.COUNT_FLUIDS)) + .transform(displaySource(AllDisplaySources.LIST_FLUIDS)) + .transform(displaySource(AllDisplaySources.READ_PACKAGE_ADDRESS)) .lang("Smart Observer") .item() .transform(customItemModel("_", "block")) @@ -1734,10 +1800,12 @@ public class AllBlocks { public static final BlockEntry THRESHOLD_SWITCH = REGISTRATE.block("stockpile_switch", ThresholdSwitchBlock::new) .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).noOcclusion()) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN) + .noOcclusion()) + .properties(p -> p.isRedstoneConductor(($1, $2, $3) -> false)) .transform(axeOrPickaxe()) .blockstate(new ThresholdSwitchGenerator()::generate) - .onRegister(assignDataBehaviour(new FillLevelDisplaySource(), "fill_level")) + .transform(displaySource(AllDisplaySources.FILL_LEVEL)) .lang("Threshold Switch") .item() .transform(customItemModel("threshold_switch", "block_wall")) @@ -1747,6 +1815,202 @@ public class AllBlocks { REGISTRATE.block("creative_crate", CreativeCrateBlock::new) .transform(BuilderTransformers.crate("creative")) .properties(p -> p.mapColor(MapColor.COLOR_PURPLE)) + .transform(mountedItemStorage(AllMountedStorageTypes.CREATIVE_CRATE)) + .register(); + + public static final BlockEntry ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE) + .sound(SoundType.NETHERITE_BLOCK) + .explosionResistance(1200)) + .transform(pickaxeOnly()) + .blockstate((c, p) -> p.getVariantBuilder(c.get()) + .forAllStates(s -> ConfiguredModel.builder() + .modelFile(AssetLookup.standardModel(c, p)) + .rotationY(s.getValue(ItemVaultBlock.HORIZONTAL_AXIS) == Axis.X ? 90 : 0) + .build())) + .onRegister(connectedTextures(ItemVaultCTBehaviour::new)) + .transform(mountedItemStorage(AllMountedStorageTypes.VAULT)) + .item(ItemVaultItem::new) + .build() + .register(); + + public static final BlockEntry ITEM_HATCH = REGISTRATE.block("item_hatch", ItemHatchBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE) + .sound(SoundType.NETHERITE_BLOCK)) + .transform(pickaxeOnly()) + .addLayer(() -> RenderType::cutoutMipped) + .blockstate((c, p) -> p.horizontalBlock(c.get(), + s -> AssetLookup.partialBaseModel(c, p, s.getValue(ItemHatchBlock.OPEN) ? "open" : "closed"))) + .item() + .transform(customItemModel("_", "block_closed")) + .register(); + + public static final BlockEntry PACKAGER = REGISTRATE.block("packager", PackagerBlock::new) + .transform(BuilderTransformers.packager()) + .register(); + + public static final BlockEntry REPACKAGER = REGISTRATE.block("repackager", RepackagerBlock::new) + .transform(BuilderTransformers.packager()) + .lang("Re-Packager") + .register(); + + public static final BlockEntry PACKAGE_FROGPORT = + REGISTRATE.block("package_frogport", FrogportBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.noOcclusion()) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE) + .sound(SoundType.NETHERITE_BLOCK)) + .transform(pickaxeOnly()) + .addLayer(() -> RenderType::cutoutMipped) + .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) + .item(PackagePortItem::new) + .model(AssetLookup::customItemModel) + .build() + .register(); + + public static final DyedBlockList PACKAGE_POSTBOXES = new DyedBlockList<>(colour -> { + String colourName = colour.getSerializedName(); + return REGISTRATE.block(colourName + "_postbox", p -> new PostboxBlock(p, colour)) + .initialProperties(SharedProperties::wooden) + .properties(p -> p.mapColor(colour)) + .transform(axeOnly()) + .blockstate((c, p) -> { + p.horizontalBlock(c.get(), s -> { + String suffix = s.getValue(PostboxBlock.OPEN) ? "open" : "closed"; + return p.models() + .withExistingParent(colourName + "_postbox_" + suffix, + p.modLoc("block/package_postbox/block_" + suffix)) + .texture("0", p.modLoc("block/post_box/post_box_" + colourName)) + .texture("1", p.modLoc("block/post_box/post_box_" + colourName + "_" + suffix)); + }); + }) + .tag(AllBlockTags.POSTBOXES.tag) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "block.create.package_postbox")) + .item(PackagePortItem::new) + .recipe((c, p) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, c.get()) + .define('D', colour.getTag()) + .define('B', Items.BARREL) + .define('A', AllItems.ANDESITE_ALLOY) + .pattern("D") + .pattern("B") + .pattern("A") + .unlockedBy("has_barrel", RegistrateRecipeProvider.has(Items.BARREL)) + .save(p, Create.asResource("crafting/logistics/" + c.getName())); + ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, c.get()) + .requires(colour.getTag()) + .requires(AllItemTags.POSTBOXES.tag) + .unlockedBy("has_postbox", RegistrateRecipeProvider.has(AllItemTags.POSTBOXES.tag)) + .save(p, Create.asResource("crafting/logistics/" + c.getName() + "_from_other_postbox")); + }) + .model((c, p) -> p.withExistingParent(colourName + "_postbox", p.modLoc("block/package_postbox/item")) + .texture("0", p.modLoc("block/post_box/post_box_" + colourName)) + .texture("1", p.modLoc("block/post_box/post_box_" + colourName + "_closed"))) + .tag(AllItemTags.POSTBOXES.tag) + .build() + .register(); + }); + + public static final BlockEntry STOCK_LINK = + REGISTRATE.block("stock_link", PackagerLinkBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE) + .sound(SoundType.NETHERITE_BLOCK)) + .transform(pickaxeOnly()) + .blockstate(new PackagerLinkGenerator()::generate) + .item(LogisticallyLinkedBlockItem::new) + .transform(customItemModel("_", "block_vertical")) + .register(); + + public static final BlockEntry STOCK_TICKER = + REGISTRATE.block("stock_ticker", StockTickerBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.sound(SoundType.GLASS)) + .transform(axeOrPickaxe()) + .addLayer(() -> RenderType::cutoutMipped) + .blockstate((c, p) -> p.horizontalBlock(c.get(), AssetLookup.standardModel(c, p))) + .item(LogisticallyLinkedBlockItem::new) + .build() + .register(); + + public static final BlockEntry REDSTONE_REQUESTER = + REGISTRATE.block("redstone_requester", RedstoneRequesterBlock::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.noOcclusion()) + .transform(pickaxeOnly()) + .blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, AssetLookup.forPowered(c, p))) + .item(RedstoneRequesterBlockItem::new) + .transform(customItemModel("_", "block")) + .register(); + + public static final BlockEntry FACTORY_GAUGE = + REGISTRATE.block("factory_gauge", FactoryPanelBlock::new) + .addLayer(() -> RenderType::cutoutMipped) + .initialProperties(SharedProperties::copperMetal) + .properties(p -> p.noOcclusion()) + .properties(p -> p.forceSolidOn()) + .transform(pickaxeOnly()) + .blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.partialBaseModel(c, p))) + .onRegister(CreateRegistrate.blockModel(() -> FactoryPanelModel::new)) + .transform(displaySource(AllDisplaySources.GAUGE_STATUS)) + .item(FactoryPanelBlockItem::new) + .model(AssetLookup::customItemModel) + .build() + .register(); + + public static final DyedBlockList TABLE_CLOTHS = new DyedBlockList<>(colour -> { + String colourName = colour.getSerializedName(); + return REGISTRATE.block(colourName + "_table_cloth", p -> new TableClothBlock(p, colour)) + .transform(BuilderTransformers.tableCloth(colourName, () -> Blocks.BLACK_CARPET, true)) + .properties(p -> p.mapColor(colour)) + .recipe((c, p) -> { + ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, c.get(), 2) + .requires(DyeHelper.getWoolOfDye(colour)) + .requires(AllItems.ANDESITE_ALLOY) + .unlockedBy("has_wool", RegistrateRecipeProvider.has(ItemTags.WOOL)) + .save(p, Create.asResource("crafting/logistics/" + c.getName())); + ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, c.get()) + .requires(colour.getTag()) + .requires(AllItemTags.DYED_TABLE_CLOTHS.tag) + .unlockedBy("has_postbox", RegistrateRecipeProvider.has(AllItemTags.DYED_TABLE_CLOTHS.tag)) + .save(p, Create.asResource("crafting/logistics/" + c.getName() + "_from_other_table_cloth")); + }) + .register(); + }); + + public static final BlockEntry ANDESITE_TABLE_CLOTH = + REGISTRATE.block("andesite_table_cloth", p -> new TableClothBlock(p, "andesite")) + .transform(BuilderTransformers.tableCloth("andesite", SharedProperties::stone, false)) + .properties(p -> p.mapColor(MapColor.STONE) + .requiresCorrectToolForDrops()) + .recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.ANDESITE_ALLOY.get()), + RecipeCategory.DECORATIONS, c::get, 2)) + .transform(pickaxeOnly()) + .lang("Andesite Table Cover") + .register(); + + public static final BlockEntry BRASS_TABLE_CLOTH = + REGISTRATE.block("brass_table_cloth", p -> new TableClothBlock(p, "brass")) + .transform(BuilderTransformers.tableCloth("brass", SharedProperties::softMetal, false)) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW) + .requiresCorrectToolForDrops()) + .recipe((c, p) -> p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/brass")), + RecipeCategory.DECORATIONS, c::get, 2)) + .transform(pickaxeOnly()) + .lang("Brass Table Cover") + .register(); + + public static final BlockEntry COPPER_TABLE_CLOTH = + REGISTRATE.block("copper_table_cloth", p -> new TableClothBlock(p, "copper")) + .transform(BuilderTransformers.tableCloth("copper", SharedProperties::copperMetal, false)) + .properties(p -> p.requiresCorrectToolForDrops()) + .recipe((c, p) -> p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), + RecipeCategory.DECORATIONS, c::get, 2)) + .transform(pickaxeOnly()) + .lang("Copper Table Cover") .register(); public static final BlockEntry DISPLAY_LINK = @@ -1766,9 +2030,9 @@ public class AllBlocks { .properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .addLayer(() -> RenderType::cutoutMipped) .transform(pickaxeOnly()) - .transform(BlockStressDefaults.setImpact(0)) + .transform(CStress.setNoImpact()) .blockstate((c, p) -> p.horizontalBlock(c.get(), AssetLookup.partialBaseModel(c, p))) - .onRegister(assignDataBehaviour(new DisplayBoardTarget())) + .transform(displayTarget(AllDisplayTargets.DISPLAY_BOARD)) .lang("Display Board") .item() .transform(customItemModel()) @@ -1777,7 +2041,9 @@ public class AllBlocks { public static final BlockEntry ORANGE_NIXIE_TUBE = REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE)) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.lightLevel($ -> 5).mapColor(DyeColor.ORANGE).forceSolidOn()) + .properties(p -> p.lightLevel($ -> 5) + .mapColor(DyeColor.ORANGE) + .forceSolidOn()) .transform(pickaxeOnly()) .blockstate(new NixieTubeGenerator()::generate) .addLayer(() -> RenderType::translucent) @@ -1791,7 +2057,9 @@ public class AllBlocks { String colourName = colour.getSerializedName(); return REGISTRATE.block(colourName + "_nixie_tube", p -> new NixieTubeBlock(p, colour)) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.lightLevel($ -> 5).mapColor(colour).forceSolidOn()) + .properties(p -> p.lightLevel($ -> 5) + .mapColor(colour) + .forceSolidOn()) .transform(pickaxeOnly()) .blockstate(new NixieTubeGenerator()::generate) .loot((p, b) -> p.dropOther(b, ORANGE_NIXIE_TUBE.get())) @@ -1817,7 +2085,8 @@ public class AllBlocks { public static final BlockEntry REDSTONE_LINK = REGISTRATE.block("redstone_link", RedstoneLinkBlock::new) .initialProperties(SharedProperties::wooden) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN) + .forceSolidOn()) .transform(axeOrPickaxe()) .tag(AllBlockTags.BRITTLE.tag, AllBlockTags.SAFE_NBT.tag) .blockstate(new RedstoneLinkGenerator()::generate) @@ -1867,6 +2136,16 @@ public class AllBlocks { .build() .register(); + public static final BlockEntry PULSE_TIMER = REGISTRATE.block("pulse_timer", BrassDiodeBlock::new) + .initialProperties(() -> Blocks.REPEATER) + .tag(AllBlockTags.SAFE_NBT.tag) + .blockstate(new BrassDiodeGenerator()::generate) + .addLayer(() -> RenderType::cutoutMipped) + .item() + .model(AbstractDiodeGenerator::diodeItemModel) + .build() + .register(); + public static final BlockEntry POWERED_LATCH = REGISTRATE.block("powered_latch", PoweredLatchBlock::new) .initialProperties(() -> Blocks.REPEATER) @@ -1909,23 +2188,35 @@ public class AllBlocks { public static final BlockEntry PECULIAR_BELL = REGISTRATE.block("peculiar_bell", PeculiarBellBlock::new) - .properties(p -> p.mapColor(MapColor.GOLD).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.GOLD) + .forceSolidOn()) .transform(BuilderTransformers.bell()) .onRegister(movementBehaviour(new BellMovementBehaviour())) .register(); public static final BlockEntry HAUNTED_BELL = REGISTRATE.block("haunted_bell", HauntedBellBlock::new) - .properties(p -> p.mapColor(MapColor.SAND).forceSolidOn()) + .properties(p -> p.mapColor(MapColor.SAND) + .forceSolidOn()) .transform(BuilderTransformers.bell()) .onRegister(movementBehaviour(new HauntedBellMovementBehaviour())) .register(); + public static final BlockEntry DESK_BELL = REGISTRATE.block("desk_bell", DeskBellBlock::new) + .properties(p -> p.mapColor(MapColor.SAND)) + .blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.forPowered(c, p))) + .item() + .transform(customItemModel("_", "block")) + .onRegister(movementBehaviour(new BellMovementBehaviour())) + .register(); + public static final DyedBlockList TOOLBOXES = new DyedBlockList<>(colour -> { String colourName = colour.getSerializedName(); return REGISTRATE.block(colourName + "_toolbox", p -> new ToolboxBlock(p, colour)) .initialProperties(SharedProperties::wooden) - .properties(p -> p.sound(SoundType.WOOD).mapColor(colour).forceSolidOn()) + .properties(p -> p.sound(SoundType.WOOD) + .mapColor(colour) + .forceSolidOn()) .addLayer(() -> RenderType::cutoutMipped) .loot((lt, block) -> { Builder builder = LootTable.lootTable(); @@ -1946,6 +2237,7 @@ public class AllBlocks { .texture("0", p.modLoc("block/toolbox/" + colourName))); }) .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "block.create.toolbox")) + .transform(mountedItemStorage(AllMountedStorageTypes.TOOLBOX)) .tag(AllBlockTags.TOOLBOXES.tag) .item(UncontainableBlockItem::new) .model((c, p) -> p.withExistingParent(colourName + "_toolbox", p.modLoc("block/toolbox/item")) @@ -2023,7 +2315,8 @@ public class AllBlocks { public static final BlockEntry METAL_GIRDER = REGISTRATE.block("metal_girder", GirderBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.mapColor(MapColor.COLOR_GRAY) + .sound(SoundType.NETHERITE_BLOCK)) .transform(pickaxeOnly()) .blockstate(GirderBlockStateGenerator::blockState) .onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new)) @@ -2034,7 +2327,8 @@ public class AllBlocks { public static final BlockEntry METAL_GIRDER_ENCASED_SHAFT = REGISTRATE.block("metal_girder_encased_shaft", GirderEncasedShaftBlock::new) .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.mapColor(MapColor.COLOR_GRAY) + .sound(SoundType.NETHERITE_BLOCK)) .transform(pickaxeOnly()) .blockstate(GirderBlockStateGenerator::blockStateWithShaft) .loot((p, b) -> p.add(b, p.createSingleItemTable(METAL_GIRDER.get()) @@ -2090,7 +2384,7 @@ public class AllBlocks { .transform(axeOnly()) .onRegister(movementBehaviour(movementBehaviour)) .onRegister(interactionBehaviour(interactionBehaviour)) - .onRegister(assignDataBehaviour(new EntityNameDisplaySource(), "entity_name")) + .transform(displaySource(AllDisplaySources.ENTITY_NAME)) .blockstate((c, p) -> { p.simpleBlock(c.get(), p.models() .withExistingParent(colourName + "_seat", p.modLoc("block/seat")) @@ -2212,7 +2506,8 @@ public class AllBlocks { public static final BlockEntry RAW_ZINC_BLOCK = REGISTRATE.block("raw_zinc_block", Block::new) .initialProperties(() -> Blocks.RAW_GOLD_BLOCK) - .properties(p -> p.mapColor(MapColor.GLOW_LICHEN).requiresCorrectToolForDrops()) + .properties(p -> p.mapColor(MapColor.GLOW_LICHEN) + .requiresCorrectToolForDrops()) .transform(pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS) .tag(BlockTags.NEEDS_IRON_TOOL) @@ -2224,7 +2519,8 @@ public class AllBlocks { public static final BlockEntry ZINC_BLOCK = REGISTRATE.block("zinc_block", Block::new) .initialProperties(() -> Blocks.IRON_BLOCK) - .properties(p -> p.mapColor(MapColor.GLOW_LICHEN).requiresCorrectToolForDrops()) + .properties(p -> p.mapColor(MapColor.GLOW_LICHEN) + .requiresCorrectToolForDrops()) .transform(pickaxeOnly()) .tag(BlockTags.NEEDS_IRON_TOOL) .tag(Tags.Blocks.STORAGE_BLOCKS) @@ -2237,7 +2533,8 @@ public class AllBlocks { public static final BlockEntry ANDESITE_ALLOY_BLOCK = REGISTRATE.block("andesite_alloy_block", Block::new) .initialProperties(() -> Blocks.ANDESITE) - .properties(p -> p.mapColor(MapColor.STONE).requiresCorrectToolForDrops()) + .properties(p -> p.mapColor(MapColor.STONE) + .requiresCorrectToolForDrops()) .transform(pickaxeOnly()) .blockstate(simpleCubeAll("andesite_block")) .tag(Tags.Blocks.STORAGE_BLOCKS) @@ -2248,24 +2545,19 @@ public class AllBlocks { .register(); public static final BlockEntry INDUSTRIAL_IRON_BLOCK = REGISTRATE.block("industrial_iron_block", Block::new) - .initialProperties(SharedProperties::softMetal) - .properties(p -> p.mapColor(MapColor.COLOR_GRAY) - .sound(SoundType.NETHERITE_BLOCK) - .requiresCorrectToolForDrops()) - .transform(pickaxeOnly()) - .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() - .cubeColumn(c.getName(), p.modLoc("block/industrial_iron_block"), - p.modLoc("block/industrial_iron_block_top")))) - .tag(AllBlockTags.WRENCH_PICKUP.tag) + .transform(BuilderTransformers.palettesIronBlock()) .lang("Block of Industrial Iron") - .recipe((c, p) -> p.stonecutting(DataIngredient.tag(Tags.Items.INGOTS_IRON), RecipeCategory.BUILDING_BLOCKS, - c::get, 2)) - .simpleItem() + .register(); + + public static final BlockEntry WEATHERED_IRON_BLOCK = REGISTRATE.block("weathered_iron_block", Block::new) + .transform(BuilderTransformers.palettesIronBlock()) + .lang("Block of Weathered Iron") .register(); public static final BlockEntry BRASS_BLOCK = REGISTRATE.block("brass_block", Block::new) .initialProperties(() -> Blocks.IRON_BLOCK) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW).requiresCorrectToolForDrops()) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW) + .requiresCorrectToolForDrops()) .transform(pickaxeOnly()) .blockstate(simpleCubeAll("brass_block")) .tag(BlockTags.NEEDS_IRON_TOOL) @@ -2277,6 +2569,43 @@ public class AllBlocks { .lang("Block of Brass") .register(); + public static final BlockEntry CARDBOARD_BLOCK = + REGISTRATE.block("cardboard_block", CardboardBlock::new) + .initialProperties(() -> Blocks.MUSHROOM_STEM) + .properties(p -> p.mapColor(MapColor.COLOR_BROWN) + .sound(SoundType.CHISELED_BOOKSHELF) + .ignitedByLava()) + .transform(axeOnly()) + .blockstate(BlockStateGen.horizontalAxisBlockProvider(false)) + .tag(Tags.Blocks.STORAGE_BLOCKS) + .tag(AllTags.forgeBlockTag("storage_blocks/cardboard")) + .item(CardboardBlockItem::new) + .tag(AllTags.forgeItemTag("storage_blocks/cardboard")) + .tag(Tags.Items.STORAGE_BLOCKS) + .build() + .lang("Block of Cardboard") + .register(); + + public static final BlockEntry BOUND_CARDBOARD_BLOCK = + REGISTRATE.block("bound_cardboard_block", CardboardBlock::new) + .initialProperties(() -> Blocks.MUSHROOM_STEM) + .properties(p -> p.mapColor(MapColor.COLOR_BROWN) + .sound(SoundType.CHISELED_BOOKSHELF) + .ignitedByLava()) + .transform(axeOnly()) + .blockstate(BlockStateGen.horizontalAxisBlockProvider(false)) + .loot((r, b) -> r.add(b, LootTable.lootTable() + .withPool(r.applyExplosionCondition(b, LootPool.lootPool() + .setRolls(ConstantValue.exactly(1.0F)) + .add(LootItem.lootTableItem(Items.STRING)))) + .withPool(r.applyExplosionCondition(b, LootPool.lootPool() + .setRolls(ConstantValue.exactly(1.0F)) + .add(LootItem.lootTableItem(AllBlocks.CARDBOARD_BLOCK.asItem())))))) + .item(CardboardBlockItem::new) + .build() + .lang("Bound Block of Cardboard") + .register(); + public static final BlockEntry EXPERIENCE_BLOCK = REGISTRATE.block("experience_block", ExperienceBlock::new) .initialProperties(SharedProperties::softMetal) @@ -2314,7 +2643,8 @@ public class AllBlocks { public static final BlockEntry ROSE_QUARTZ_TILES = REGISTRATE.block("rose_quartz_tiles", Block::new) .initialProperties(() -> Blocks.DEEPSLATE) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK).requiresCorrectToolForDrops()) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK) + .requiresCorrectToolForDrops()) .transform(pickaxeOnly()) .blockstate(simpleCubeAll("palettes/rose_quartz_tiles")) .recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()), @@ -2325,7 +2655,8 @@ public class AllBlocks { public static final BlockEntry SMALL_ROSE_QUARTZ_TILES = REGISTRATE.block("small_rose_quartz_tiles", Block::new) .initialProperties(() -> Blocks.DEEPSLATE) - .properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK).requiresCorrectToolForDrops()) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK) + .requiresCorrectToolForDrops()) .transform(pickaxeOnly()) .blockstate(simpleCubeAll("palettes/small_rose_quartz_tiles")) .recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()), @@ -2335,18 +2666,21 @@ public class AllBlocks { public static final CopperBlockSet COPPER_SHINGLES = new CopperBlockSet(REGISTRATE, "copper_shingles", "copper_roof_top", CopperBlockSet.DEFAULT_VARIANTS, (c, p) -> { - p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), RecipeCategory.BUILDING_BLOCKS, - c::get, 2); - }); + p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), RecipeCategory.BUILDING_BLOCKS, + c::get, 2); + }, (ws, block) -> connectedTextures(() -> new RoofBlockCTBehaviour(AllSpriteShifts.COPPER_SHINGLES.get(ws))) + .accept(block)); public static final CopperBlockSet COPPER_TILES = new CopperBlockSet(REGISTRATE, "copper_tiles", "copper_roof_top", CopperBlockSet.DEFAULT_VARIANTS, (c, p) -> { p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), RecipeCategory.BUILDING_BLOCKS, c::get, 2); - }); + }, (ws, block) -> connectedTextures(() -> new RoofBlockCTBehaviour(AllSpriteShifts.COPPER_TILES.get(ws))) + .accept(block)); // Load this class - public static void register() {} + public static void register() { + } } diff --git a/src/main/java/com/simibubi/create/AllBogeyStyles.java b/src/main/java/com/simibubi/create/AllBogeyStyles.java index 67506bb9d2..4d536cd5e9 100644 --- a/src/main/java/com/simibubi/create/AllBogeyStyles.java +++ b/src/main/java/com/simibubi/create/AllBogeyStyles.java @@ -4,6 +4,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import net.minecraft.network.chat.Component; + import org.jetbrains.annotations.ApiStatus; import com.simibubi.create.content.trains.bogey.BogeySizes; @@ -11,7 +13,6 @@ import com.simibubi.create.content.trains.bogey.BogeyStyle; import com.simibubi.create.content.trains.bogey.BogeyStyle.SizeRenderer; import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer; import com.simibubi.create.content.trains.bogey.StandardBogeyVisual; -import com.simibubi.create.foundation.utility.Components; import net.minecraft.resources.ResourceLocation; @@ -22,13 +23,13 @@ public class AllBogeyStyles { public static final ResourceLocation STANDARD_CYCLE_GROUP = Create.asResource("standard"); - public static final BogeyStyle STANDARD = - builder("standard", STANDARD_CYCLE_GROUP).displayName(Components.translatable("create.bogey.style.standard")) - .size(BogeySizes.SMALL, AllBlocks.SMALL_BOGEY, () -> new SizeRenderer(new StandardBogeyRenderer.Small(), StandardBogeyVisual.Small::new)) - .size(BogeySizes.LARGE, AllBlocks.LARGE_BOGEY, () -> new SizeRenderer(new StandardBogeyRenderer.Large(), StandardBogeyVisual.Large::new)) - .build(); + public static final BogeyStyle STANDARD + = builder("standard", STANDARD_CYCLE_GROUP).displayName(Component.translatable("create.bogey.style.standard")) + .size(BogeySizes.SMALL, AllBlocks.SMALL_BOGEY, () -> () -> new SizeRenderer(new StandardBogeyRenderer.Small(), StandardBogeyVisual.Small::new)) + .size(BogeySizes.LARGE, AllBlocks.LARGE_BOGEY, () -> () -> new SizeRenderer(new StandardBogeyRenderer.Large(), StandardBogeyVisual.Large::new)) + .build(); - public static Map getCycleGroup(ResourceLocation cycleGroup) { + public static Map getCycleGroup(ResourceLocation cycleGroup) { return CYCLE_GROUPS.getOrDefault(cycleGroup, EMPTY_GROUP); } diff --git a/src/main/java/com/simibubi/create/AllContraptionMovementSettings.java b/src/main/java/com/simibubi/create/AllContraptionMovementSettings.java new file mode 100644 index 0000000000..d7290a244b --- /dev/null +++ b/src/main/java/com/simibubi/create/AllContraptionMovementSettings.java @@ -0,0 +1,17 @@ +package com.simibubi.create; + +import com.simibubi.create.api.contraption.ContraptionMovementSetting; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.world.level.block.Blocks; + +public class AllContraptionMovementSettings { + public static void registerDefaults() { + ContraptionMovementSetting.REGISTRY.register(Blocks.SPAWNER, () -> AllConfigs.server().kinetics.spawnerMovement.get()); + ContraptionMovementSetting.REGISTRY.register(Blocks.BUDDING_AMETHYST, () -> AllConfigs.server().kinetics.amethystMovement.get()); + ContraptionMovementSetting.REGISTRY.register(Blocks.OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + ContraptionMovementSetting.REGISTRY.register(Blocks.CRYING_OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + ContraptionMovementSetting.REGISTRY.register(Blocks.RESPAWN_ANCHOR, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + ContraptionMovementSetting.REGISTRY.register(Blocks.REINFORCED_DEEPSLATE, () -> AllConfigs.server().kinetics.reinforcedDeepslateMovement.get()); + } +} diff --git a/src/main/java/com/simibubi/create/AllContraptionTypes.java b/src/main/java/com/simibubi/create/AllContraptionTypes.java new file mode 100644 index 0000000000..451960133f --- /dev/null +++ b/src/main/java/com/simibubi/create/AllContraptionTypes.java @@ -0,0 +1,45 @@ +package com.simibubi.create; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.simibubi.create.api.contraption.ContraptionType; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.bearing.BearingContraption; +import com.simibubi.create.content.contraptions.bearing.ClockworkContraption; +import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; +import com.simibubi.create.content.contraptions.gantry.GantryContraption; +import com.simibubi.create.content.contraptions.mounted.MountedContraption; +import com.simibubi.create.content.contraptions.piston.PistonContraption; +import com.simibubi.create.content.contraptions.pulley.PulleyContraption; +import com.simibubi.create.content.trains.entity.CarriageContraption; + +import net.minecraft.core.Holder.Reference; +import net.minecraft.core.Registry; + +public class AllContraptionTypes { + public static final Map BY_LEGACY_NAME = new HashMap<>(); + + public static final Reference PISTON = register("piston", PistonContraption::new); + public static final Reference BEARING = register("bearing", BearingContraption::new); + public static final Reference PULLEY = register("pulley", PulleyContraption::new); + public static final Reference CLOCKWORK = register("clockwork", ClockworkContraption::new); + public static final Reference MOUNTED = register("mounted", MountedContraption::new); + public static final Reference STABILIZED = register("stabilized", StabilizedContraption::new); + public static final Reference GANTRY = register("gantry", GantryContraption::new); + public static final Reference CARRIAGE = register("carriage", CarriageContraption::new); + public static final Reference ELEVATOR = register("elevator", ElevatorContraption::new); + + private static Reference register(String name, Supplier factory) { + ContraptionType type = new ContraptionType(factory); + BY_LEGACY_NAME.put(name, type); + + return Registry.registerForHolder(CreateBuiltInRegistries.CONTRAPTION_TYPE, Create.asResource(name), type); + } + + public static void init() { + } +} diff --git a/src/main/java/com/simibubi/create/AllCreativeModeTabs.java b/src/main/java/com/simibubi/create/AllCreativeModeTabs.java index d8416b9675..c63a763e99 100644 --- a/src/main/java/com/simibubi/create/AllCreativeModeTabs.java +++ b/src/main/java/com/simibubi/create/AllCreativeModeTabs.java @@ -7,6 +7,8 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; +import net.minecraft.network.chat.Component; + import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; @@ -14,9 +16,11 @@ import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; import com.simibubi.create.content.equipment.armor.BacktankUtil; import com.simibubi.create.content.equipment.toolbox.ToolboxBlock; import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; +import com.simibubi.create.content.logistics.box.PackageStyles; +import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlock; +import com.simibubi.create.content.logistics.tableCloth.TableClothBlock; import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.item.TagDependentIngredientItem; -import com.simibubi.create.foundation.utility.Components; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.ItemEntry; import com.tterrag.registrate.util.entry.ItemProviderEntry; @@ -59,7 +63,7 @@ public class AllCreativeModeTabs { public static final RegistryObject BASE_CREATIVE_TAB = REGISTER.register("base", () -> CreativeModeTab.builder() - .title(Components.translatable("itemGroup.create.base")) + .title(Component.translatable("itemGroup.create.base")) .withTabsBefore(CreativeModeTabs.SPAWN_EGGS) .icon(() -> AllBlocks.COGWHEEL.asStack()) .displayItems(new RegistrateDisplayItemsGenerator(true, AllCreativeModeTabs.BASE_CREATIVE_TAB)) @@ -67,7 +71,7 @@ public class AllCreativeModeTabs { public static final RegistryObject PALETTES_CREATIVE_TAB = REGISTER.register("palettes", () -> CreativeModeTab.builder() - .title(Components.translatable("itemGroup.create.palettes")) + .title(Component.translatable("itemGroup.create.palettes")) .withTabsBefore(BASE_CREATIVE_TAB.getKey()) .icon(() -> AllPaletteBlocks.ORNATE_IRON_WINDOW.asStack()) .displayItems(new RegistrateDisplayItemsGenerator(false, AllCreativeModeTabs.PALETTES_CREATIVE_TAB)) @@ -127,6 +131,7 @@ public class AllCreativeModeTabs { AllItems.FURNACE_MINECART_CONTRAPTION, AllItems.CHEST_MINECART_CONTRAPTION, AllItems.SCHEMATIC, + AllItems.SHOPPING_LIST, AllBlocks.ANDESITE_ENCASED_SHAFT, AllBlocks.BRASS_ENCASED_SHAFT, AllBlocks.ANDESITE_ENCASED_COGWHEEL, @@ -151,6 +156,8 @@ public class AllCreativeModeTabs { AllItems.CRUSHED_NICKEL ); + exclusions.addAll(PackageStyles.RARE_BOXES); + for (ItemProviderEntry entry : simpleExclusions) { exclusions.add(entry.asItem()); } @@ -185,6 +192,10 @@ public class AllCreativeModeTabs { orderings.add(ItemOrdering.after(entry.asItem(), otherEntry.asItem())); }); + PackageStyles.STANDARD_BOXES.forEach(item -> { + orderings.add(ItemOrdering.after(item, AllBlocks.PACKAGER.asItem())); + }); + return orderings; } @@ -239,6 +250,20 @@ public class AllCreativeModeTabs { } } + for (BlockEntry entry : AllBlocks.TABLE_CLOTHS) { + TableClothBlock block = entry.get(); + if (block.getColor() != DyeColor.RED) { + visibilities.put(entry.asItem(), TabVisibility.SEARCH_TAB_ONLY); + } + } + + for (BlockEntry entry : AllBlocks.PACKAGE_POSTBOXES) { + PostboxBlock block = entry.get(); + if (block.getColor() != DyeColor.WHITE) { + visibilities.put(entry.asItem(), TabVisibility.SEARCH_TAB_ONLY); + } + } + for (BlockEntry entry : AllBlocks.TOOLBOXES) { ToolboxBlock block = entry.get(); if (block.getColor() != DyeColor.BROWN) { @@ -347,4 +372,4 @@ public class AllCreativeModeTabs { } } } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/AllDisplaySources.java b/src/main/java/com/simibubi/create/AllDisplaySources.java new file mode 100644 index 0000000000..c18e587580 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllDisplaySources.java @@ -0,0 +1,155 @@ +package com.simibubi.create; + +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.content.redstone.displayLink.source.AccumulatedItemCountDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.BoilerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ComputerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.CurrentFloorDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.DeathCounterDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.EnchantPowerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.EntityNameDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.FactoryGaugeDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.FillLevelDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.FluidAmountDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.FluidListDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemCountDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemListDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemNameDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemThroughputDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.KineticSpeedDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.KineticStressDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.NixieTubeDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ObservedTrainNameSource; +import com.simibubi.create.content.redstone.displayLink.source.PackageAddressDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.RedstonePowerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ScoreboardDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.StationSummaryDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.StopWatchDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.TimeOfDayDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.TrainStatusDisplaySource; +import com.tterrag.registrate.util.entry.RegistryEntry; +import net.minecraft.Util; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import static com.simibubi.create.Create.REGISTRATE; + +public class AllDisplaySources { + public static final RegistryEntry DEATH_COUNT = REGISTRATE.displaySource("death_count", DeathCounterDisplaySource::new) + .associate(Blocks.RESPAWN_ANCHOR) + .register(); + public static final RegistryEntry SCOREBOARD = REGISTRATE.displaySource("scoreboard", ScoreboardDisplaySource::new) + .associate(BlockEntityType.COMMAND_BLOCK) + .register(); + public static final RegistryEntry ENCHANT_POWER = REGISTRATE.displaySource("enchant_power", EnchantPowerDisplaySource::new) + .associate(BlockEntityType.ENCHANTING_TABLE) + .register(); + public static final RegistryEntry REDSTONE_POWER = REGISTRATE.displaySource("redstone_power", RedstonePowerDisplaySource::new) + .associate(Blocks.TARGET) + .register(); + + public static final RegistryEntry NIXIE_TUBE = simple("nixie_tube", NixieTubeDisplaySource::new); + public static final RegistryEntry ITEM_NAMES = simple("item_names", ItemNameDisplaySource::new); + public static final RegistryEntry BOILER = simple("boiler", BoilerDisplaySource::new); + public static final RegistryEntry CURRENT_FLOOR = simple("current_floor", CurrentFloorDisplaySource::new); + public static final RegistryEntry FILL_LEVEL = simple("fill_level", FillLevelDisplaySource::new); + public static final RegistryEntry GAUGE_STATUS = simple("gauge_status", FactoryGaugeDisplaySource::new); + public static final RegistryEntry ENTITY_NAME = simple("entity_name", EntityNameDisplaySource::new); + + public static final RegistryEntry TIME_OF_DAY = simple("time_of_day", TimeOfDayDisplaySource::new); + public static final RegistryEntry STOPWATCH = simple("stopwatch", StopWatchDisplaySource::new); + + public static final RegistryEntry KINETIC_SPEED = simple("kinetic_speed", KineticSpeedDisplaySource::new); + public static final RegistryEntry KINETIC_STRESS = simple("kinetic_stress", KineticStressDisplaySource::new); + + public static final RegistryEntry STATION_SUMMARY = simple("station_summary", StationSummaryDisplaySource::new); + public static final RegistryEntry TRAIN_STATUS = simple("train_status", TrainStatusDisplaySource::new); + public static final RegistryEntry OBSERVED_TRAIN_NAME = simple("observed_train_name", ObservedTrainNameSource::new); + + public static final RegistryEntry ACCUMULATE_ITEMS = simple("accumulate_items", AccumulatedItemCountDisplaySource::new); + public static final RegistryEntry ITEM_THROUGHPUT = simple("item_throughput", ItemThroughputDisplaySource::new); + + public static final RegistryEntry COUNT_ITEMS = simple("count_items", ItemCountDisplaySource::new); + public static final RegistryEntry LIST_ITEMS = simple("list_items", ItemListDisplaySource::new); + public static final RegistryEntry COUNT_FLUIDS = simple("count_fluids", FluidAmountDisplaySource::new); + public static final RegistryEntry LIST_FLUIDS = simple("list_fluids", FluidListDisplaySource::new); + public static final RegistryEntry READ_PACKAGE_ADDRESS = simple("read_package_address", PackageAddressDisplaySource::new); + + public static final RegistryEntry COMPUTER = REGISTRATE.displaySource("computer", ComputerDisplaySource::new) + .onRegisterAfter(Registries.BLOCK_ENTITY_TYPE, source -> { + List types = List.of("wired_modem_full", "computer_normal", "computer_advanced", "computer_command"); + for (String name : types) { + ResourceLocation id = Mods.COMPUTERCRAFT.rl(name); + if (ForgeRegistries.BLOCK_ENTITY_TYPES.containsKey(id)) { + BlockEntityType type = ForgeRegistries.BLOCK_ENTITY_TYPES.getValue(id); + DisplaySource.BY_BLOCK_ENTITY.add(type, source); + } else { + Create.LOGGER.warn("Could not find block entity type {}. Outdated compat?", id); + } + } + }) + .register(); + + public static final Map> LEGACY_NAMES = Util.make(() -> { + Map> map = new HashMap<>(); + map.put("death_count_display_source", DEATH_COUNT); + map.put("scoreboard_display_source", SCOREBOARD); + map.put("enchant_power_display_source", ENCHANT_POWER); + map.put("redstone_power_display_source", REDSTONE_POWER); + + map.put("nixie_tube_source", NIXIE_TUBE); + map.put("belt_source_combine_item_names", ITEM_NAMES); + map.put("cuckoo_clock_source_time_of_day", TIME_OF_DAY); + map.put("cuckoo_clock_source_stop_watch", STOPWATCH); + map.put("speedometer_source_kinetic_speed", KINETIC_SPEED); + map.put("stressometer_source_kinetic_stress", KINETIC_STRESS); + map.put("fluid_tank_source_boiler_status", BOILER); + map.put("elevator_contact_source_current_floor", CURRENT_FLOOR); + map.put("track_station_source_station_summary", STATION_SUMMARY); + map.put("track_station_source_train_status", TRAIN_STATUS); + map.put("track_observer_source_observed_train_name", OBSERVED_TRAIN_NAME); + + map.put("andesite_tunnel_source_accumulate_items", ACCUMULATE_ITEMS); + map.put("andesite_tunnel_source_item_throughput", ITEM_THROUGHPUT); + map.put("brass_tunnel_source_accumulate_items", ACCUMULATE_ITEMS); + map.put("brass_tunnel_source_item_throughput", ITEM_THROUGHPUT); + + map.put("content_observer_source_count_items", COUNT_ITEMS); + map.put("content_observer_source_list_items", LIST_ITEMS); + map.put("content_observer_source_count_fluids", COUNT_FLUIDS); + map.put("content_observer_source_list_fluids", LIST_FLUIDS); + + map.put("stockpile_switch_source_fill_level", FILL_LEVEL); + + map.put("factory_gauge_source_gauge_status", GAUGE_STATUS); + + for (DyeColor color : DyeColor.values()) { + String name = color.getSerializedName() + "_seat_source_entity_name"; + map.put(name, ENTITY_NAME); + } + + map.put("depot_source_combine_item_names", ITEM_NAMES); + map.put("weighted_ejector_source_combine_item_names", ITEM_NAMES); + + map.put("computer_display_source", COMPUTER); + + return map; + }); + + private static RegistryEntry simple(String name, Supplier supplier) { + return REGISTRATE.displaySource(name, supplier).register(); + } + + public static void register() { + } +} diff --git a/src/main/java/com/simibubi/create/AllDisplayTargets.java b/src/main/java/com/simibubi/create/AllDisplayTargets.java new file mode 100644 index 0000000000..725d99e830 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllDisplayTargets.java @@ -0,0 +1,40 @@ +package com.simibubi.create; + +import com.simibubi.create.api.behaviour.display.DisplayTarget; +import com.simibubi.create.content.redstone.displayLink.target.DisplayBoardTarget; +import com.simibubi.create.content.redstone.displayLink.target.LecternDisplayTarget; +import com.simibubi.create.content.redstone.displayLink.target.NixieTubeDisplayTarget; +import com.simibubi.create.content.redstone.displayLink.target.SignDisplayTarget; +import com.tterrag.registrate.util.entry.RegistryEntry; +import net.minecraft.world.level.block.entity.BlockEntityType; + +import java.util.Map; +import java.util.function.Supplier; + +import static com.simibubi.create.Create.REGISTRATE; + +public class AllDisplayTargets { + public static final RegistryEntry SIGN = REGISTRATE.displayTarget("sign", SignDisplayTarget::new) + .associate(BlockEntityType.SIGN) + .register(); + public static final RegistryEntry LECTERN = REGISTRATE.displayTarget("lectern", LecternDisplayTarget::new) + .associate(BlockEntityType.LECTERN) + .register(); + + public static final RegistryEntry DISPLAY_BOARD = simple("display_board", DisplayBoardTarget::new); + public static final RegistryEntry NIXIE_TUBE = simple("nixie_tube", NixieTubeDisplayTarget::new); + + public static final Map> LEGACY_NAMES = Map.of( + "sign_display_target", SIGN, + "lectern_display_target", LECTERN, + "display_board_target", DISPLAY_BOARD, + "nixie_tube_target", NIXIE_TUBE + ); + + private static RegistryEntry simple(String name, Supplier supplier) { + return REGISTRATE.displayTarget(name, supplier).register(); + } + + public static void register() { + } +} diff --git a/src/main/java/com/simibubi/create/AllEntityTypes.java b/src/main/java/com/simibubi/create/AllEntityTypes.java index 2b21ec3f38..2c04ea664f 100644 --- a/src/main/java/com/simibubi/create/AllEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllEntityTypes.java @@ -14,22 +14,26 @@ import com.simibubi.create.content.equipment.blueprint.BlueprintEntity; import com.simibubi.create.content.equipment.blueprint.BlueprintRenderer; import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileEntity; import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileRenderer; +import com.simibubi.create.content.logistics.box.PackageEntity; +import com.simibubi.create.content.logistics.box.PackageRenderer; +import com.simibubi.create.content.logistics.box.PackageVisual; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.CarriageContraptionEntityRenderer; import com.simibubi.create.content.trains.entity.CarriageContraptionVisual; import com.simibubi.create.foundation.data.CreateEntityBuilder; -import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.util.entry.EntityEntry; import com.tterrag.registrate.util.nullness.NonNullConsumer; import com.tterrag.registrate.util.nullness.NonNullFunction; import com.tterrag.registrate.util.nullness.NonNullSupplier; +import net.createmod.catnip.lang.Lang; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType.EntityFactory; import net.minecraft.world.entity.MobCategory; +import net.minecraftforge.event.entity.EntityAttributeCreationEvent; public class AllEntityTypes { @@ -67,6 +71,11 @@ public class AllEntityTypes { public static final EntityEntry SEAT = register("seat", SeatEntity::new, () -> SeatEntity.Render::new, MobCategory.MISC, 5, Integer.MAX_VALUE, false, true, SeatEntity::build).register(); + public static final EntityEntry PACKAGE = register("package", PackageEntity::new, () -> PackageRenderer::new, + MobCategory.MISC, 10, 3, true, false, PackageEntity::build) + .visual(() -> PackageVisual::new, true) + .register(); + // private static CreateEntityBuilder contraption(String name, EntityFactory factory, @@ -94,5 +103,10 @@ public class AllEntityTypes { .renderer(renderer); } + public static void registerEntityAttributes(EntityAttributeCreationEvent event) { + event.put(PACKAGE.get(), PackageEntity.createPackageAttributes() + .build()); + } + public static void register() {} } diff --git a/src/main/java/com/simibubi/create/AllFluids.java b/src/main/java/com/simibubi/create/AllFluids.java index 8595a404b3..a295b43ea3 100644 --- a/src/main/java/com/simibubi/create/AllFluids.java +++ b/src/main/java/com/simibubi/create/AllFluids.java @@ -18,11 +18,11 @@ import com.simibubi.create.AllTags.AllFluidTags; import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes; import com.simibubi.create.content.fluids.potion.PotionFluid; import com.simibubi.create.content.fluids.potion.PotionFluid.PotionFluidType; -import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.infrastructure.config.AllConfigs; import com.tterrag.registrate.builders.FluidBuilder.FluidTypeFactory; import com.tterrag.registrate.util.entry.FluidEntry; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.FogRenderer.FogMode; diff --git a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java index 0c857e93d0..e666d1144a 100644 --- a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java +++ b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java @@ -1,95 +1,20 @@ package com.simibubi.create; -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.contraptions.behaviour.FenceGateMovingInteraction; - -import org.jetbrains.annotations.Nullable; - +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; +import com.simibubi.create.api.registry.SimpleRegistry; import com.simibubi.create.content.contraptions.behaviour.DoorMovingInteraction; import com.simibubi.create.content.contraptions.behaviour.LeverMovingInteraction; -import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.behaviour.TrapdoorMovingInteraction; -import com.simibubi.create.foundation.utility.AttachedRegistry; -import com.tterrag.registrate.util.nullness.NonNullConsumer; -import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; public class AllInteractionBehaviours { - private static final AttachedRegistry BLOCK_BEHAVIOURS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final List GLOBAL_BEHAVIOURS = new ArrayList<>(); - - public static void registerBehaviour(ResourceLocation block, MovingInteractionBehaviour provider) { - BLOCK_BEHAVIOURS.register(block, provider); - } - - public static void registerBehaviour(Block block, MovingInteractionBehaviour provider) { - BLOCK_BEHAVIOURS.register(block, provider); - } - - public static void registerBehaviourProvider(BehaviourProvider provider) { - GLOBAL_BEHAVIOURS.add(provider); - } - - @Nullable - public static MovingInteractionBehaviour getBehaviour(BlockState state) { - MovingInteractionBehaviour behaviour = BLOCK_BEHAVIOURS.get(state.getBlock()); - if (behaviour != null) { - return behaviour; - } - - for (BehaviourProvider provider : GLOBAL_BEHAVIOURS) { - behaviour = provider.getBehaviour(state); - if (behaviour != null) { - return behaviour; - } - } - - return null; - } - - public static NonNullConsumer interactionBehaviour( - MovingInteractionBehaviour behaviour) { - return b -> registerBehaviour(b, behaviour); - } - static void registerDefaults() { - registerBehaviour(Blocks.LEVER, new LeverMovingInteraction()); + MovingInteractionBehaviour.REGISTRY.register(Blocks.LEVER, new LeverMovingInteraction()); - DoorMovingInteraction doorBehaviour = new DoorMovingInteraction(); - registerBehaviourProvider(state -> { - if (state.is(BlockTags.WOODEN_DOORS)) { - return doorBehaviour; - } - return null; - }); - - TrapdoorMovingInteraction trapdoorBehaviour = new TrapdoorMovingInteraction(); - registerBehaviourProvider(state -> { - if (state.is(BlockTags.WOODEN_TRAPDOORS)) { - return trapdoorBehaviour; - } - return null; - }); - - FenceGateMovingInteraction fenceGateBehavior = new FenceGateMovingInteraction(); - registerBehaviourProvider(state -> { - if (state.is(BlockTags.FENCE_GATES)) { - return fenceGateBehavior; - } - return null; - }); - - } - - public interface BehaviourProvider { - @Nullable - MovingInteractionBehaviour getBehaviour(BlockState state); + MovingInteractionBehaviour.REGISTRY.registerProvider(SimpleRegistry.Provider.forBlockTag(BlockTags.WOODEN_DOORS, new DoorMovingInteraction())); + MovingInteractionBehaviour.REGISTRY.registerProvider(SimpleRegistry.Provider.forBlockTag(BlockTags.WOODEN_TRAPDOORS, new TrapdoorMovingInteraction())); + MovingInteractionBehaviour.REGISTRY.registerProvider(SimpleRegistry.Provider.forBlockTag(BlockTags.FENCE_GATES, new TrapdoorMovingInteraction())); } } diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index f835461762..7b8bb7c5c2 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -1,9 +1,9 @@ package com.simibubi.create; -import static com.simibubi.create.AllTags.forgeItemTag; import static com.simibubi.create.AllTags.AllItemTags.CREATE_INGOTS; import static com.simibubi.create.AllTags.AllItemTags.CRUSHED_RAW_MATERIALS; import static com.simibubi.create.AllTags.AllItemTags.PLATES; +import static com.simibubi.create.AllTags.forgeItemTag; import static com.simibubi.create.Create.REGISTRATE; import static com.simibubi.create.foundation.data.recipe.CompatMetals.ALUMINUM; import static com.simibubi.create.foundation.data.recipe.CompatMetals.LEAD; @@ -24,8 +24,12 @@ import com.simibubi.create.content.equipment.TreeFertilizerItem; import com.simibubi.create.content.equipment.armor.AllArmorMaterials; import com.simibubi.create.content.equipment.armor.BacktankItem; import com.simibubi.create.content.equipment.armor.BacktankItem.BacktankBlockItem; +import com.simibubi.create.content.equipment.armor.BaseArmorItem; +import com.simibubi.create.content.equipment.armor.CardboardArmorItem; +import com.simibubi.create.content.equipment.armor.CardboardHelmetItem; import com.simibubi.create.content.equipment.armor.DivingBootsItem; import com.simibubi.create.content.equipment.armor.DivingHelmetItem; +import com.simibubi.create.content.equipment.armor.TrimmableArmorModelGenerator; import com.simibubi.create.content.equipment.blueprint.BlueprintItem; import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem; import com.simibubi.create.content.equipment.goggles.GogglesItem; @@ -33,6 +37,7 @@ import com.simibubi.create.content.equipment.goggles.GogglesModel; import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItem; import com.simibubi.create.content.equipment.sandPaper.SandPaperItem; import com.simibubi.create.content.equipment.symmetryWand.SymmetryWandItem; +import com.simibubi.create.content.equipment.tool.CardboardSwordItem; import com.simibubi.create.content.equipment.wrench.WrenchItem; import com.simibubi.create.content.equipment.zapper.terrainzapper.WorldshaperItem; import com.simibubi.create.content.kinetics.belt.item.BeltConnectorItem; @@ -41,7 +46,11 @@ import com.simibubi.create.content.legacy.ChromaticCompoundColor; import com.simibubi.create.content.legacy.ChromaticCompoundItem; import com.simibubi.create.content.legacy.RefinedRadianceItem; import com.simibubi.create.content.legacy.ShadowSteelItem; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.box.PackageStyles; +import com.simibubi.create.content.logistics.box.PackageStyles.PackageStyle; import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.logistics.tableCloth.ShoppingListItem; import com.simibubi.create.content.materials.ExperienceNuggetItem; import com.simibubi.create.content.processing.burner.BlazeBurnerBlockItem; import com.simibubi.create.content.processing.sequenced.SequencedAssemblyItem; @@ -50,19 +59,28 @@ import com.simibubi.create.content.schematics.SchematicAndQuillItem; import com.simibubi.create.content.schematics.SchematicItem; import com.simibubi.create.content.trains.schedule.ScheduleItem; import com.simibubi.create.foundation.data.AssetLookup; +import com.simibubi.create.foundation.data.BuilderTransformers; import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.recipe.CompatMetals; import com.simibubi.create.foundation.item.CombustibleItem; import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.TagDependentIngredientItem; +import com.tterrag.registrate.builders.ItemBuilder; +import com.tterrag.registrate.providers.ProviderType; import com.tterrag.registrate.util.entry.ItemEntry; +import com.tterrag.registrate.util.nullness.NonNullBiConsumer; +import net.minecraft.core.registries.Registries; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ArmorMaterials; import net.minecraft.world.item.Item; import net.minecraft.world.item.Rarity; + import net.minecraftforge.common.Tags; public class AllItems { @@ -78,20 +96,25 @@ public class AllItems { POLISHED_ROSE_QUARTZ = ingredient("polished_rose_quartz"), POWDERED_OBSIDIAN = ingredient("powdered_obsidian"), STURDY_SHEET = taggedIngredient("sturdy_sheet", forgeItemTag("plates/obsidian"), PLATES.tag), PROPELLER = ingredient("propeller"), WHISK = ingredient("whisk"), BRASS_HAND = ingredient("brass_hand"), - CRAFTER_SLOT_COVER = ingredient("crafter_slot_cover"), ELECTRON_TUBE = ingredient("electron_tube"); + CRAFTER_SLOT_COVER = ingredient("crafter_slot_cover"), ELECTRON_TUBE = ingredient("electron_tube"), + TRANSMITTER = ingredient("transmitter"), PULP = ingredient("pulp"); + + public static final ItemEntry CARDBOARD = REGISTRATE.item("cardboard", CombustibleItem::new) + .tag(forgeItemTag("plates/cardboard")) + .onRegister(i -> i.setBurnTime(1000)) + .register(); public static final ItemEntry - INCOMPLETE_PRECISION_MECHANISM = sequencedIngredient("incomplete_precision_mechanism"), + INCOMPLETE_PRECISION_MECHANISM = sequencedIngredient("incomplete_precision_mechanism"), INCOMPLETE_REINFORCED_SHEET = sequencedIngredient("unprocessed_obsidian_sheet"), INCOMPLETE_TRACK = sequencedIngredient("incomplete_track"); public static final ItemEntry PRECISION_MECHANISM = ingredient("precision_mechanism"); - public static final ItemEntry BLAZE_CAKE_BASE = - REGISTRATE.item("blaze_cake_base", Item::new) - .tag(AllItemTags.UPRIGHT_ON_BELT.tag) - .register(); + public static final ItemEntry BLAZE_CAKE_BASE = REGISTRATE.item("blaze_cake_base", Item::new) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) + .register(); public static final ItemEntry BLAZE_CAKE = REGISTRATE.item("blaze_cake", CombustibleItem::new) .tag(AllItemTags.BLAZE_BURNER_FUEL_SPECIAL.tag, AllItemTags.UPRIGHT_ON_BELT.tag) @@ -132,10 +155,25 @@ public class AllItems { public static final ItemEntry BUILDERS_TEA = REGISTRATE.item("builders_tea", BuildersTeaItem::new) .tag(AllItemTags.UPRIGHT_ON_BELT.tag) - .properties(p -> p.stacksTo(16)) + .properties(p -> p + .stacksTo(16) + .food(new FoodProperties.Builder() + .nutrition(1) + .saturationMod(.6F) + .alwaysEat() + .effect(() -> new MobEffectInstance(MobEffects.DIG_SPEED, 3 * 60 * 20, 0, false, false, false), 1F) + .build() + ) + ) .lang("Builder's Tea") .register(); + public static final ItemEntry CARDBOARD_SWORD = + REGISTRATE.item("cardboard_sword", CardboardSwordItem::new) + .properties(p -> p.stacksTo(1)) + .model(AssetLookup.itemModelWithPartials()) + .register(); + public static final ItemEntry RAW_ZINC = taggedIngredient("raw_zinc", forgeItemTag("raw_materials/zinc"), forgeItemTag("raw_materials")); @@ -177,7 +215,7 @@ public class AllItems { IRON_SHEET = taggedIngredient("iron_sheet", forgeItemTag("plates/iron"), PLATES.tag), GOLDEN_SHEET = taggedIngredient("golden_sheet", forgeItemTag("plates/gold"), PLATES.tag, ItemTags.PIGLIN_LOVED), - CRUSHED_IRON = taggedIngredient("crushed_raw_iron", CRUSHED_RAW_MATERIALS.tag), + CRUSHED_IRON = taggedIngredient("crushed_raw_iron", CRUSHED_RAW_MATERIALS.tag), CRUSHED_GOLD = taggedIngredient("crushed_raw_gold", CRUSHED_RAW_MATERIALS.tag, ItemTags.PIGLIN_LOVED), CRUSHED_COPPER = taggedIngredient("crushed_raw_copper", CRUSHED_RAW_MATERIALS.tag), CRUSHED_ZINC = taggedIngredient("crushed_raw_zinc", CRUSHED_RAW_MATERIALS.tag); @@ -242,7 +280,7 @@ public class AllItems { public static final ItemEntry - COPPER_BACKTANK = + COPPER_BACKTANK = REGISTRATE .item("copper_backtank", p -> new BacktankItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving"), @@ -252,47 +290,75 @@ public class AllItems { .tag(forgeItemTag("armors/chestplates")) .register(), - NETHERITE_BACKTANK = REGISTRATE - .item("netherite_backtank", - p -> new BacktankItem.Layered(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"), - NETHERITE_BACKTANK_PLACEABLE)) - .model(AssetLookup.customGenericItemModel("_", "item")) - .properties(p -> p.fireResistant()) - .tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag) - .tag(forgeItemTag("armors/chestplates")) - .register(); + NETHERITE_BACKTANK = REGISTRATE + .item("netherite_backtank", + p -> new BacktankItem.Layered(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"), + NETHERITE_BACKTANK_PLACEABLE)) + .model(AssetLookup.customGenericItemModel("_", "item")) + .properties(p -> p.fireResistant()) + .tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag) + .tag(forgeItemTag("armors/chestplates")) + .register(); public static final ItemEntry - COPPER_DIVING_HELMET = + COPPER_DIVING_HELMET = REGISTRATE .item("copper_diving_helmet", p -> new DivingHelmetItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving"))) .tag(forgeItemTag("armors/helmets")) .register(), - NETHERITE_DIVING_HELMET = REGISTRATE - .item("netherite_diving_helmet", - p -> new DivingHelmetItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"))) - .properties(p -> p.fireResistant()) - .tag(forgeItemTag("armors/helmets")) - .register(); + NETHERITE_DIVING_HELMET = REGISTRATE + .item("netherite_diving_helmet", + p -> new DivingHelmetItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"))) + .properties(p -> p.fireResistant()) + .tag(forgeItemTag("armors/helmets")) + .register(); public static final ItemEntry - COPPER_DIVING_BOOTS = + COPPER_DIVING_BOOTS = REGISTRATE .item("copper_diving_boots", p -> new DivingBootsItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving"))) .tag(forgeItemTag("armors/boots")) .register(), - NETHERITE_DIVING_BOOTS = REGISTRATE - .item("netherite_diving_boots", - p -> new DivingBootsItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"))) - .properties(p -> p.fireResistant()) - .tag(forgeItemTag("armors/boots")) - .register(); + NETHERITE_DIVING_BOOTS = REGISTRATE + .item("netherite_diving_boots", + p -> new DivingBootsItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"))) + .properties(p -> p.fireResistant()) + .tag(forgeItemTag("armors/boots")) + .register(); + + public static final ItemEntry + + CARDBOARD_HELMET = REGISTRATE.item("cardboard_helmet", p -> new CardboardHelmetItem(ArmorItem.Type.HELMET, p)) + .tag(forgeItemTag("armors/helmet"), ItemTags.TRIMMABLE_ARMOR) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "item.create.cardboard_armor")) + .model(TrimmableArmorModelGenerator::generate) + .register(), + + CARDBOARD_CHESTPLATE = + REGISTRATE.item("cardboard_chestplate", p -> new CardboardArmorItem(ArmorItem.Type.CHESTPLATE, p)) + .tag(forgeItemTag("armors/chestplate"), ItemTags.TRIMMABLE_ARMOR) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "item.create.cardboard_armor")) + .model(TrimmableArmorModelGenerator::generate) + .register(), + + CARDBOARD_LEGGINGS = + REGISTRATE.item("cardboard_leggings", p -> new CardboardArmorItem(ArmorItem.Type.LEGGINGS, p)) + .tag(forgeItemTag("armors/leggings"), ItemTags.TRIMMABLE_ARMOR) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "item.create.cardboard_armor")) + .model(TrimmableArmorModelGenerator::generate) + .register(), + + CARDBOARD_BOOTS = REGISTRATE.item("cardboard_boots", p -> new CardboardArmorItem(ArmorItem.Type.BOOTS, p)) + .tag(forgeItemTag("armors/boots"), ItemTags.TRIMMABLE_ARMOR) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "item.create.cardboard_armor")) + .model(TrimmableArmorModelGenerator::generate) + .register(); public static final ItemEntry SAND_PAPER = REGISTRATE.item("sand_paper", SandPaperItem::new) .tag(AllTags.AllItemTags.SANDPAPER.tag) @@ -359,16 +425,40 @@ public class AllItems { // Logistics + static { + boolean rareCreated = false; + boolean normalCreated = false; + for (PackageStyle style : PackageStyles.STYLES) { + ItemBuilder packageItem = BuilderTransformers.packageItem(style); + + if (rareCreated && style.rare() || normalCreated && !style.rare()) + packageItem.setData(ProviderType.LANG, NonNullBiConsumer.noop()); + + rareCreated |= style.rare(); + normalCreated |= !style.rare(); + packageItem.register(); + } + } + public static final ItemEntry FILTER = REGISTRATE.item("filter", FilterItem::regular) .lang("List Filter") - .register(), ATTRIBUTE_FILTER = - REGISTRATE.item("attribute_filter", FilterItem::attribute) - .register(); + .register(), + + ATTRIBUTE_FILTER = REGISTRATE.item("attribute_filter", FilterItem::attribute) + .register(), + + PACKAGE_FILTER = REGISTRATE.item("package_filter", FilterItem::address) + .register(); public static final ItemEntry SCHEDULE = REGISTRATE.item("schedule", ScheduleItem::new) .lang("Train Schedule") .register(); + public static final ItemEntry SHOPPING_LIST = + REGISTRATE.item("shopping_list", ShoppingListItem::new) + .properties(p -> p.stacksTo(1)) + .register(); + // Schematics public static final ItemEntry EMPTY_SCHEMATIC = REGISTRATE.item("empty_schematic", Item::new) @@ -419,6 +509,7 @@ public class AllItems { // Load this class - public static void register() {} + public static void register() { + } } diff --git a/src/main/java/com/simibubi/create/AllKeys.java b/src/main/java/com/simibubi/create/AllKeys.java index 15804c9bb3..b4b99de6a4 100644 --- a/src/main/java/com/simibubi/create/AllKeys.java +++ b/src/main/java/com/simibubi/create/AllKeys.java @@ -1,5 +1,7 @@ package com.simibubi.create; +import java.util.function.BiConsumer; + import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants; @@ -7,6 +9,7 @@ import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RegisterKeyMappingsEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -15,22 +18,34 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD) public enum AllKeys { - TOOL_MENU("toolmenu", GLFW.GLFW_KEY_LEFT_ALT), - ACTIVATE_TOOL("", GLFW.GLFW_KEY_LEFT_CONTROL), - TOOLBELT("toolbelt", GLFW.GLFW_KEY_LEFT_ALT), - PONDER("ponder", GLFW.GLFW_KEY_W) + TOOL_MENU("toolmenu", GLFW.GLFW_KEY_LEFT_ALT, "Focus Schematic Overlay"), + ACTIVATE_TOOL(GLFW.GLFW_KEY_LEFT_CONTROL), + TOOLBELT("toolbelt", GLFW.GLFW_KEY_LEFT_ALT, "Access Nearby Toolboxes"), + ROTATE_MENU("rotate_menu", GLFW.GLFW_KEY_UNKNOWN, "Open Block Rotation Menu"), ; private KeyMapping keybind; - private String description; - private int key; - private boolean modifiable; + private final String description; + private final String translation; + private final int key; + private final boolean modifiable; - private AllKeys(String description, int defaultKey) { + AllKeys(int defaultKey) { + this("", defaultKey, ""); + } + + AllKeys(String description, int defaultKey, String translation) { this.description = Create.ID + ".keyinfo." + description; this.key = defaultKey; this.modifiable = !description.isEmpty(); + this.translation = translation; + } + + public static void provideLang(BiConsumer consumer) { + for (AllKeys key : values()) + if (key.modifiable) + consumer.accept(key.description, key.translation); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/AllMenuTypes.java b/src/main/java/com/simibubi/create/AllMenuTypes.java index 853a9e6471..92244483fb 100644 --- a/src/main/java/com/simibubi/create/AllMenuTypes.java +++ b/src/main/java/com/simibubi/create/AllMenuTypes.java @@ -4,10 +4,22 @@ import com.simibubi.create.content.equipment.blueprint.BlueprintMenu; import com.simibubi.create.content.equipment.blueprint.BlueprintScreen; import com.simibubi.create.content.equipment.toolbox.ToolboxMenu; import com.simibubi.create.content.equipment.toolbox.ToolboxScreen; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSetItemMenu; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSetItemScreen; import com.simibubi.create.content.logistics.filter.AttributeFilterMenu; import com.simibubi.create.content.logistics.filter.AttributeFilterScreen; import com.simibubi.create.content.logistics.filter.FilterMenu; import com.simibubi.create.content.logistics.filter.FilterScreen; +import com.simibubi.create.content.logistics.filter.PackageFilterMenu; +import com.simibubi.create.content.logistics.filter.PackageFilterScreen; +import com.simibubi.create.content.logistics.packagePort.PackagePortMenu; +import com.simibubi.create.content.logistics.packagePort.PackagePortScreen; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterMenu; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterScreen; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperCategoryMenu; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperCategoryScreen; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperRequestMenu; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperRequestScreen; import com.simibubi.create.content.redstone.link.controller.LinkedControllerMenu; import com.simibubi.create.content.redstone.link.controller.LinkedControllerScreen; import com.simibubi.create.content.schematics.cannon.SchematicannonMenu; @@ -38,6 +50,9 @@ public class AllMenuTypes { public static final MenuEntry ATTRIBUTE_FILTER = register("attribute_filter", AttributeFilterMenu::new, () -> AttributeFilterScreen::new); + + public static final MenuEntry PACKAGE_FILTER = + register("package_filter", PackageFilterMenu::new, () -> PackageFilterScreen::new); public static final MenuEntry CRAFTING_BLUEPRINT = register("crafting_blueprint", BlueprintMenu::new, () -> BlueprintScreen::new); @@ -50,7 +65,22 @@ public class AllMenuTypes { public static final MenuEntry SCHEDULE = register("schedule", ScheduleMenu::new, () -> ScheduleScreen::new); - + + public static final MenuEntry STOCK_KEEPER_CATEGORY = + register("stock_keeper_category", StockKeeperCategoryMenu::new, () -> StockKeeperCategoryScreen::new); + + public static final MenuEntry STOCK_KEEPER_REQUEST = + register("stock_keeper_request", StockKeeperRequestMenu::new, () -> StockKeeperRequestScreen::new); + + public static final MenuEntry PACKAGE_PORT = + register("package_port", PackagePortMenu::new, () -> PackagePortScreen::new); + + public static final MenuEntry REDSTONE_REQUESTER = + register("redstone_requester", RedstoneRequesterMenu::new, () -> RedstoneRequesterScreen::new); + + public static final MenuEntry FACTORY_PANEL_SET_ITEM = + register("factory_panel_set_item", FactoryPanelSetItemMenu::new, () -> FactoryPanelSetItemScreen::new); + private static > MenuEntry register( String name, ForgeMenuFactory factory, NonNullSupplier> screenFactory) { return Create.REGISTRATE diff --git a/src/main/java/com/simibubi/create/AllMountedDispenseItemBehaviors.java b/src/main/java/com/simibubi/create/AllMountedDispenseItemBehaviors.java new file mode 100644 index 0000000000..167b2db402 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllMountedDispenseItemBehaviors.java @@ -0,0 +1,190 @@ +package com.simibubi.create; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.dispenser.DefaultMountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedProjectileDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.OptionalMountedDispenseBehavior; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.entity.projectile.FireworkRocketEntity; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.projectile.SmallFireball; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.BeehiveBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BucketPickup; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.level.block.entity.BeehiveBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class AllMountedDispenseItemBehaviors { + private static final MountedDispenseBehavior SPAWN_EGG = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + if (!(stack.getItem() instanceof SpawnEggItem egg)) + return super.execute(stack, context, pos, facing); + + if (context.world instanceof ServerLevel serverLevel) { + EntityType type = egg.getType(stack.getTag()); + BlockPos offset = BlockPos.containing(facing.x + .7, facing.y + .7, facing.z + .7); + Entity entity = type.spawn(serverLevel, stack, null, pos.offset(offset), MobSpawnType.DISPENSER, facing.y < .5, false); + if (entity != null) { + entity.setDeltaMovement(context.motion.scale(2)); + } + } + + stack.shrink(1); + return stack; + } + }; + private static final MountedDispenseBehavior TNT = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + PrimedTnt tnt = new PrimedTnt(context.world, x, y, z, null); + tnt.push(context.motion.x, context.motion.y, context.motion.z); + context.world.addFreshEntity(tnt); + context.world.playSound(null, tnt.getX(), tnt.getY(), tnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1, 1); + stack.shrink(1); + return stack; + } + }; + private static final MountedDispenseBehavior FIREWORK = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + FireworkRocketEntity firework = new FireworkRocketEntity(context.world, stack, x, y, z, true); + firework.shoot(facing.x, facing.y, facing.z, 0.5F, 1.0F); + context.world.addFreshEntity(firework); + stack.shrink(1); + return stack; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_FIREWORK_SHOOT, pos, 0); + } + }; + private static final MountedDispenseBehavior FIRE_CHARGE = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + RandomSource random = context.world.random; + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + SmallFireball fireball = new SmallFireball( + context.world, + x, y, z, + random.nextGaussian() * 0.05 + facing.x + context.motion.x, + random.nextGaussian() * 0.05 + facing.y + context.motion.y, + random.nextGaussian() * 0.05 + facing.z + context.motion.z + ); + fireball.setItem(stack); // copies the stack + context.world.addFreshEntity(fireball); + stack.shrink(1); + return stack; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_BLAZE_FIREBALL, pos, 0); + } + }; + private static final MountedDispenseBehavior BUCKET = new DefaultMountedDispenseBehavior() { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + BlockPos interactionPos = pos.relative(MountedDispenseBehavior.getClosestFacingDirection(facing)); + BlockState state = context.world.getBlockState(interactionPos); + if (!(state.getBlock() instanceof BucketPickup bucketPickup)) { + return super.execute(stack, context, pos, facing); + } + + ItemStack bucket = bucketPickup.pickupBlock(context.world, interactionPos, state); + MountedDispenseBehavior.placeItemInInventory(bucket, context, pos); + stack.shrink(1); + return stack; + } + }; + private static final MountedDispenseBehavior POTIONS = new MountedProjectileDispenseBehavior() { + @Override + protected Projectile getProjectile(Level level, double x, double y, double z, ItemStack stack) { + ThrownPotion potion = new ThrownPotion(level, x, y, z); + potion.setItem(stack); // copies item + return potion; + } + + @Override + protected float getUncertainty() { + return super.getUncertainty() * 0.5f; + } + + @Override + protected float getPower() { + return super.getPower() * 1.25f; + } + }; + private static final MountedDispenseBehavior BOTTLE = new OptionalMountedDispenseBehavior() { + @Override + @Nullable + protected ItemStack doExecute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + BlockPos interactionPos = pos.relative(MountedDispenseBehavior.getClosestFacingDirection(facing)); + BlockState state = context.world.getBlockState(interactionPos); + Block block = state.getBlock(); + + if (block instanceof BeehiveBlock hive && state.is(BlockTags.BEEHIVES) && state.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { + hive.releaseBeesAndResetHoneyLevel(context.world, state, interactionPos, null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); + MountedDispenseBehavior.placeItemInInventory(new ItemStack(Items.HONEY_BOTTLE), context, pos); + stack.shrink(1); + return stack; + } else if (context.world.getFluidState(interactionPos).is(FluidTags.WATER)) { + ItemStack waterBottle = PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER); + MountedDispenseBehavior.placeItemInInventory(waterBottle, context, pos); + stack.shrink(1); + return stack; + } else { + return null; + } + } + }; + + public static void registerDefaults() { + for (SpawnEggItem egg : SpawnEggItem.eggs()) { + MountedDispenseBehavior.REGISTRY.register(egg, SPAWN_EGG); + } + + MountedDispenseBehavior.REGISTRY.register(Items.TNT, TNT); + MountedDispenseBehavior.REGISTRY.register(Items.FIREWORK_ROCKET, FIREWORK); + MountedDispenseBehavior.REGISTRY.register(Items.FIRE_CHARGE, FIRE_CHARGE); + MountedDispenseBehavior.REGISTRY.register(Items.BUCKET, BUCKET); + MountedDispenseBehavior.REGISTRY.register(Items.GLASS_BOTTLE, BOTTLE); + + // potions can't be automatically converted since they use a weird wrapper thing + MountedDispenseBehavior.REGISTRY.register(Items.SPLASH_POTION, POTIONS); + MountedDispenseBehavior.REGISTRY.register(Items.LINGERING_POTION, POTIONS); + } +} diff --git a/src/main/java/com/simibubi/create/AllMountedStorageTypes.java b/src/main/java/com/simibubi/create/AllMountedStorageTypes.java new file mode 100644 index 0000000000..1efde13aac --- /dev/null +++ b/src/main/java/com/simibubi/create/AllMountedStorageTypes.java @@ -0,0 +1,57 @@ +package com.simibubi.create; + +import static com.simibubi.create.Create.REGISTRATE; + +import java.util.function.Supplier; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.chest.ChestMountedStorageType; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorageType; +import com.simibubi.create.content.contraptions.behaviour.dispenser.storage.DispenserMountedStorageType; +import com.simibubi.create.content.equipment.toolbox.ToolboxMountedStorageType; +import com.simibubi.create.content.fluids.tank.storage.FluidTankMountedStorageType; +import com.simibubi.create.content.fluids.tank.storage.creative.CreativeFluidTankMountedStorageType; +import com.simibubi.create.content.logistics.crate.CreativeCrateMountedStorageType; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorageType; +import com.simibubi.create.content.logistics.vault.ItemVaultMountedStorageType; +import com.simibubi.create.impl.contraption.storage.FallbackMountedStorageType; +import com.tterrag.registrate.util.entry.RegistryEntry; + +import net.minecraft.world.level.block.Blocks; + +public class AllMountedStorageTypes { + // fallback is special, provider is registered on lookup creation so it's always last + public static final RegistryEntry FALLBACK = simpleItem("fallback", FallbackMountedStorageType::new); + + // registrations for these are handled by the blocks, not the types + public static final RegistryEntry CREATIVE_CRATE = simpleItem("creative_crate", CreativeCrateMountedStorageType::new); + public static final RegistryEntry VAULT = simpleItem("vault", ItemVaultMountedStorageType::new); + public static final RegistryEntry TOOLBOX = simpleItem("toolbox", ToolboxMountedStorageType::new); + public static final RegistryEntry DEPOT = simpleItem("depot", DepotMountedStorageType::new); + public static final RegistryEntry FLUID_TANK = simpleFluid("fluid_tank", FluidTankMountedStorageType::new); + public static final RegistryEntry CREATIVE_FLUID_TANK = simpleFluid("creative_fluid_tank", CreativeFluidTankMountedStorageType::new); + + // these are for external blocks, register associations here + public static final RegistryEntry SIMPLE = REGISTRATE.mountedItemStorage("simple", SimpleMountedStorageType.Impl::new) + .associateBlockTag(AllTags.AllBlockTags.SIMPLE_MOUNTED_STORAGE.tag) + .register(); + public static final RegistryEntry CHEST = REGISTRATE.mountedItemStorage("chest", ChestMountedStorageType::new) + .associateBlockTag(AllTags.AllBlockTags.CHEST_MOUNTED_STORAGE.tag) + .register(); + public static final RegistryEntry DISPENSER = REGISTRATE.mountedItemStorage("dispenser", DispenserMountedStorageType::new) + .associate(Blocks.DISPENSER) + .associate(Blocks.DROPPER) + .register(); + + private static > RegistryEntry simpleItem(String name, Supplier supplier) { + return REGISTRATE.mountedItemStorage(name, supplier).register(); + } + + private static > RegistryEntry simpleFluid(String name, Supplier supplier) { + return REGISTRATE.mountedFluidStorage(name, supplier).register(); + } + + public static void register() { + } +} diff --git a/src/main/java/com/simibubi/create/AllMovementBehaviours.java b/src/main/java/com/simibubi/create/AllMovementBehaviours.java index 6dde486402..d218ff7eeb 100644 --- a/src/main/java/com/simibubi/create/AllMovementBehaviours.java +++ b/src/main/java/com/simibubi/create/AllMovementBehaviours.java @@ -1,74 +1,19 @@ package com.simibubi.create; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; - +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.BellMovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.CampfireMovementBehaviour; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.dispenser.DispenserMovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.dispenser.DropperMovementBehaviour; -import com.simibubi.create.foundation.utility.AttachedRegistry; -import com.tterrag.registrate.util.nullness.NonNullConsumer; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; public class AllMovementBehaviours { - private static final AttachedRegistry BLOCK_BEHAVIOURS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final List GLOBAL_BEHAVIOURS = new ArrayList<>(); - - public static void registerBehaviour(ResourceLocation block, MovementBehaviour behaviour) { - BLOCK_BEHAVIOURS.register(block, behaviour); - } - - public static void registerBehaviour(Block block, MovementBehaviour behaviour) { - BLOCK_BEHAVIOURS.register(block, behaviour); - } - - public static void registerBehaviourProvider(BehaviourProvider provider) { - GLOBAL_BEHAVIOURS.add(provider); - } - - @Nullable - public static MovementBehaviour getBehaviour(BlockState state) { - MovementBehaviour behaviour = BLOCK_BEHAVIOURS.get(state.getBlock()); - if (behaviour != null) { - return behaviour; - } - - for (BehaviourProvider provider : GLOBAL_BEHAVIOURS) { - behaviour = provider.getBehaviour(state); - if (behaviour != null) { - return behaviour; - } - } - - return null; - } - - public static NonNullConsumer movementBehaviour( - MovementBehaviour behaviour) { - return b -> registerBehaviour(b, behaviour); - } - static void registerDefaults() { - registerBehaviour(Blocks.BELL, new BellMovementBehaviour()); - registerBehaviour(Blocks.CAMPFIRE, new CampfireMovementBehaviour()); - registerBehaviour(Blocks.SOUL_CAMPFIRE, new CampfireMovementBehaviour()); - - DispenserMovementBehaviour.gatherMovedDispenseItemBehaviours(); - registerBehaviour(Blocks.DISPENSER, new DispenserMovementBehaviour()); - registerBehaviour(Blocks.DROPPER, new DropperMovementBehaviour()); - } - - public interface BehaviourProvider { - @Nullable - MovementBehaviour getBehaviour(BlockState state); + MovementBehaviour.REGISTRY.register(Blocks.BELL, new BellMovementBehaviour()); + MovementBehaviour.REGISTRY.register(Blocks.CAMPFIRE, new CampfireMovementBehaviour()); + MovementBehaviour.REGISTRY.register(Blocks.SOUL_CAMPFIRE, new CampfireMovementBehaviour()); + MovementBehaviour.REGISTRY.register(Blocks.DISPENSER, new DispenserMovementBehaviour()); + MovementBehaviour.REGISTRY.register(Blocks.DROPPER, new DropperMovementBehaviour()); } } diff --git a/src/main/java/com/simibubi/create/AllOpenPipeEffectHandlers.java b/src/main/java/com/simibubi/create/AllOpenPipeEffectHandlers.java new file mode 100644 index 0000000000..ff373760bf --- /dev/null +++ b/src/main/java/com/simibubi/create/AllOpenPipeEffectHandlers.java @@ -0,0 +1,23 @@ +package com.simibubi.create; + +import com.simibubi.create.api.effect.OpenPipeEffectHandler; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.impl.effect.LavaEffectHandler; +import com.simibubi.create.impl.effect.MilkEffectHandler; +import com.simibubi.create.impl.effect.PotionEffectHandler; +import com.simibubi.create.impl.effect.TeaEffectHandler; +import com.simibubi.create.impl.effect.WaterEffectHandler; + +import net.minecraft.tags.FluidTags; + +import net.minecraftforge.common.Tags; + +public class AllOpenPipeEffectHandlers { + public static void registerDefaults() { + OpenPipeEffectHandler.REGISTRY.registerProvider(SimpleRegistry.Provider.forFluidTag(FluidTags.WATER, new WaterEffectHandler())); + OpenPipeEffectHandler.REGISTRY.registerProvider(SimpleRegistry.Provider.forFluidTag(FluidTags.LAVA, new LavaEffectHandler())); + OpenPipeEffectHandler.REGISTRY.registerProvider(SimpleRegistry.Provider.forFluidTag(Tags.Fluids.MILK, new MilkEffectHandler())); + OpenPipeEffectHandler.REGISTRY.register(AllFluids.POTION.getSource(), new PotionEffectHandler()); + OpenPipeEffectHandler.REGISTRY.register(AllFluids.TEA.getSource(), new TeaEffectHandler()); + } +} diff --git a/src/main/java/com/simibubi/create/AllPackets.java b/src/main/java/com/simibubi/create/AllPackets.java index 4123752808..5dc3a044e0 100644 --- a/src/main/java/com/simibubi/create/AllPackets.java +++ b/src/main/java/com/simibubi/create/AllPackets.java @@ -16,6 +16,7 @@ import com.simibubi.create.content.contraptions.ContraptionColliderLockPacket.Co import com.simibubi.create.content.contraptions.ContraptionDisassemblyPacket; import com.simibubi.create.content.contraptions.ContraptionRelocationPacket; import com.simibubi.create.content.contraptions.ContraptionStallPacket; +import com.simibubi.create.content.contraptions.MountedStorageSyncPacket; import com.simibubi.create.content.contraptions.TrainCollisionPacket; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionDisableActorPacket; import com.simibubi.create.content.contraptions.actors.trainControls.ControlsInputPacket; @@ -30,32 +31,52 @@ import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionPacket; import com.simibubi.create.content.contraptions.minecart.CouplingCreationPacket; import com.simibubi.create.content.contraptions.minecart.capability.MinecartControllerUpdatePacket; import com.simibubi.create.content.contraptions.sync.ClientMotionPacket; -import com.simibubi.create.content.contraptions.sync.ContraptionFluidPacket; import com.simibubi.create.content.contraptions.sync.ContraptionInteractionPacket; import com.simibubi.create.content.contraptions.sync.ContraptionSeatMappingPacket; import com.simibubi.create.content.contraptions.sync.LimbSwingUpdatePacket; +import com.simibubi.create.content.contraptions.wrench.RadialWrenchMenuSubmitPacket; import com.simibubi.create.content.equipment.bell.SoulPulseEffectPacket; import com.simibubi.create.content.equipment.blueprint.BlueprintAssignCompleteRecipePacket; import com.simibubi.create.content.equipment.clipboard.ClipboardEditPacket; import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripInteractionPacket; import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonPacket; -import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileTypeManager; import com.simibubi.create.content.equipment.symmetryWand.ConfigureSymmetryWandPacket; import com.simibubi.create.content.equipment.symmetryWand.SymmetryEffectPacket; +import com.simibubi.create.content.equipment.tool.KnockbackPacket; import com.simibubi.create.content.equipment.toolbox.ToolboxDisposeAllPacket; import com.simibubi.create.content.equipment.toolbox.ToolboxEquipPacket; import com.simibubi.create.content.equipment.zapper.ZapperBeamPacket; import com.simibubi.create.content.equipment.zapper.terrainzapper.ConfigureWorldshaperPacket; import com.simibubi.create.content.fluids.transfer.FluidSplashPacket; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorConnectionPacket; +import com.simibubi.create.content.kinetics.chainConveyor.ChainPackageInteractionPacket; +import com.simibubi.create.content.kinetics.chainConveyor.ClientboundChainConveyorRidingPacket; +import com.simibubi.create.content.kinetics.chainConveyor.ServerboundChainConveyorRidingPacket; import com.simibubi.create.content.kinetics.gauge.GaugeObservedPacket; import com.simibubi.create.content.kinetics.mechanicalArm.ArmPlacementPacket; import com.simibubi.create.content.kinetics.transmission.sequencer.ConfigureSequencedGearshiftPacket; +import com.simibubi.create.content.logistics.box.PackageDestroyPacket; import com.simibubi.create.content.logistics.depot.EjectorAwardPacket; import com.simibubi.create.content.logistics.depot.EjectorElytraPacket; import com.simibubi.create.content.logistics.depot.EjectorPlacementPacket; import com.simibubi.create.content.logistics.depot.EjectorTriggerPacket; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelConfigurationPacket; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelConnectionPacket; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelEffectPacket; import com.simibubi.create.content.logistics.filter.FilterScreenPacket; import com.simibubi.create.content.logistics.funnel.FunnelFlapPacket; +import com.simibubi.create.content.logistics.packagePort.PackagePortConfigurationPacket; +import com.simibubi.create.content.logistics.packagePort.PackagePortPlacementPacket; +import com.simibubi.create.content.logistics.packagerLink.WiFiEffectPacket; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterConfigurationPacket; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterEffectPacket; +import com.simibubi.create.content.logistics.stockTicker.LogisticalStockRequestPacket; +import com.simibubi.create.content.logistics.stockTicker.LogisticalStockResponsePacket; +import com.simibubi.create.content.logistics.stockTicker.PackageOrderRequestPacket; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperCategoryEditPacket; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperCategoryHidingPacket; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperCategoryRefundPacket; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperLockPacket; import com.simibubi.create.content.logistics.tunnel.TunnelFlapPacket; import com.simibubi.create.content.redstone.displayLink.DisplayLinkConfigurationPacket; import com.simibubi.create.content.redstone.link.controller.LinkedControllerBindPacket; @@ -85,7 +106,6 @@ import com.simibubi.create.content.trains.track.CurvedTrackSelectionPacket; import com.simibubi.create.content.trains.track.PlaceExtendedCurvePacket; import com.simibubi.create.foundation.blockEntity.RemoveBlockEntityPacket; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsPacket; -import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket; import com.simibubi.create.foundation.gui.menu.ClearMenuPacket; import com.simibubi.create.foundation.gui.menu.GhostItemSubmitPacket; import com.simibubi.create.foundation.networking.ISyncPersistentData; @@ -93,13 +113,15 @@ import com.simibubi.create.foundation.networking.LeftClickPacket; import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.infrastructure.command.HighlightPacket; -import com.simibubi.create.infrastructure.command.SConfigureConfigPacket; +import com.simibubi.create.infrastructure.command.SimpleCreateActions; import com.simibubi.create.infrastructure.debugInfo.ServerDebugInfoPacket; +import net.createmod.catnip.net.ClientboundSimpleActionPacket; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; + import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent.Context; import net.minecraftforge.network.NetworkRegistry; @@ -122,6 +144,7 @@ public enum AllPackets { CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new, PLAY_TO_SERVER), CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new, PLAY_TO_SERVER), PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new, PLAY_TO_SERVER), + PLACE_PACKAGE_PORT(PackagePortPlacementPacket.class, PackagePortPlacementPacket::new, PLAY_TO_SERVER), MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new, PLAY_TO_SERVER), INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new, PLAY_TO_SERVER), SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new, PLAY_TO_SERVER), @@ -133,7 +156,6 @@ public enum AllPackets { LINKED_CONTROLLER_BIND(LinkedControllerBindPacket.class, LinkedControllerBindPacket::new, PLAY_TO_SERVER), LINKED_CONTROLLER_USE_LECTERN(LinkedControllerStopLecternPacket.class, LinkedControllerStopLecternPacket::new, PLAY_TO_SERVER), - C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER), SUBMIT_GHOST_ITEM(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new, PLAY_TO_SERVER), BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new, PLAY_TO_SERVER), @@ -166,13 +188,27 @@ public enum AllPackets { CLIPBOARD_EDIT(ClipboardEditPacket.class, ClipboardEditPacket::new, PLAY_TO_SERVER), CONTRAPTION_COLLIDER_LOCK_REQUEST(ContraptionColliderLockPacketRequest.class, ContraptionColliderLockPacketRequest::new, PLAY_TO_SERVER), + RADIAL_WRENCH_MENU_SUBMIT(RadialWrenchMenuSubmitPacket.class, RadialWrenchMenuSubmitPacket::new, + PLAY_TO_SERVER), + LOGISTICS_STOCK_REQUEST(LogisticalStockRequestPacket.class, LogisticalStockRequestPacket::new, PLAY_TO_SERVER), + LOGISTICS_PACKAGE_REQUEST(PackageOrderRequestPacket.class, PackageOrderRequestPacket::new, PLAY_TO_SERVER), + CHAIN_CONVEYOR_CONNECT(ChainConveyorConnectionPacket.class, ChainConveyorConnectionPacket::new, PLAY_TO_SERVER), + CHAIN_CONVEYOR_RIDING(ServerboundChainConveyorRidingPacket.class, ServerboundChainConveyorRidingPacket::new, PLAY_TO_SERVER), + CHAIN_PACKAGE_INTERACTION(ChainPackageInteractionPacket.class, ChainPackageInteractionPacket::new, PLAY_TO_SERVER), + PACKAGE_PORT_CONFIGURATION(PackagePortConfigurationPacket.class, PackagePortConfigurationPacket::new, PLAY_TO_SERVER), TRAIN_MAP_REQUEST(TrainMapSyncRequestPacket.class, TrainMapSyncRequestPacket::new, PLAY_TO_SERVER), + CONNECT_FACTORY_PANEL(FactoryPanelConnectionPacket.class, FactoryPanelConnectionPacket::new, PLAY_TO_SERVER), + CONFIGURE_FACTORY_PANEL(FactoryPanelConfigurationPacket.class, FactoryPanelConfigurationPacket::new, PLAY_TO_SERVER), + CONFIGURE_REDSTONE_REQUESTER(RedstoneRequesterConfigurationPacket.class, RedstoneRequesterConfigurationPacket::new, PLAY_TO_SERVER), + CONFIGURE_STOCK_KEEPER_CATEGORIES(StockKeeperCategoryEditPacket.class, StockKeeperCategoryEditPacket::new, PLAY_TO_SERVER), + REFUND_STOCK_KEEPER_CATEGORY(StockKeeperCategoryRefundPacket.class, StockKeeperCategoryRefundPacket::new, PLAY_TO_SERVER), + LOCK_STOCK_KEEPER(StockKeeperLockPacket.class, StockKeeperLockPacket::new, PLAY_TO_SERVER), + STOCK_KEEPER_HIDE_CATEGORY(StockKeeperCategoryHidingPacket.class, StockKeeperCategoryHidingPacket::new, PLAY_TO_SERVER), // Server to Client SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT), BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT), - S_CONFIGURE_CONFIG(SConfigureConfigPacket.class, SConfigureConfigPacket::new, PLAY_TO_CLIENT), CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT), CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT), CONTRAPTION_BLOCK_CHANGED(ContraptionBlockChangedPacket.class, ContraptionBlockChangedPacket::new, PLAY_TO_CLIENT), @@ -181,7 +217,7 @@ public enum AllPackets { LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new, PLAY_TO_CLIENT), MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new, PLAY_TO_CLIENT), FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT), - CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT), + MOUNTED_STORAGE_SYNC(MountedStorageSyncPacket.class, MountedStorageSyncPacket::new, PLAY_TO_CLIENT), GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new, PLAY_TO_CLIENT), BLOCK_HIGHLIGHT(HighlightPacket.class, HighlightPacket::new, PLAY_TO_CLIENT), TUNNEL_FLAP(TunnelFlapPacket.class, TunnelFlapPacket::new, PLAY_TO_CLIENT), @@ -190,8 +226,6 @@ public enum AllPackets { SOUL_PULSE(SoulPulseEffectPacket.class, SoulPulseEffectPacket::new, PLAY_TO_CLIENT), PERSISTENT_DATA(ISyncPersistentData.PersistentDataPacket.class, ISyncPersistentData.PersistentDataPacket::new, PLAY_TO_CLIENT), - SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class, - PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT), SYNC_RAIL_GRAPH(TrackGraphSyncPacket.class, TrackGraphSyncPacket::new, PLAY_TO_CLIENT), SYNC_EDGE_GROUP(SignalEdgeGroupPacket.class, SignalEdgeGroupPacket::new, PLAY_TO_CLIENT), SYNC_TRAIN(TrainPacket.class, TrainPacket::new, PLAY_TO_CLIENT), @@ -207,13 +241,33 @@ public enum AllPackets { PLAY_TO_CLIENT), S_PLACE_ARM(EjectorPlacementPacket.ClientBoundRequest.class, EjectorPlacementPacket.ClientBoundRequest::new, PLAY_TO_CLIENT), + S_PLACE_PACKAGE_PORT(PackagePortPlacementPacket.ClientBoundRequest.class, PackagePortPlacementPacket.ClientBoundRequest::new, + PLAY_TO_CLIENT), UPDATE_ELEVATOR_FLOORS(ElevatorFloorListPacket.class, ElevatorFloorListPacket::new, PLAY_TO_CLIENT), CONTRAPTION_ACTOR_TOGGLE(ContraptionDisableActorPacket.class, ContraptionDisableActorPacket::new, PLAY_TO_CLIENT), CONTRAPTION_COLLIDER_LOCK(ContraptionColliderLockPacket.class, ContraptionColliderLockPacket::new, PLAY_TO_CLIENT), ATTACHED_COMPUTER(AttachedComputerPacket.class, AttachedComputerPacket::new, PLAY_TO_CLIENT), SERVER_DEBUG_INFO(ServerDebugInfoPacket.class, ServerDebugInfoPacket::new, PLAY_TO_CLIENT), - TRAIN_MAP_SYNC(TrainMapSyncPacket.class, TrainMapSyncPacket::new, PLAY_TO_CLIENT) - ; + PACKAGE_DESTROYED(PackageDestroyPacket.class, PackageDestroyPacket::new, PLAY_TO_CLIENT), + LOGISTICS_STOCK_RESPONSE(LogisticalStockResponsePacket.class, LogisticalStockResponsePacket::new, PLAY_TO_CLIENT), + FACTORY_PANEL_EFFECT(FactoryPanelEffectPacket.class, FactoryPanelEffectPacket::new, PLAY_TO_CLIENT), + PACKAGER_LINK_EFFECT(WiFiEffectPacket.class, WiFiEffectPacket::new, PLAY_TO_CLIENT), + REDSTONE_REQUESTER_EFFECT(RedstoneRequesterEffectPacket.class, RedstoneRequesterEffectPacket::new, PLAY_TO_CLIENT), + KNOCKBACK(KnockbackPacket.class, KnockbackPacket::new, PLAY_TO_CLIENT), + TRAIN_MAP_SYNC(TrainMapSyncPacket.class, TrainMapSyncPacket::new, PLAY_TO_CLIENT), + CLIENTBOUND_CHAIN_CONVEYOR(ClientboundChainConveyorRidingPacket.class, ClientboundChainConveyorRidingPacket::new, PLAY_TO_CLIENT); + + static { + ClientboundSimpleActionPacket.addAction("rainbowDebug", () -> SimpleCreateActions::rainbowDebug); + ClientboundSimpleActionPacket.addAction("overlayReset", () -> SimpleCreateActions::overlayReset); + ClientboundSimpleActionPacket.addAction("overlayScreen", () -> SimpleCreateActions::overlayScreen); + ClientboundSimpleActionPacket.addAction("experimentalLighting", () -> SimpleCreateActions::experimentalLighting); + ClientboundSimpleActionPacket.addAction("fabulousWarning", () -> SimpleCreateActions::fabulousWarning); + ClientboundSimpleActionPacket.addAction("zoomMultiplier", () -> SimpleCreateActions::zoomMultiplier); + ClientboundSimpleActionPacket.addAction("camAngleYawTarget", () -> value -> SimpleCreateActions.camAngleTarget(value, true)); + ClientboundSimpleActionPacket.addAction("camAnglePitchTarget", () -> value -> SimpleCreateActions.camAngleTarget(value, false)); + ClientboundSimpleActionPacket.addAction("camAngleFunction", () -> SimpleCreateActions::camAngleFunction); + } public static final ResourceLocation CHANNEL_NAME = Create.asResource("main"); public static final int NETWORK_VERSION = 3; @@ -223,7 +277,7 @@ public enum AllPackets { private PacketType packetType; AllPackets(Class type, Function factory, - NetworkDirection direction) { + NetworkDirection direction) { packetType = new PacketType<>(type, factory, direction); } diff --git a/src/main/java/com/simibubi/create/AllPartialModels.java b/src/main/java/com/simibubi/create/AllPartialModels.java index 9a5b37c76f..705a21d2db 100644 --- a/src/main/java/com/simibubi/create/AllPartialModels.java +++ b/src/main/java/com/simibubi/create/AllPartialModels.java @@ -7,11 +7,14 @@ import java.util.List; import java.util.Map; import com.simibubi.create.content.fluids.FluidTransportBehaviour; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; +import com.simibubi.create.content.logistics.box.PackageStyles; +import com.simibubi.create.content.logistics.box.PackageStyles.PackageStyle; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.DyeColor; @@ -24,6 +27,8 @@ public class AllPartialModels { SHAFTLESS_COGWHEEL = block("cogwheel_shaftless"), SHAFTLESS_LARGE_COGWHEEL = block("large_cogwheel_shaftless"), COGWHEEL_SHAFT = block("cogwheel_shaft"), SHAFT_HALF = block("shaft_half"), + SHAFT = block("shaft"), + COGWHEEL = block("cogwheel"), BELT_PULLEY = block("belt_pulley"), BELT_START = block("belt/start"), BELT_MIDDLE = block("belt/middle"), BELT_END = block("belt/end"), BELT_START_BOTTOM = block("belt/start_bottom"), @@ -36,6 +41,8 @@ public class AllPartialModels { BRASS_BELT_COVER_Z = block("belt_cover/brass_belt_cover_z"), ENCASED_FAN_INNER = block("encased_fan/propeller"), HAND_CRANK_HANDLE = block("hand_crank/handle"), + HAND_CRANK_BASE = block("hand_crank/block"), + VALVE_HANDLE = block("valve_handle"), MECHANICAL_PRESS_HEAD = block("mechanical_press/head"), MECHANICAL_MIXER_POLE = block("mechanical_mixer/pole"), MECHANICAL_MIXER_HEAD = block("mechanical_mixer/head"), MECHANICAL_CRAFTER_LID = block("mechanical_crafter/lid"), @@ -59,8 +66,7 @@ public class AllPartialModels { BELT_FUNNEL_FLAP = block("belt_funnel/flap"), BELT_TUNNEL_FLAP = block("belt_tunnel/flap"), FLEXPEATER_INDICATOR = block("diodes/indicator"), - ROLLER_WHEEL = block("mechanical_roller/wheel"), - ROLLER_FRAME = block("mechanical_roller/frame"), + ROLLER_WHEEL = block("mechanical_roller/wheel"), ROLLER_FRAME = block("mechanical_roller/frame"), CUCKOO_MINUTE_HAND = block("cuckoo_clock/minute_hand"), CUCKOO_HOUR_HAND = block("cuckoo_clock/hour_hand"), CUCKOO_LEFT_DOOR = block("cuckoo_clock/left_door"), CUCKOO_RIGHT_DOOR = block("cuckoo_clock/right_door"), @@ -70,8 +76,10 @@ public class AllPartialModels { ROPE_COIL = block("rope_pulley/rope_coil"), ROPE_HALF = block("rope_pulley/rope_half"), ROPE_HALF_MAGNET = block("rope_pulley/rope_half_magnet"), + ROPE = block("rope_pulley/rope"), + PULLEY_MAGNET = block("rope_pulley/pulley_magnet"), - HOSE_COIL = block("hose_pulley/rope_coil"), HOSE = block("hose_pulley/rope"), + HOSE_COIL = block("hose_pulley/hose_coil"), HOSE = block("hose_pulley/rope"), HOSE_MAGNET = block("hose_pulley/pulley_magnet"), HOSE_HALF = block("hose_pulley/rope_half"), HOSE_HALF_MAGNET = block("hose_pulley/rope_half_magnet"), @@ -85,6 +93,9 @@ public class AllPartialModels { STICKER_HEAD = block("sticker/head"), + DESK_BELL_PLUNGER = block("desk_bell/plunger"), + DESK_BELL_BELL = block("desk_bell/bell"), + PORTABLE_STORAGE_INTERFACE_MIDDLE = block("portable_storage_interface/block_middle"), PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED = block("portable_storage_interface/block_middle_powered"), PORTABLE_STORAGE_INTERFACE_TOP = block("portable_storage_interface/block_top"), @@ -100,8 +111,8 @@ public class AllPartialModels { ARM_CLAW_GRIP_UPPER = block("mechanical_arm/upper_claw_grip"), ARM_CLAW_GRIP_LOWER = block("mechanical_arm/lower_claw_grip"), - MECHANICAL_PUMP_COG = block("mechanical_pump/cog"), - FLUID_PIPE_CASING = block("fluid_pipe/casing"), FLUID_VALVE_POINTER = block("fluid_valve/pointer"), + MECHANICAL_PUMP_COG = block("mechanical_pump/cog"), FLUID_PIPE_CASING = block("fluid_pipe/casing"), + FLUID_VALVE_POINTER = block("fluid_valve/pointer"), SPOUT_TOP = block("spout/top"), SPOUT_MIDDLE = block("spout/middle"), SPOUT_BOTTOM = block("spout/bottom"), @@ -115,6 +126,20 @@ public class AllPartialModels { EJECTOR_TOP = block("weighted_ejector/top"), + CHAIN_CONVEYOR_WHEEL = block("chain_conveyor/wheel"), CHAIN_CONVEYOR_GUARD = block("chain_conveyor/guard"), + CHAIN_CONVEYOR_SHAFT = block("chain_conveyor/shaft"), + + FROGPORT_BODY = block("package_frogport/body"), FROGPORT_HEAD = block("package_frogport/head"), + FROGPORT_HEAD_GOGGLES = block("package_frogport/head_goggles"), + FROGPORT_TONGUE = block("package_frogport/tongue"), + POSTBOX_FLAG = block("package_postbox/flag"), + + PACKAGER_TRAY_REGULAR = block("packager/tray"), PACKAGER_TRAY_DEFRAG = block("repackager/tray"), + PACKAGER_HATCH_OPEN = block("packager/hatch_open"), PACKAGER_HATCH_CLOSED = block("packager/hatch_closed"), + + TABLE_CLOTH_PRICE_SIDE = block("table_cloth/price_tag_side"), + TABLE_CLOTH_PRICE_TOP = block("table_cloth/price_tag_top"), + COPPER_BACKTANK_SHAFT = block("copper_backtank/block_shaft_input"), COPPER_BACKTANK_COGS = block("copper_backtank/block_cogs"), @@ -134,6 +159,7 @@ public class AllPartialModels { BOGEY_FRAME = block("track/bogey/bogey_frame"), SMALL_BOGEY_WHEELS = block("track/bogey/bogey_wheel"), BOGEY_PIN = block("track/bogey/bogey_drive_wheel_pin"), BOGEY_PISTON = block("track/bogey/bogey_drive_piston"), BOGEY_DRIVE = block("track/bogey/bogey_drive"), LARGE_BOGEY_WHEELS = block("track/bogey/bogey_drive_wheel"), + BOGEY_DRIVE_BELT = block("track/bogey/bogey_drive_belt"), TRAIN_COUPLING_HEAD = block("track/bogey/coupling_head"), TRAIN_COUPLING_CABLE = block("track/bogey/coupling_cable"), @@ -157,12 +183,12 @@ public class AllPartialModels { SIGNAL_RED = block("track_signal/red_tube"), SIGNAL_YELLOW_CUBE = block("track_signal/yellow_cube"), SIGNAL_YELLOW_GLOW = block("track_signal/yellow_glow"), SIGNAL_YELLOW = block("track_signal/yellow_tube"), + BLAZE_CAGE = block("blaze_burner/block"), BLAZE_INERT = block("blaze_burner/blaze/inert"), BLAZE_SUPER_ACTIVE = block("blaze_burner/blaze/super_active"), BLAZE_GOGGLES = block("blaze_burner/goggles"), BLAZE_GOGGLES_SMALL = block("blaze_burner/goggles_small"), BLAZE_IDLE = block("blaze_burner/blaze/idle"), BLAZE_ACTIVE = block("blaze_burner/blaze/active"), BLAZE_SUPER = block("blaze_burner/blaze/super"), BLAZE_BURNER_FLAME = block("blaze_burner/flame"), - BLAZE_BURNER_RODS = block("blaze_burner/rods_small"), - BLAZE_BURNER_RODS_2 = block("blaze_burner/rods_large"), + BLAZE_BURNER_RODS = block("blaze_burner/rods_small"), BLAZE_BURNER_RODS_2 = block("blaze_burner/rods_large"), BLAZE_BURNER_SUPER_RODS = block("blaze_burner/superheated_rods_small"), BLAZE_BURNER_SUPER_RODS_2 = block("blaze_burner/superheated_rods_large"), @@ -170,15 +196,35 @@ public class AllPartialModels { WHISTLE_MOUTH_MEDIUM = block("steam_whistle/medium_mouth"), WHISTLE_MOUTH_SMALL = block("steam_whistle/small_mouth"), - WATER_WHEEL = block("water_wheel/wheel"), - LARGE_WATER_WHEEL = block("large_water_wheel/block"), + WATER_WHEEL = block("water_wheel/wheel"), LARGE_WATER_WHEEL = block("large_water_wheel/block"), LARGE_WATER_WHEEL_EXTENSION = block("large_water_wheel/block_extension"), + FACTORY_PANEL = block("factory_gauge/panel"), + FACTORY_PANEL_WITH_BULB = block("factory_gauge/panel_with_bulb"), + FACTORY_PANEL_RESTOCKER = block("factory_gauge/panel_restocker"), + FACTORY_PANEL_RESTOCKER_WITH_BULB = block("factory_gauge/panel_restocker_with_bulb"), + FACTORY_PANEL_LIGHT = block("factory_gauge/bulb_light"), + FACTORY_PANEL_RED_LIGHT = block("factory_gauge/bulb_red"), + + TABLE_CLOTH_NW = block("table_cloth/north_west"), + TABLE_CLOTH_NE = block("table_cloth/north_east"), + TABLE_CLOTH_SW = block("table_cloth/south_west"), + TABLE_CLOTH_SE = block("table_cloth/south_east"), + + FLYWHEEL = block("flywheel/block"), + CRUSHING_WHEEL = block("crushing_wheel/block"), + TURNTABLE = block("turntable"), + GANTRY_SHAFT_START = block("gantry_shaft/block_start"), + GANTRY_SHAFT_END = block("gantry_shaft/block_end"), + GANTRY_SHAFT_MIDDLE = block("gantry_shaft/block_middle"), + GANTRY_SHAFT_SINGLE = block("gantry_shaft/block_single"), + POWERED_SHAFT = block("powered_shaft"), + CRAFTING_BLUEPRINT_1x1 = entity("crafting_blueprint_small"), CRAFTING_BLUEPRINT_2x2 = entity("crafting_blueprint_medium"), CRAFTING_BLUEPRINT_3x3 = entity("crafting_blueprint_large"), - TRAIN_HAT = entity("train_hat"), + TRAIN_HAT = entity("train_hat"), LOGISTICS_HAT = entity("logistics_hat"), COUPLING_ATTACHMENT = entity("minecart_coupling/attachment"), COUPLING_RING = entity("minecart_coupling/ring"), COUPLING_CONNECTOR = entity("minecart_coupling/connector") @@ -188,13 +234,25 @@ public class AllPartialModels { public static final Map> PIPE_ATTACHMENTS = new EnumMap<>(FluidTransportBehaviour.AttachmentTypes.ComponentPartials.class); + public static final Map FACTORY_PANEL_ARROWS = new EnumMap<>(Direction.class); + public static final Map FACTORY_PANEL_LINES = new EnumMap<>(Direction.class); + public static final Map FACTORY_PANEL_DOTTED = new EnumMap<>(Direction.class); + public static final Map METAL_GIRDER_BRACKETS = new EnumMap<>(Direction.class); public static final Map TOOLBOX_LIDS = new EnumMap<>(DyeColor.class); + public static final Map DYED_VALVE_HANDLES = new EnumMap<>(DyeColor.class); public static final Map> FOLDING_DOORS = new HashMap<>(); public static final List CONTRAPTION_CONTROLS_INDICATOR = new ArrayList<>(); + public static final Map PACKAGES = new HashMap<>(); + public static final List PACKAGES_TO_HIDE_AS = new ArrayList<>(); + public static final Map PACKAGE_RIGGING = new HashMap<>(); + + public static final Map GANTRY_SHAFTS = new HashMap<>(); + static { - for (FluidTransportBehaviour.AttachmentTypes.ComponentPartials type : FluidTransportBehaviour.AttachmentTypes.ComponentPartials.values()) { + for (FluidTransportBehaviour.AttachmentTypes.ComponentPartials type : FluidTransportBehaviour.AttachmentTypes.ComponentPartials + .values()) { Map map = new HashMap<>(); for (Direction d : Iterate.directions) { String asId = Lang.asId(type.name()); @@ -202,15 +260,55 @@ public class AllPartialModels { } PIPE_ATTACHMENTS.put(type, map); } - for (DyeColor color : DyeColor.values()) + for (DyeColor color : DyeColor.values()) { TOOLBOX_LIDS.put(color, block("toolbox/lid/" + Lang.asId(color.name()))); - for (Direction d : Iterate.horizontalDirections) + DYED_VALVE_HANDLES.put(color, block(Lang.asId(color.name()) + "_valve_handle")); + } + for (Direction d : Iterate.horizontalDirections) { METAL_GIRDER_BRACKETS.put(d, block("metal_girder/bracket_" + Lang.asId(d.name()))); + FACTORY_PANEL_ARROWS.put(d, block("factory_gauge/connections/arrow_" + Lang.asId(d.name()))); + FACTORY_PANEL_LINES.put(d, block("factory_gauge/connections/line_" + Lang.asId(d.name()))); + FACTORY_PANEL_DOTTED.put(d, block("factory_gauge/connections/dotted_" + Lang.asId(d.name()))); + } for (int i = 0; i < 8; i++) CONTRAPTION_CONTROLS_INDICATOR.add(block("contraption_controls/indicator_" + i)); putFoldingDoor("andesite_door"); putFoldingDoor("copper_door"); + + for (PackageStyle style : PackageStyles.STYLES) { + ResourceLocation key = style.getItemId(); + PartialModel model = PartialModel.of(Create.asResource("item/" + key.getPath())); + PACKAGES.put(key, model); + if (!style.rare()) + PACKAGES_TO_HIDE_AS.add(model); + PACKAGE_RIGGING.put(key, PartialModel.of(style.getRiggingModel())); + } + + for (boolean flipped : Iterate.trueAndFalse) { + for (boolean powered : Iterate.trueAndFalse) { + for (GantryShaftBlock.Part part : GantryShaftBlock.Part.values()) { + GantryShaftKey key = new GantryShaftKey(part, powered, flipped); + GANTRY_SHAFTS.put(key, PartialModel.of(key.name())); + } + } + } + } + + public record GantryShaftKey(GantryShaftBlock.Part part, boolean powered, boolean flipped) { + private ResourceLocation name() { + String partName = part.getSerializedName(); + + if (!(flipped || powered)) { + // Non-generated + return Create.asResource("block/gantry_shaft/block_" + partName); + } + + String flipped = this.flipped ? "_flipped" : ""; + String powered = this.powered ? "_powered" : ""; + + return Create.asResource("block/gantry_shaft_" + partName + powered + flipped); + } } private static void putFoldingDoor(String path) { diff --git a/src/main/java/com/simibubi/create/AllParticleTypes.java b/src/main/java/com/simibubi/create/AllParticleTypes.java index 31759c4a3b..62a346e7f5 100644 --- a/src/main/java/com/simibubi/create/AllParticleTypes.java +++ b/src/main/java/com/simibubi/create/AllParticleTypes.java @@ -8,11 +8,12 @@ import com.simibubi.create.content.fluids.particle.FluidParticleData; import com.simibubi.create.content.kinetics.base.RotationIndicatorParticleData; import com.simibubi.create.content.kinetics.fan.AirFlowParticleData; import com.simibubi.create.content.kinetics.steamEngine.SteamJetParticleData; +import com.simibubi.create.content.logistics.packagerLink.WiFiParticle; import com.simibubi.create.content.trains.CubeParticleData; import com.simibubi.create.foundation.particle.AirParticleData; import com.simibubi.create.foundation.particle.ICustomParticleData; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraftforge.api.distmarker.Dist; @@ -33,6 +34,7 @@ public enum AllParticleTypes { FLUID_PARTICLE(FluidParticleData::new), BASIN_FLUID(FluidParticleData::new), FLUID_DRIP(FluidParticleData::new), + WIFI(WiFiParticle.Data::new), SOUL(SoulParticle.Data::new), SOUL_BASE(SoulBaseParticle.Data::new), SOUL_PERIMETER(SoulParticle.PerimeterData::new), diff --git a/src/main/java/com/simibubi/create/AllRecipeTypes.java b/src/main/java/com/simibubi/create/AllRecipeTypes.java index 8967a9e392..e8540ed470 100644 --- a/src/main/java/com/simibubi/create/AllRecipeTypes.java +++ b/src/main/java/com/simibubi/create/AllRecipeTypes.java @@ -27,8 +27,9 @@ import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.Pro import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer; import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipeSerializer; import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.recipe.ItemCopyingRecipe; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Container; @@ -64,7 +65,8 @@ public enum AllRecipeTypes implements IRecipeTypeInfo { MECHANICAL_CRAFTING(MechanicalCraftingRecipe.Serializer::new), SEQUENCED_ASSEMBLY(SequencedAssemblyRecipeSerializer::new), - TOOLBOX_DYEING(() -> new SimpleCraftingRecipeSerializer<>(ToolboxDyeingRecipe::new), () -> RecipeType.CRAFTING, false); + TOOLBOX_DYEING(() -> new SimpleCraftingRecipeSerializer<>(ToolboxDyeingRecipe::new), () -> RecipeType.CRAFTING, false), + ITEM_COPYING(() -> new SimpleCraftingRecipeSerializer<>(ItemCopyingRecipe::new), () -> RecipeType.CRAFTING, false); public static final Predicate> CAN_BE_AUTOMATED = r -> !r.getId() .getPath() @@ -128,7 +130,7 @@ public enum AllRecipeTypes implements IRecipeTypeInfo { return world.getRecipeManager() .getRecipeFor(getType(), inv, world); } - + public static boolean shouldIgnoreInAutomation(Recipe recipe) { RecipeSerializer serializer = recipe.getSerializer(); if (serializer != null && AllTags.AllRecipeSerializerTags.AUTOMATION_IGNORE.matches(serializer)) diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 8f3e065683..fe4c9c48d3 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -9,8 +9,8 @@ import java.util.function.BiFunction; import com.simibubi.create.content.logistics.chute.ChuteShapes; import com.simibubi.create.content.trains.track.TrackVoxelShapes; -import com.simibubi.create.foundation.utility.VoxelShaper; +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.world.level.block.Block; @@ -39,10 +39,6 @@ public class AllShapes { FURNACE_ENGINE = shape(1, 1, 0, 15, 15, 16).add(0, 0, 9, 16, 16, 14) .forHorizontal(SOUTH), PORTABLE_STORAGE_INTERFACE = shape(0, 0, 0, 16, 14, 16).forDirectional(), - PULLEY = shape(0, 0, 0, 16, 16, 2).add(1, 1, 2, 15, 15, 14) - .add(2, 13, 2, 14, 16, 14) - .add(0, 0, 14, 16, 16, 16) - .forHorizontalAxis(), ELEVATOR_PULLEY = shape(0, 0, 0, 16, 16, 2).add(0, 0, 14, 16, 16, 16) .add(2, 0, 2, 14, 14, 14) .forHorizontal(EAST), @@ -111,9 +107,7 @@ public class AllShapes { .add(5, 0, 5, 11, 1, 9) .add(5, -1, 6, 11, 0, 8) .forHorizontal(SOUTH), - PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12) - .add(3, 11, 3, 13, 16, 13) - .forDirectional(Direction.UP), + PUMP = shape(2, 0, 2, 14, 16, 14).forDirectional(Direction.UP), CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16).forDirectional(Direction.DOWN), BELL_FLOOR = shape(0, 0, 5, 16, 11, 11).add(3, 1, 3, 13, 13, 13) @@ -132,10 +126,18 @@ public class AllShapes { STEP_BOTTOM = shape(0, 0, 8, 16, 8, 16).forHorizontal(SOUTH), STEP_TOP = shape(0, 8, 8, 16, 16, 16).forHorizontal(SOUTH), - CONTROLS = shape(0, 0, 6, 16, 14, 16).forHorizontal(NORTH), - CONTRAPTION_CONTROLS = shape(0, 0, 6, 2, 14, 16).add(14, 0, 6, 16, 14, 16) - .add(0, 0, 14, 16, 14, 16) - .add(0, 0, 7, 16, 10, 16) + CONTROLS = shape(0, 0, 6, 16, 16, 16).add(0, 0, 4, 16, 2, 16) + .forHorizontal(NORTH), + CONTROLS_COLLISION = shape(0, 0, 6, 16, 16, 16).forHorizontal(NORTH), + + CONTRAPTION_CONTROLS = shape(0, 0, 6, 2, 16, 16).add(14, 0, 6, 16, 16, 16) + .add(0, 0, 14, 16, 16, 16) + .add(0, 0, 6, 16, 12, 16) + .add(0, 0, 4, 16, 2, 16) + .forHorizontal(NORTH), + CONTRAPTION_CONTROLS_COLLISION = shape(0, 0, 6, 2, 16, 16).add(14, 0, 6, 16, 16, 16) + .add(0, 0, 14, 16, 16, 16) + .add(0, 0, 7, 16, 12, 16) .forHorizontal(NORTH), NIXIE_TUBE = shape(9, 0, 5, 15, 12, 11).add(1, 0, 5, 7, 12, 11) @@ -149,6 +151,7 @@ public class AllShapes { DATA_GATHERER = shape(1, 0, 1, 15, 6, 15).add(3, 5, 3, 13, 9, 13) .forDirectional(), + STOCK_LINK = shape(1, 0, 1, 15, 5, 15).forDirectional(), STEAM_ENGINE = shape(1, 0, 1, 15, 3, 15).add(3, 0, 3, 13, 15, 13) .add(1, 5, 4, 15, 13, 12) @@ -161,7 +164,8 @@ public class AllShapes { .forHorizontal(SOUTH), PLACARD = shape(2, 0, 2, 14, 3, 14).forDirectional(UP), - + FACTORY_PANEL_FALLBACK = shape(0, 0, 0, 16, 2, 16).forDirectional(UP), + CLIPBOARD_FLOOR = shape(3, 0, 1, 13, 1, 15).forHorizontal(SOUTH), CLIPBOARD_CEILING = shape(3, 15, 1, 13, 16, 15).forHorizontal(SOUTH), CLIPBOARD_WALL = shape(3, 1, 0, 13, 15, 1).forHorizontal(SOUTH), @@ -175,7 +179,17 @@ public class AllShapes { .forDirectional(UP), WHISTLE_BASE = shape(1, 0, 1, 15, 3, 15).add(5, 0, 5, 11, 8, 11) - .forDirectional(UP) + .forDirectional(UP), + + DESK_BELL = shape(3, 0, 3, 13, 3, 13).add(4, 0, 4, 12, 9, 12) + .forDirectional(UP), + + ITEM_HATCH = shape(1, 0, 0, 15, 16, 2).add(2, 2, 0, 14, 13, 3.8) + .add(2, 4, 0, 14, 11, 5.8) + .add(2, 6, 0, 14, 9, 7.8) + .forHorizontal(SOUTH), + + POSTBOX = shape(2, 0, 0, 14, 14, 16).forHorizontal(SOUTH); ; @@ -217,6 +231,17 @@ public class AllShapes { TRACK_COLLISION = shape(0, 0, 0, 16, 2, 16).build(), + PACKAGE_PORT = shape(0, 0, 0, 16, 4, 16).add(2, 2, 2, 14, 14, 14) + .build(), + + TABLE_CLOTH = shape(-1, -9, -1, 17, 1, 17).build(), + TABLE_CLOTH_OCCLUSION = shape(0, 0, 0, 16, 1, 16).build(), + + CHAIN_CONVEYOR_INTERACTION = shape(-10, 2, 0, 26, 14, 16).add(0, 2, -10, 16, 14, 26) + .add(-5, 2, -5, 21, 14, 21) + .add(Shapes.block()) + .build(), + TRACK_FALLBACK = shape(0, 0, 0, 16, 4, 16).build(), BASIN_BLOCK_SHAPE = shape(0, 2, 0, 16, 16, 16).erase(2, 2, 2, 14, 16, 14) @@ -249,7 +274,7 @@ public class AllShapes { BELT_COLLISION_MASK = cuboid(0, 0, 0, 16, 19, 16), SCHEMATICANNON_SHAPE = shape(1, 0, 1, 15, 8, 15).add(0.5, 8, 0.5, 15.5, 11, 15.5) .build(), - PULLEY_MAGNET = shape(3, 0, 3, 13, 3, 13).add(FOUR_VOXEL_POLE.get(UP)) + PULLEY_MAGNET = shape(3, -3, 3, 13, 2, 13).add(FOUR_VOXEL_POLE.get(UP)) .build(), SPOUT = shape(1, 2, 1, 15, 14, 15).add(2, 0, 2, 14, 16, 14) .build(), @@ -281,6 +306,8 @@ public class AllShapes { .build(), STATION = shape(0, 0, 0, 16, 2, 16).add(1, 0, 1, 15, 13, 15) .build(), + STOCK_TICKER = shape(1, 0, 1, 15, 4, 15).add(2, 0, 2, 14, 16, 14) + .build(), WHISTLE_SMALL_FLOOR = shape(WHISTLE_SMALL).add(WHISTLE_BASE.get(UP)) .build(), diff --git a/src/main/java/com/simibubi/create/AllSoundEvents.java b/src/main/java/com/simibubi/create/AllSoundEvents.java index f5eef6505b..ec9daeb21c 100644 --- a/src/main/java/com/simibubi/create/AllSoundEvents.java +++ b/src/main/java/com/simibubi/create/AllSoundEvents.java @@ -63,6 +63,11 @@ public class AllSoundEvents { .playExisting(SoundEvents.WOOL_BREAK, .0425f, .75f) .category(SoundSource.BLOCKS) .build(), + + PACKAGER = create("packager").subtitle("Packager packages") + .playExisting(SoundEvents.SHULKER_OPEN, 0.5f, 0.75f) + .category(SoundSource.BLOCKS) + .build(), SLIME_ADDED = create("slime_added").subtitle("Slime squishes") .playExisting(SoundEvents.SLIME_BLOCK_PLACE) @@ -116,6 +121,10 @@ public class AllSoundEvents { .category(SoundSource.PLAYERS) .build(), + CONFIRM_2 = create("confirm_2").subtitle("Affirmative ding") + .category(SoundSource.PLAYERS) + .build(), + DENY = create("deny").subtitle("Declining boop") .playExisting(SoundEvents.NOTE_BLOCK_BASS, 1f, 0.5f) .category(SoundSource.PLAYERS) @@ -125,10 +134,39 @@ public class AllSoundEvents { .category(SoundSource.BLOCKS) .build(), - FWOOMP = create("fwoomp").subtitle("Potato Launcher fwoomps") + FWOOMP = create("fwoomp").subtitle("Resonant fwoomp") .category(SoundSource.PLAYERS) .build(), + CARDBOARD_SWORD = create("cardboard_bonk").subtitle("Resonant bonk") + .category(SoundSource.PLAYERS) + .build(), + + FROGPORT_OPEN = create("frogport_open").subtitle("Frogport opens") + .playExisting(SoundEvents.WARDEN_TENDRIL_CLICKS, 1f, 2f) + .category(SoundSource.BLOCKS) + .build(), + + FROGPORT_CLOSE = create("frogport_close").subtitle("Frogport shuts") + .category(SoundSource.BLOCKS) + .build(), + + FROGPORT_CATCH = create("frogport_catch").subtitle("Frogport catches package") + .addVariant("frogport_catch_1") + .addVariant("frogport_catch_2") + .addVariant("frogport_catch_3") + .category(SoundSource.BLOCKS) + .build(), + + STOCK_LINK = create("stock_link").subtitle("Stock link reacts") + .category(SoundSource.BLOCKS) + .build(), + + FROGPORT_DEPOSIT = create("frogport_deposit").subtitle("Frogport places package") + .playExisting(SoundEvents.FROG_TONGUE, 1f, 1f) + .category(SoundSource.BLOCKS) + .build(), + POTATO_HIT = create("potato_hit").subtitle("Vegetable impacts") .playExisting(SoundEvents.ITEM_FRAME_BREAK, .75f, .75f) .playExisting(SoundEvents.WEEPING_VINES_BREAK, .75f, 1.25f) @@ -156,6 +194,12 @@ public class AllSoundEvents { .playExisting(SoundEvents.NETHERITE_BLOCK_HIT, .25f, .75f) .category(SoundSource.BLOCKS) .build(), + + PACKAGE_POP = create("package_pop").subtitle("Package breaks") + .playExisting(SoundEvents.CHISELED_BOOKSHELF_BREAK, .75f, 1f) + .playExisting(SoundEvents.WOOL_BREAK, .25f, 1.15f) + .category(SoundSource.BLOCKS) + .build(), CRAFTER_CLICK = create("crafter_click").subtitle("Crafter clicks") .playExisting(SoundEvents.NETHERITE_BLOCK_HIT, .25f, 1) @@ -211,6 +255,12 @@ public class AllSoundEvents { .playExisting(SoundEvents.GENERIC_EAT, .5f, 1f) .category(SoundSource.BLOCKS) .build(), + + ITEM_HATCH = create("item_hatch").subtitle("Item Hatch opens") + .playExisting(SoundEvents.BARREL_OPEN, .25f, 1.4f) + .playExisting(SoundEvents.NETHERITE_BLOCK_PLACE, .75f, 1.15f) + .category(SoundSource.BLOCKS) + .build(), CRUSHING_1 = create("crushing_1").subtitle("Crushing noises") .playExisting(SoundEvents.NETHERRACK_HIT) @@ -231,6 +281,11 @@ public class AllSoundEvents { .playExisting(SoundEvents.BELL_BLOCK) .category(SoundSource.BLOCKS) .build(), + + DESK_BELL_USE = create("desk_bell").subtitle("Reception bell dings") + .category(SoundSource.BLOCKS) + .attenuationDistance(64) + .build(), WHISTLE_HIGH = create("whistle_high").subtitle("High whistling") .category(SoundSource.RECORDS) @@ -305,7 +360,15 @@ public class AllSoundEvents { HAUNTED_BELL_USE = create("haunted_bell_use").subtitle("Haunted Bell tolls") .category(SoundSource.BLOCKS) - .build(), + .build(), + + STOCK_TICKER_REQUEST = create("stock_ticker_request").subtitle("Stock ticker requests") + .category(SoundSource.BLOCKS) + .build(), + + STOCK_TICKER_TRADE = create("stock_ticker_trade").subtitle("Stock ticker goes 'ka-ching!'") + .category(SoundSource.BLOCKS) + .build(), CLIPBOARD_CHECKMARK = create("clipboard_check").noSubtitle() .category(SoundSource.BLOCKS) @@ -346,8 +409,9 @@ public class AllSoundEvents { } public static void playItemPickup(Player player) { - player.level().playSound(null, player.blockPosition(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f, - 1f + Create.RANDOM.nextFloat()); + player.level() + .playSound(null, player.blockPosition(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f, + 1f + player.level().random.nextFloat()); } // @SubscribeEvent @@ -360,7 +424,7 @@ public class AllSoundEvents { // // } - private static class SoundEntryProvider implements DataProvider { + public static class SoundEntryProvider implements DataProvider { private PackOutput output; @@ -452,7 +516,7 @@ public class AllSoundEvents { public SoundEntryBuilder playExisting(SoundEvent event) { return playExisting(event, 1, 1); } - + public SoundEntryBuilder playExisting(Holder event) { return playExisting(event::get, 1, 1); } diff --git a/src/main/java/com/simibubi/create/AllSpecialTextures.java b/src/main/java/com/simibubi/create/AllSpecialTextures.java index f697d04d6a..03a1424053 100644 --- a/src/main/java/com/simibubi/create/AllSpecialTextures.java +++ b/src/main/java/com/simibubi/create/AllSpecialTextures.java @@ -1,12 +1,10 @@ package com.simibubi.create; -import com.mojang.blaze3d.systems.RenderSystem; - +import net.createmod.catnip.render.BindableTexture; import net.minecraft.resources.ResourceLocation; -public enum AllSpecialTextures { +public enum AllSpecialTextures implements BindableTexture { - BLANK("blank.png"), CHECKERED("checkerboard.png"), THIN_CHECKERED("thin_checkerboard.png"), CUTOUT_CHECKERED("cutout_checkerboard.png"), @@ -17,18 +15,14 @@ public enum AllSpecialTextures { ; public static final String ASSET_PATH = "textures/special/"; - private ResourceLocation location; + private final ResourceLocation location; - private AllSpecialTextures(String filename) { + AllSpecialTextures(String filename) { location = Create.asResource(ASSET_PATH + filename); } - public void bind() { - RenderSystem.setShaderTexture(0, location); - } - public ResourceLocation getLocation() { return location; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/AllSpriteShifts.java b/src/main/java/com/simibubi/create/AllSpriteShifts.java index f79047f465..b319e12559 100644 --- a/src/main/java/com/simibubi/create/AllSpriteShifts.java +++ b/src/main/java/com/simibubi/create/AllSpriteShifts.java @@ -9,16 +9,20 @@ import com.simibubi.create.foundation.block.connected.AllCTTypes; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.block.connected.CTSpriteShifter; import com.simibubi.create.foundation.block.connected.CTType; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.block.render.SpriteShifter; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.render.SpriteShifter; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.lang.Lang; import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.WeatheringCopper.WeatherState; import net.minecraft.world.level.block.state.properties.WoodType; public class AllSpriteShifts { private static final Map WOODEN_WINDOWS = new IdentityHashMap<>(); + public static final Map COPPER_SHINGLES = new EnumMap<>(WeatherState.class); + public static final Map COPPER_TILES = new EnumMap<>(WeatherState.class); public static final Map DYED_BELTS = new EnumMap<>(DyeColor.class), DYED_OFFSET_BELTS = new EnumMap<>(DyeColor.class), DYED_DIAGONAL_BELTS = new EnumMap<>(DyeColor.class); @@ -40,7 +44,13 @@ public class AllSpriteShifts { HORIZONTAL_FRAMED_GLASS = getCT(AllCTTypes.HORIZONTAL_KRYPPERS, "palettes/framed_glass", "palettes/horizontal_framed_glass"), VERTICAL_FRAMED_GLASS = getCT(AllCTTypes.VERTICAL, "palettes/framed_glass", "palettes/vertical_framed_glass"), - ORNATE_IRON_WINDOW = vertical("palettes/ornate_iron_window"); + ORNATE_IRON_WINDOW = vertical("palettes/ornate_iron_window"), + INDUSTRIAL_IRON_WINDOW = getCT(AllCTTypes.RECTANGLE, "palettes/industrial_iron_window"), + + OLD_FACTORY_WINDOW_1 = getCT(AllCTTypes.RECTANGLE, "palettes/weathered_iron_window", "palettes/weathered_iron_window_1"), + OLD_FACTORY_WINDOW_2 = getCT(AllCTTypes.RECTANGLE, "palettes/weathered_iron_window", "palettes/weathered_iron_window_2"), + OLD_FACTORY_WINDOW_3 = getCT(AllCTTypes.RECTANGLE, "palettes/weathered_iron_window", "palettes/weathered_iron_window_3"), + OLD_FACTORY_WINDOW_4 = getCT(AllCTTypes.RECTANGLE, "palettes/weathered_iron_window", "palettes/weathered_iron_window_4"); public static final CTSpriteShiftEntry CRAFTER_SIDE = vertical("crafter_side"), CRAFTER_OTHERSIDE = horizontal("crafter_side"), @@ -71,7 +81,12 @@ public class AllSpriteShifts { public static final SpriteShiftEntry ELEVATOR_BELT = get("block/elevator_pulley_belt", "block/elevator_pulley_belt_scroll"), - ELEVATOR_COIL = get("block/elevator_pulley_coil", "block/elevator_pulley_coil_scroll"); + ROPE_PULLEY_COIL = get("block/rope_pulley_coil", "block/rope_pulley_coil_scroll"), + ELEVATOR_COIL = get("block/elevator_pulley_coil", "block/elevator_pulley_coil_scroll"), + HOSE_PULLEY_COIL = get("block/hose_pulley_coil", "block/hose_pulley_coil_scroll"); + + public static final SpriteShiftEntry FACTORY_PANEL_CONNECTIONS = + get("block/factory_panel_connections", "block/factory_panel_connections_animated"); public static final SpriteShiftEntry BELT = get("block/belt", "block/belt_scroll"), BELT_OFFSET = get("block/belt_offset", "block/belt_scroll"), @@ -79,13 +94,16 @@ public class AllSpriteShifts { ANDESIDE_BELT_CASING = get("block/belt/brass_belt_casing", "block/belt/andesite_belt_casing"), CRAFTER_THINGIES = get("block/crafter_thingies", "block/crafter_thingies"); + public static final SpriteShiftEntry BOGEY_BELT = get("block/bogey/belt", "block/bogey/belt_scroll"); + static { populateMaps(); } private static void populateMaps() { WoodType[] supportedWoodTypes = new WoodType[] { WoodType.OAK, WoodType.SPRUCE, WoodType.BIRCH, WoodType.ACACIA, - WoodType.JUNGLE, WoodType.DARK_OAK, WoodType.MANGROVE, WoodType.CRIMSON, WoodType.WARPED }; + WoodType.JUNGLE, WoodType.DARK_OAK, WoodType.MANGROVE, WoodType.CRIMSON, WoodType.WARPED, WoodType.CHERRY, + WoodType.BAMBOO }; Arrays.stream(supportedWoodTypes) .forEach(woodType -> WOODEN_WINDOWS.put(woodType, vertical("palettes/" + woodType.name() + "_window"))); @@ -95,6 +113,12 @@ public class AllSpriteShifts { DYED_OFFSET_BELTS.put(color, get("block/belt_offset", "block/belt/" + id + "_scroll")); DYED_DIAGONAL_BELTS.put(color, get("block/belt_diagonal", "block/belt/" + id + "_diagonal_scroll")); } + + for (WeatherState state : WeatherState.values()) { + String pref = "copper/" + (state == WeatherState.UNAFFECTED ? "" : Lang.asId(state.name()) + "_"); + COPPER_SHINGLES.put(state, getCT(AllCTTypes.ROOF, pref + "copper_roof_top", pref + "copper_shingles_top")); + COPPER_TILES.put(state, getCT(AllCTTypes.ROOF, pref + "copper_roof_top", pref + "copper_tiles_top")); + } } private static Couple vault(String name) { diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index 49a98d5572..065f9067d0 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -8,8 +8,12 @@ import static com.simibubi.create.AllTags.NameSpace.TIC; import java.util.Collections; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.api.contraption.ContraptionType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.registry.CreateRegistries; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; @@ -26,12 +30,13 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; + import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.IForgeRegistry; public class AllTags { public static TagKey optionalTag(IForgeRegistry registry, - ResourceLocation id) { + ResourceLocation id) { return registry.tags() .createOptionalTagKey(id, Collections.emptySet()); } @@ -59,9 +64,7 @@ public class AllTags { TIC("tconstruct"), QUARK("quark"), GS("galosphere"), - CURIOS("curios") - - ; + CURIOS("curios"); public final String id; public final boolean optionalDefault; @@ -82,7 +85,6 @@ public class AllTags { BRITTLE, CASING, - CONTRAPTION_INVENTORY_DENY, COPYCAT_ALLOW, COPYCAT_DENY, FAN_PROCESSING_CATALYSTS_BLASTING(MOD, "fan_processing_catalysts/blasting"), @@ -93,18 +95,25 @@ public class AllTags { GIRDABLE_TRACKS, MOVABLE_EMPTY_COLLIDER, NON_MOVABLE, + NON_BREAKABLE, ORE_OVERRIDE_STONE, PASSIVE_BOILER_HEATERS, SAFE_NBT, SEATS, + POSTBOXES, + TABLE_CLOTHS, TOOLBOXES, TRACKS, TREE_ATTACHMENTS, VALVE_HANDLES, WINDMILL_SAILS, WRENCH_PICKUP, + CHEST_MOUNTED_STORAGE, + SIMPLE_MOUNTED_STORAGE, + FALLBACK_MOUNTED_STORAGE_BLACKLIST, ROOTS, SUGAR_CANE_VARIANTS, + NON_HARVESTABLE, CORALS, @@ -159,7 +168,8 @@ public class AllTags { return state.is(tag); } - private static void init() {} + private static void init() { + } } @@ -171,34 +181,40 @@ public class AllTags { CONTRAPTION_CONTROLLED, CREATE_INGOTS, CRUSHED_RAW_MATERIALS, + INVALID_FOR_TRACK_PAVING, DEPLOYABLE_DRINK, MODDED_STRIPPED_LOGS, MODDED_STRIPPED_WOOD, PRESSURIZED_AIR_SOURCES, SANDPAPER, SEATS, + POSTBOXES, + TABLE_CLOTHS, + DYED_TABLE_CLOTHS, + PULPIFIABLE, SLEEPERS, TOOLBOXES, + PACKAGES, + CHAIN_RIDEABLE, TRACKS, UPRIGHT_ON_BELT, VALVE_HANDLES, VANILLA_STRIPPED_LOGS, VANILLA_STRIPPED_WOOD, + DISPENSE_BEHAVIOR_WRAP_BLACKLIST, STRIPPED_LOGS(FORGE), STRIPPED_WOOD(FORGE), PLATES(FORGE), - OBSIDIAN_DUST(FORGE,"dusts/obsidian"), + OBSIDIAN_DUST(FORGE, "dusts/obsidian"), WRENCH(FORGE, "tools/wrench"), - ALLURITE(MOD,"stone_types/galosphere/allurite"), - AMETHYST(MOD,"stone_types/galosphere/amethyst"), + ALLURITE(MOD, "stone_types/galosphere/allurite"), + AMETHYST(MOD, "stone_types/galosphere/amethyst"), LUMIERE(MOD, "stone_types/galosphere/lumiere"), UA_CORAL(MOD, "upgrade_aquatic/coral"), - CURIOS_HEAD(CURIOS, "head") - - ; + CURIOS_HEAD(CURIOS, "head"); public final TagKey tag; public final boolean alwaysDatagen; @@ -239,7 +255,8 @@ public class AllTags { return stack.is(tag); } - private static void init() {} + private static void init() { + } } @@ -252,9 +269,7 @@ public class AllTags { FAN_PROCESSING_CATALYSTS_SMOKING(MOD, "fan_processing_catalysts/smoking"), FAN_PROCESSING_CATALYSTS_SPLASHING(MOD, "fan_processing_catalysts/splashing"), - HONEY(FORGE) - - ; + HONEY(FORGE); public final TagKey tag; public final boolean alwaysDatagen; @@ -294,7 +309,8 @@ public class AllTags { return state.is(tag); } - private static void init() {} + private static void init() { + } } @@ -342,7 +358,8 @@ public class AllTags { return matches(entity.getType()); } - private static void init() {} + private static void init() { + } } @@ -385,7 +402,54 @@ public class AllTags { return ForgeRegistries.RECIPE_SERIALIZERS.getHolder(recipeSerializer).orElseThrow().is(tag); } - private static void init() {} + private static void init() { + } + } + + public enum AllContraptionTypeTags { + OPENS_CONTROLS, + REQUIRES_VEHICLE_FOR_RENDER; + + public final TagKey tag; + public final boolean alwaysDatagen; + + AllContraptionTypeTags() { + ResourceLocation tagId = Create.asResource(Lang.asId(this.name())); + this.tag = TagKey.create(CreateRegistries.CONTRAPTION_TYPE, tagId); + this.alwaysDatagen = true; + } + + public boolean matches(ContraptionType type) { + return type.is(this.tag); + } + + private static void init() { + } + } + + public enum AllMountedItemStorageTypeTags { + INTERNAL, + FUEL_BLACKLIST; + + public final TagKey> tag; + public final boolean alwaysDatagen; + + AllMountedItemStorageTypeTags() { + ResourceLocation tagId = Create.asResource(Lang.asId(this.name())); + this.tag = TagKey.create(CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE, tagId); + this.alwaysDatagen = true; + } + + public boolean matches(MountedItemStorage storage) { + return this.matches(storage.type); + } + + public boolean matches(MountedItemStorageType type) { + return type.is(this.tag); + } + + private static void init() { + } } public static void init() { @@ -394,5 +458,7 @@ public class AllTags { AllFluidTags.init(); AllEntityTags.init(); AllRecipeSerializerTags.init(); + AllContraptionTypeTags.init(); + AllMountedItemStorageTypeTags.init(); } } diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 2ef1094a85..c34e4ce306 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -7,43 +7,47 @@ import org.slf4j.Logger; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.mojang.logging.LogUtils; -import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; +import com.simibubi.create.api.behaviour.spouting.BlockSpoutingBehaviour; import com.simibubi.create.compat.Mods; import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.compat.curios.Curios; -import com.simibubi.create.content.contraptions.ContraptionMovementSetting; import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; -import com.simibubi.create.content.equipment.potatoCannon.BuiltinPotatoProjectileTypes; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileBlockHitActions; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileEntityHitActions; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileRenderModes; import com.simibubi.create.content.fluids.tank.BoilerHeaters; import com.simibubi.create.content.kinetics.TorquePropagator; import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes; import com.simibubi.create.content.kinetics.mechanicalArm.AllArmInteractionPointTypes; -import com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours; +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.packagerLink.GlobalLogisticsManager; import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler; import com.simibubi.create.content.schematics.ServerSchematicLoader; import com.simibubi.create.content.trains.GlobalRailwayManager; import com.simibubi.create.content.trains.bogey.BogeySizes; import com.simibubi.create.content.trains.track.AllPortalTracks; +import com.simibubi.create.foundation.CreateNBTProcessors; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.block.CopperRegistries; import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.KineticStats; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.item.TooltipModifier; -import com.simibubi.create.foundation.utility.AttachedRegistry; import com.simibubi.create.infrastructure.command.ServerLagger; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.data.CreateDatagen; import com.simibubi.create.infrastructure.worldgen.AllFeatures; import com.simibubi.create.infrastructure.worldgen.AllPlacementModifiers; +import net.createmod.catnip.lang.FontHelper; +import net.createmod.catnip.lang.LangBuilder; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.level.Level; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.MinecraftForge; @@ -54,13 +58,12 @@ import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.RegisterEvent; @Mod(Create.ID) public class Create { - public static final String ID = "create"; public static final String NAME = "Create"; - public static final String VERSION = "0.5.2-experimental"; public static final Logger LOGGER = LogUtils.getLogger(); @@ -68,7 +71,9 @@ public class Create { .disableHtmlEscaping() .create(); - /** Use the {@link Random} of a local {@link Level} or {@link Entity} or create one */ + /** + * Use the {@link Random} of a local {@link Level} or {@link Entity} or create one + */ @Deprecated public static final Random RANDOM = new Random(); @@ -80,16 +85,17 @@ public class Create { .defaultCreativeTab((ResourceKey) null); static { - REGISTRATE.setTooltipModifierFactory(item -> { - return new ItemDescription.Modifier(item, Palette.STANDARD_CREATE) - .andThen(TooltipModifier.mapNull(KineticStats.create(item))); - }); + REGISTRATE.setTooltipModifierFactory(item -> + new ItemDescription.Modifier(item, FontHelper.Palette.STANDARD_CREATE) + .andThen(TooltipModifier.mapNull(KineticStats.create(item))) + ); } public static final ServerSchematicLoader SCHEMATIC_RECEIVER = new ServerSchematicLoader(); public static final RedstoneLinkNetworkHandler REDSTONE_LINK_NETWORK_HANDLER = new RedstoneLinkNetworkHandler(); public static final TorquePropagator TORQUE_PROPAGATOR = new TorquePropagator(); public static final GlobalRailwayManager RAILWAYS = new GlobalRailwayManager(); + public static final GlobalLogisticsManager LOGISTICS = new GlobalLogisticsManager(); public static final ServerLagger LAGGER = new ServerLagger(); public Create() { @@ -97,6 +103,8 @@ public class Create { } public static void onCtor() { + LOGGER.info("{} {} initializing! Commit hash: {}", NAME, CreateBuildInfo.VERSION, CreateBuildInfo.GIT_COMMIT); + ModLoadingContext modLoadingContext = ModLoadingContext.get(); IEventBus modEventBus = FMLJavaModLoadingContext.get() @@ -108,6 +116,8 @@ public class Create { AllSoundEvents.prepare(); AllTags.init(); AllCreativeModeTabs.register(modEventBus); + AllDisplaySources.register(); + AllDisplayTargets.register(); AllBlocks.register(); AllItems.register(); AllFluids.register(); @@ -123,18 +133,11 @@ public class Create { AllPackets.registerPackets(); AllFeatures.register(modEventBus); AllPlacementModifiers.register(modEventBus); + AllMountedStorageTypes.register(); AllConfigs.register(modLoadingContext); // FIXME: some of these registrations are not thread-safe - AllMovementBehaviours.registerDefaults(); - AllInteractionBehaviours.registerDefaults(); - AllPortalTracks.registerDefaults(); - AllDisplayBehaviours.registerDefaults(); - ContraptionMovementSetting.registerDefaults(); - AllArmInteractionPointTypes.register(); - AllFanProcessingTypes.register(); - BlockSpoutingBehaviour.registerDefaults(); BogeySizes.init(); AllBogeyStyles.init(); // ---- @@ -145,6 +148,8 @@ public class Create { CopperRegistries.inject(); modEventBus.addListener(Create::init); + modEventBus.addListener(Create::onRegister); + modEventBus.addListener(AllEntityTypes::registerEntityAttributes); modEventBus.addListener(EventPriority.LOWEST, CreateDatagen::gatherData); modEventBus.addListener(AllSoundEvents::register); @@ -156,23 +161,42 @@ public class Create { public static void init(final FMLCommonSetupEvent event) { AllFluids.registerFluidInteractions(); + CreateNBTProcessors.register(); event.enqueueWork(() -> { // TODO: custom registration should all happen in one place // Most registration happens in the constructor. // These registrations use Create's registered objects directly so they must run after registration has finished. - BuiltinPotatoProjectileTypes.register(); BoilerHeaters.registerDefaults(); + AllPortalTracks.registerDefaults(); + BlockSpoutingBehaviour.registerDefaults(); + AllMovementBehaviours.registerDefaults(); + AllInteractionBehaviours.registerDefaults(); + AllContraptionMovementSettings.registerDefaults(); + AllOpenPipeEffectHandlers.registerDefaults(); + AllMountedDispenseItemBehaviors.registerDefaults(); // -- - AttachedRegistry.unwrapAll(); AllAdvancements.register(); AllTriggers.register(); }); } + public static void onRegister(final RegisterEvent event) { + AllArmInteractionPointTypes.init(); + AllFanProcessingTypes.init(); + AllItemAttributeTypes.init(); + AllContraptionTypes.init(); + AllPotatoProjectileRenderModes.init(); + AllPotatoProjectileEntityHitActions.init(); + AllPotatoProjectileBlockHitActions.init(); + } + + public static LangBuilder lang() { + return new LangBuilder(ID); + } + public static ResourceLocation asResource(String path) { return new ResourceLocation(ID, path); } - } diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 5763dec8dd..9c20241e22 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -1,5 +1,9 @@ package com.simibubi.create; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.compat.ftb.FTBIntegration; import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionHandler; import com.simibubi.create.content.contraptions.render.ContraptionRenderInfo; import com.simibubi.create.content.contraptions.render.ContraptionRenderInfoManager; @@ -8,6 +12,7 @@ import com.simibubi.create.content.equipment.bell.SoulPulseEffectHandler; import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonRenderHandler; import com.simibubi.create.content.equipment.zapper.ZapperRenderHandler; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; import com.simibubi.create.content.kinetics.waterwheel.WaterWheelRenderer; import com.simibubi.create.content.schematics.client.ClientSchematicLoader; import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler; @@ -15,35 +20,32 @@ import com.simibubi.create.content.schematics.client.SchematicHandler; import com.simibubi.create.content.trains.GlobalRailwayManager; import com.simibubi.create.foundation.ClientResourceReloadListener; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsClient; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.outliner.Outliner; -import com.simibubi.create.foundation.ponder.element.WorldSectionElement; +import com.simibubi.create.foundation.model.ModelSwapper; +import com.simibubi.create.foundation.ponder.CreatePonderPlugin; import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.StitchedSprite; -import com.simibubi.create.foundation.render.SuperByteBufferCache; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.ModelSwapper; -import com.simibubi.create.foundation.utility.ghost.GhostBlocks; import com.simibubi.create.infrastructure.config.AllConfigs; -import com.simibubi.create.infrastructure.ponder.AllPonderTags; -import com.simibubi.create.infrastructure.ponder.PonderIndex; +import com.simibubi.create.infrastructure.gui.CreateMainMenuScreen; +import net.createmod.catnip.config.ui.BaseConfigScreen; +import net.createmod.catnip.config.ui.ConfigScreen; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBufferCache; +import net.createmod.ponder.foundation.PonderIndex; import net.minecraft.ChatFormatting; import net.minecraft.client.GraphicsStatus; import net.minecraft.client.Minecraft; +import net.minecraft.core.Direction; import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentUtils; import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.MutableComponent; + import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; public class CreateClient { - public static final SuperByteBufferCache BUFFER_CACHE = new SuperByteBufferCache(); - public static final Outliner OUTLINER = new Outliner(); - public static final GhostBlocks GHOST_BLOCKS = new GhostBlocks(); public static final ModelSwapper MODEL_SWAPPER = new ModelSwapper(); public static final CasingConnectivity CASING_CONNECTIVITY = new CasingConnectivity(); @@ -64,36 +66,62 @@ public class CreateClient { modEventBus.addListener(CreateClient::clientInit); modEventBus.addListener(AllParticleTypes::registerFactories); - modEventBus.addListener(StitchedSprite::onTextureStitchPost); - AllInstanceTypes.init(); MODEL_SWAPPER.registerListeners(modEventBus); ZAPPER_RENDER_HANDLER.registerListeners(forgeEventBus); POTATO_CANNON_RENDER_HANDLER.registerListeners(forgeEventBus); + + Mods.FTBLIBRARY.executeIfInstalled(() -> () -> FTBIntegration.init(modEventBus, forgeEventBus)); } public static void clientInit(final FMLClientSetupEvent event) { - BUFFER_CACHE.registerCompartment(CachedBufferer.GENERIC_BLOCK); - BUFFER_CACHE.registerCompartment(CachedBufferer.PARTIAL); - BUFFER_CACHE.registerCompartment(CachedBufferer.DIRECTIONAL_PARTIAL); - BUFFER_CACHE.registerCompartment(KineticBlockEntityRenderer.KINETIC_BLOCK); - BUFFER_CACHE.registerCompartment(WaterWheelRenderer.WATER_WHEEL); - BUFFER_CACHE.registerCompartment(ContraptionRenderInfo.CONTRAPTION, 20); - BUFFER_CACHE.registerCompartment(WorldSectionElement.DOC_WORLD_SECTION, 20); + //BUFFER_CACHE.registerCompartment(CachedBufferer.GENERIC_BLOCK); + //BUFFER_CACHE.registerCompartment(CachedPartialBuffers.partial); + //BUFFER_CACHE.registerCompartment(CachedBufferer.DIRECTIONAL_PARTIAL); + //BUFFER_CACHE.registerCompartment(KineticBlockEntityRenderer.KINETIC_BLOCK); + //BUFFER_CACHE.registerCompartment(WaterWheelRenderer.WATER_WHEEL); + //BUFFER_CACHE.registerCompartment(ContraptionRenderInfo.CONTRAPTION, 20); + //BUFFER_CACHE.registerCompartment(WorldSectionElement.DOC_WORLD_SECTION, 20); + + SuperByteBufferCache.getInstance().registerCompartment(CachedBuffers.PARTIAL); + SuperByteBufferCache.getInstance().registerCompartment(CachedBuffers.DIRECTIONAL_PARTIAL); + SuperByteBufferCache.getInstance().registerCompartment(KineticBlockEntityRenderer.KINETIC_BLOCK); + SuperByteBufferCache.getInstance().registerCompartment(WaterWheelRenderer.WATER_WHEEL); + SuperByteBufferCache.getInstance().registerCompartment(ContraptionRenderInfo.CONTRAPTION, 20); AllPartialModels.init(); - AllPonderTags.register(); - PonderIndex.register(); - UIRenderHelper.init(); + //AllPonderTags.register(); + //PonderIndex.register(); + PonderIndex.addPlugin(new CreatePonderPlugin()); + + setupConfigUIBackground(); + } + + private static void setupConfigUIBackground() { + ConfigScreen.backgrounds.put(Create.ID, (screen, graphics, partialTicks) -> { + CreateMainMenuScreen.PANORAMA.render(screen.getMinecraft().getDeltaFrameTime(), 1); + + //RenderSystem.setShaderTexture(0, CreateMainMenuScreen.PANORAMA_OVERLAY_TEXTURES); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + graphics.blit(CreateMainMenuScreen.PANORAMA_OVERLAY_TEXTURES, 0, 0, screen.width, screen.height, 0.0F, 0.0F, 16, 128, 16, 128); + + graphics.fill(0, 0, screen.width, screen.height, 0x90_282c34); + }); + + ConfigScreen.shadowState = AllBlocks.LARGE_COGWHEEL.getDefaultState().setValue(CogWheelBlock.AXIS, Direction.Axis.Y); + + BaseConfigScreen.setDefaultActionFor(Create.ID, base -> base + .withButtonLabels("Client Settings", "World Generation Settings", "Gameplay Settings") + .withSpecs(AllConfigs.client().specification, AllConfigs.common().specification, AllConfigs.server().specification) + ); } public static void invalidateRenderers() { - BUFFER_CACHE.invalidate(); - SCHEMATIC_HANDLER.updateRenderers(); ContraptionRenderInfoManager.resetAll(); } @@ -109,14 +137,15 @@ public class CreateClient { if (AllConfigs.client().ignoreFabulousWarning.get()) return; - MutableComponent text = ComponentUtils.wrapInSquareBrackets(Components.literal("WARN")) + MutableComponent text = ComponentUtils.wrapInSquareBrackets(Component.literal("WARN")) .withStyle(ChatFormatting.GOLD) - .append(Components.literal( - " Some of Create's visual features will not be available while Fabulous graphics are enabled!")) - .withStyle(style -> style - .withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/create dismissFabulousWarning")) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - Components.literal("Click here to disable this warning")))); + .append(Component.literal(" Some of Create's visual features will not be available while Fabulous graphics are enabled!")) + .withStyle(style -> { + return style + .withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/create dismissFabulousWarning")) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, + Component.literal("Click here to disable this warning"))); + }); mc.player.displayClientMessage(text, false); } diff --git a/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java b/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java deleted file mode 100644 index 9bdcf69d49..0000000000 --- a/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.api.behaviour; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; - -import com.simibubi.create.Create; -import com.simibubi.create.compat.tconstruct.SpoutCasting; -import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; -import net.minecraftforge.fluids.FluidStack; - -public abstract class BlockSpoutingBehaviour { - - private static final Map BLOCK_SPOUTING_BEHAVIOURS = new HashMap<>(); - - public static void addCustomSpoutInteraction(ResourceLocation resourceLocation, - BlockSpoutingBehaviour movementBehaviour) { - BLOCK_SPOUTING_BEHAVIOURS.put(resourceLocation, movementBehaviour); - } - - public static void forEach(Consumer accept) { - BLOCK_SPOUTING_BEHAVIOURS.values() - .forEach(accept); - } - - /** - * While idle, Spouts will call this every tick with simulate == true
- * When fillBlock returns > 0, the Spout will start its animation cycle
- *
- * During this animation cycle, fillBlock is called once again with simulate == false but only on the relevant SpoutingBehaviour
- * When fillBlock returns > 0 once again, the Spout will drain its content by the returned amount of units
- * Perform any other side-effects in this method
- * This method is called server-side only (except in ponder)
- * - * @param world - * @param pos of the affected block - * @param spout - * @param availableFluid do not modify, return the amount to be subtracted instead - * @param simulate whether the spout is testing or actually performing this behaviour - * @return amount filled into the block, 0 to idle/cancel - */ - public abstract int fillBlock(Level world, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, - boolean simulate); - - public static void registerDefaults() { - addCustomSpoutInteraction(Create.asResource("ticon_casting"), new SpoutCasting()); - } - -} diff --git a/src/main/java/com/simibubi/create/api/behaviour/display/DisplaySource.java b/src/main/java/com/simibubi/create/api/behaviour/display/DisplaySource.java new file mode 100644 index 0000000000..c1b6181ffb --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/display/DisplaySource.java @@ -0,0 +1,172 @@ +package com.simibubi.create.api.behaviour.display; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.jetbrains.annotations.Nullable; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllDisplaySources; +import com.simibubi.create.Create; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayBoardTarget; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; +import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; +import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.util.entry.RegistryEntry; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; + +import net.createmod.catnip.nbt.NBTProcessors; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class DisplaySource { + public static final SimpleRegistry.Multi BY_BLOCK = SimpleRegistry.Multi.create(); + public static final SimpleRegistry.Multi, DisplaySource> BY_BLOCK_ENTITY = SimpleRegistry.Multi.create(); + + public static final List EMPTY = ImmutableList.of(Component.empty()); + public static final MutableComponent EMPTY_LINE = Component.empty(); + public static final MutableComponent WHITESPACE = CommonComponents.space(); + + public abstract List provideText(DisplayLinkContext context, DisplayTargetStats stats); + + public void transferData(DisplayLinkContext context, DisplayTarget activeTarget, int line) { + DisplayTargetStats stats = activeTarget.provideStats(context); + + if (activeTarget instanceof DisplayBoardTarget fddt) { + List> flapDisplayText = provideFlapDisplayText(context, stats); + fddt.acceptFlapText(line, flapDisplayText, context); + } + + List text = provideText(context, stats); + if (text.isEmpty()) + text = EMPTY; + + if (activeTarget.requiresComponentSanitization()) + for (MutableComponent component : text) + if (NBTProcessors.textComponentHasClickEvent(component)) + return; // Naughty + + activeTarget.acceptText(line, text, context); + } + + public void onSignalReset(DisplayLinkContext context) { + } + + public void populateData(DisplayLinkContext context) { + } + + public int getPassiveRefreshTicks() { + return 100; + } + + public boolean shouldPassiveReset() { + return true; + } + + protected final ResourceLocation getId() { + return CreateBuiltInRegistries.DISPLAY_SOURCE.getKey(this); + } + + protected String getTranslationKey() { + return this.getId().getPath(); + } + + public Component getName() { + return Component.translatable(this.getId().getNamespace() + ".display_source." + getTranslationKey()); + } + + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout, int lineIndex) { + loadFlapDisplayLayout(context, flapDisplay, layout); + } + + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, + FlapDisplayLayout layout) { + if (!layout.isLayout("Default")) + layout.loadDefault(flapDisplay.getMaxCharCount()); + } + + public List> provideFlapDisplayText(DisplayLinkContext context, DisplayTargetStats stats) { + return provideText(context, stats).stream() + .map(Arrays::asList) + .toList(); + } + + @OnlyIn(Dist.CLIENT) + public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, + boolean isFirstLine) { + } + + /** + * Utility for use with Registrate builders. Creates a builder transformer + * that will register the given DisplaySource to a block when ready. + */ + public static NonNullUnaryOperator> displaySource(RegistryEntry source) { + return builder -> builder.onRegisterAfter(CreateRegistries.DISPLAY_SOURCE, block -> BY_BLOCK.add(block, source.get())); + } + + /** + * Get the DisplaySource with the given ID, accounting for legacy names. + */ + @Nullable + public static DisplaySource get(@Nullable ResourceLocation id) { + if (id == null) + return null; + + if (id.getNamespace().equals(Create.ID) && AllDisplaySources.LEGACY_NAMES.containsKey(id.getPath())) { + return AllDisplaySources.LEGACY_NAMES.get(id.getPath()).get(); + } + + return CreateBuiltInRegistries.DISPLAY_SOURCE.get(id); + } + + /** + * Get all DisplaySources applicable to the block at the given location, checking both the Block and BlockEntity. + * Returns an empty list if none are present, not null. + */ + public static List getAll(LevelAccessor level, BlockPos pos) { + BlockState state = level.getBlockState(pos); + List byBlock = BY_BLOCK.get(state); + + BlockEntity be = level.getBlockEntity(pos); + if (be == null) + return byBlock; + + List byBe = BY_BLOCK_ENTITY.get(be.getType()); + + if (byBlock.isEmpty()) { + if (byBe.isEmpty()) { + // none + return List.of(); + } else { + // only BlockEntity + return byBe; + } + } else if (byBe.isEmpty()) { + // only Block + return byBlock; + } else { + // both present, combine + List combined = new ArrayList<>(byBlock); + combined.addAll(byBe); + return combined; + } + } +} diff --git a/src/main/java/com/simibubi/create/api/behaviour/display/DisplayTarget.java b/src/main/java/com/simibubi/create/api/behaviour/display/DisplayTarget.java new file mode 100644 index 0000000000..7a168a1e2d --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/display/DisplayTarget.java @@ -0,0 +1,137 @@ +package com.simibubi.create.api.behaviour.display; + +import java.util.List; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllDisplayTargets; +import com.simibubi.create.Create; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.utility.CreateLang; +import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.util.entry.RegistryEntry; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.SignBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.VoxelShape; + +public abstract class DisplayTarget { + public static final SimpleRegistry BY_BLOCK = SimpleRegistry.create(); + public static final SimpleRegistry, DisplayTarget> BY_BLOCK_ENTITY = SimpleRegistry.create(); + + public abstract void acceptText(int line, List text, DisplayLinkContext context); + + public abstract DisplayTargetStats provideStats(DisplayLinkContext context); + + public AABB getMultiblockBounds(LevelAccessor level, BlockPos pos) { + VoxelShape shape = level.getBlockState(pos) + .getShape(level, pos); + if (shape.isEmpty()) + return new AABB(pos); + return shape.bounds() + .move(pos); + } + + public Component getLineOptionText(int line) { + return CreateLang.translateDirect("display_target.line", line + 1); + } + + public static void reserve(int line, BlockEntity target, DisplayLinkContext context) { + if (line == 0) + return; + + CompoundTag tag = target.getPersistentData(); + CompoundTag compound = tag.getCompound("DisplayLink"); + compound.putLong("Line" + line, context.blockEntity() + .getBlockPos() + .asLong()); + tag.put("DisplayLink", compound); + } + + public boolean isReserved(int line, BlockEntity target, DisplayLinkContext context) { + CompoundTag tag = target.getPersistentData(); + CompoundTag compound = tag.getCompound("DisplayLink"); + + if (!compound.contains("Line" + line)) + return false; + + long l = compound.getLong("Line" + line); + BlockPos reserved = BlockPos.of(l); + + if (!reserved.equals(context.blockEntity() + .getBlockPos()) && AllBlocks.DISPLAY_LINK.has(target.getLevel() + .getBlockState(reserved))) + return true; + + compound.remove("Line" + line); + if (compound.isEmpty()) + tag.remove("DisplayLink"); + return false; + } + + public boolean requiresComponentSanitization() { + return false; + } + + /** + * Utility for use with Registrate builders. Creates a builder transformer + * that will register the given DisplayTarget to a block when ready. + */ + public static NonNullUnaryOperator> displayTarget(RegistryEntry target) { + return builder -> builder.onRegisterAfter(CreateRegistries.DISPLAY_TARGET, block -> BY_BLOCK.register(block, target.get())); + } + + /** + * Get the DisplayTarget with the given ID, accounting for legacy names. + */ + @Nullable + public static DisplayTarget get(@Nullable ResourceLocation id) { + if (id == null) + return null; + + if (id.getNamespace().equals(Create.ID) && AllDisplayTargets.LEGACY_NAMES.containsKey(id.getPath())) { + return AllDisplayTargets.LEGACY_NAMES.get(id.getPath()).get(); + } + + return CreateBuiltInRegistries.DISPLAY_TARGET.get(id); + } + + /** + * Get the DisplayTarget applicable to the given location, or null if there isn't one. + */ + @Nullable + public static DisplayTarget get(LevelAccessor level, BlockPos pos) { + BlockState state = level.getBlockState(pos); + DisplayTarget byBlock = BY_BLOCK.get(state); + // block takes priority if present, it's more granular + if (byBlock != null) + return byBlock; + + BlockEntity be = level.getBlockEntity(pos); + if (be == null) + return null; + + DisplayTarget byBe = BY_BLOCK_ENTITY.get(be.getType()); + if (byBe != null) + return byBe; + + // special case: modded signs are common + return be instanceof SignBlockEntity ? AllDisplayTargets.SIGN.get() : null; + } +} diff --git a/src/main/java/com/simibubi/create/api/behaviour/interaction/ConductorBlockInteractionBehavior.java b/src/main/java/com/simibubi/create/api/behaviour/interaction/ConductorBlockInteractionBehavior.java new file mode 100644 index 0000000000..003b6949fb --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/interaction/ConductorBlockInteractionBehavior.java @@ -0,0 +1,142 @@ +package com.simibubi.create.api.behaviour.interaction; + +import java.util.function.Consumer; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.schedule.Schedule; +import com.simibubi.create.content.trains.schedule.ScheduleItem; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.data.Iterate; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +/** + * Partial interaction behavior implementation that allows blocks to act as conductors on trains, like Blaze Burners. + */ +public abstract class ConductorBlockInteractionBehavior extends MovingInteractionBehaviour { + /** + * Check if the given state is capable of being a conductor. + */ + public abstract boolean isValidConductor(BlockState state); + + /** + * Called when the conductor's schedule has changed. + * @param hasSchedule true if the schedule was set, false if it was removed + * @param blockStateSetter a consumer that will change the BlockState of this conductor on the contraption + */ + protected void onScheduleUpdate(boolean hasSchedule, BlockState currentBlockState, Consumer blockStateSetter) { + } + + @Override + public final boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + ItemStack itemInHand = player.getItemInHand(activeHand); + + if (!(contraptionEntity instanceof CarriageContraptionEntity carriageEntity)) + return false; + if (activeHand == InteractionHand.OFF_HAND) + return false; + Contraption contraption = carriageEntity.getContraption(); + if (!(contraption instanceof CarriageContraption carriageContraption)) + return false; + + StructureBlockInfo info = carriageContraption.getBlocks() + .get(localPos); + if (info == null || !this.isValidConductor(info.state())) + return false; + + Direction assemblyDirection = carriageContraption.getAssemblyDirection(); + for (Direction direction : Iterate.directionsInAxis(assemblyDirection.getAxis())) { + if (!carriageContraption.inControl(localPos, direction)) + continue; + + Train train = carriageEntity.getCarriage().train; + if (train == null) + return false; + if (player.level().isClientSide) + return true; + + if (train.runtime.getSchedule() != null) { + if (train.runtime.paused && !train.runtime.completed) { + train.runtime.paused = false; + AllSoundEvents.CONFIRM.playOnServer(player.level(), player.blockPosition(), 1, 1); + player.displayClientMessage(CreateLang.translateDirect("schedule.continued"), true); + return true; + } + + if (!itemInHand.isEmpty()) { + AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); + player.displayClientMessage(CreateLang.translateDirect("schedule.remove_with_empty_hand"), true); + return true; + } + + AllSoundEvents.playItemPickup(player); + player.displayClientMessage(CreateLang.translateDirect( + train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"), + true); + player.setItemInHand(activeHand, train.runtime.returnSchedule()); + this.onScheduleUpdate(false, info.state(), newBlockState -> setBlockState(localPos, contraptionEntity, newBlockState)); + return true; + } + + if (!AllItems.SCHEDULE.isIn(itemInHand)) + return true; + + Schedule schedule = ScheduleItem.getSchedule(itemInHand); + if (schedule == null) + return false; + + if (schedule.entries.isEmpty()) { + AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); + player.displayClientMessage(CreateLang.translateDirect("schedule.no_stops"), true); + return true; + } + this.onScheduleUpdate(true, info.state(), newBlockState -> setBlockState(localPos, contraptionEntity, newBlockState)); + train.runtime.setSchedule(schedule, false); + AllAdvancements.CONDUCTOR.awardTo(player); + AllSoundEvents.CONFIRM.playOnServer(player.level(), player.blockPosition(), 1, 1); + player.displayClientMessage(CreateLang.translateDirect("schedule.applied_to_train") + .withStyle(ChatFormatting.GREEN), true); + itemInHand.shrink(1); + player.setItemInHand(activeHand, itemInHand.isEmpty() ? ItemStack.EMPTY : itemInHand); + return true; + } + + player.displayClientMessage(CreateLang.translateDirect("schedule.non_controlling_seat"), true); + AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); + return true; + } + + private void setBlockState(BlockPos localPos, AbstractContraptionEntity contraption, BlockState newState) { + StructureTemplate.StructureBlockInfo info = contraption.getContraption().getBlocks().get(localPos); + if (info != null) { + setContraptionBlockData(contraption, localPos, new StructureTemplate.StructureBlockInfo(info.pos(), newState, info.nbt())); + } + } + + /** + * Implementation used for Blaze Burners. May be reused by addons if applicable. + */ + public static class BlazeBurner extends ConductorBlockInteractionBehavior { + @Override + public boolean isValidConductor(BlockState state) { + return state.getValue(BlazeBurnerBlock.HEAT_LEVEL) != BlazeBurnerBlock.HeatLevel.NONE; + } + } +} diff --git a/src/main/java/com/simibubi/create/api/behaviour/interaction/MovingInteractionBehaviour.java b/src/main/java/com/simibubi/create/api/behaviour/interaction/MovingInteractionBehaviour.java new file mode 100644 index 0000000000..570bc98364 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/interaction/MovingInteractionBehaviour.java @@ -0,0 +1,53 @@ +package com.simibubi.create.api.behaviour.interaction; + +import org.apache.commons.lang3.tuple.MutablePair; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.tterrag.registrate.util.nullness.NonNullConsumer; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +/** + * MovingInteractionBehaviors define behavior of blocks on contraptions + * when interacted with by players or collided with by entities. + */ +public abstract class MovingInteractionBehaviour { + public static final SimpleRegistry REGISTRY = SimpleRegistry.create(); + + /** + * Creates a consumer that will register a behavior to a block. Useful for Registrate. + */ + public static NonNullConsumer interactionBehaviour(MovingInteractionBehaviour behaviour) { + return b -> REGISTRY.register(b, behaviour); + } + + protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, + StructureBlockInfo info, MovementContext ctx) { + contraptionEntity.getContraption().getActors().remove(index); + contraptionEntity.getContraption().getActors().add(index, MutablePair.of(info, ctx)); + if (contraptionEntity.level().isClientSide) + contraptionEntity.getContraption().deferInvalidate = true; + } + + protected void setContraptionBlockData(AbstractContraptionEntity contraptionEntity, BlockPos pos, + StructureBlockInfo info) { + if (contraptionEntity.level().isClientSide()) + return; + contraptionEntity.setBlock(pos, info); + } + + public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + return true; + } + + public void handleEntityCollision(Entity entity, BlockPos localPos, AbstractContraptionEntity contraptionEntity) {} + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java b/src/main/java/com/simibubi/create/api/behaviour/movement/MovementBehaviour.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java rename to src/main/java/com/simibubi/create/api/behaviour/movement/MovementBehaviour.java index 02f502258f..f97975041e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java +++ b/src/main/java/com/simibubi/create/api/behaviour/movement/MovementBehaviour.java @@ -1,11 +1,14 @@ -package com.simibubi.create.content.contraptions.behaviour; +package com.simibubi.create.api.behaviour.movement; import javax.annotation.Nullable; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ActorVisual; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import com.simibubi.create.infrastructure.config.AllConfigs; +import com.tterrag.registrate.util.nullness.NonNullConsumer; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import net.minecraft.client.renderer.MultiBufferSource; @@ -14,11 +17,24 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.ItemHandlerHelper; +/** + * MovementBehaviors, also known as Actors, provide behavior to blocks mounted on contraptions. + * Blocks may be associated with a behavior through {@link #REGISTRY}. + */ public interface MovementBehaviour { + SimpleRegistry REGISTRY = SimpleRegistry.create(); + + /** + * Creates a consumer that will register a behavior to a block. Useful for Registrate. + */ + static NonNullConsumer movementBehaviour(MovementBehaviour behaviour) { + return b -> REGISTRY.register(b, behaviour); + } default boolean isActive(MovementContext context) { return !context.disabled; @@ -53,7 +69,7 @@ public interface MovementBehaviour { default void dropItem(MovementContext context, ItemStack stack) { ItemStack remainder; if (AllConfigs.server().kinetics.moveItemsToStorage.get()) - remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false); + remainder = ItemHandlerHelper.insertItem(context.contraption.getStorage().getAllItems(), stack, false); else remainder = stack; if (remainder.isEmpty()) diff --git a/src/main/java/com/simibubi/create/api/behaviour/spouting/BlockSpoutingBehaviour.java b/src/main/java/com/simibubi/create/api/behaviour/spouting/BlockSpoutingBehaviour.java new file mode 100644 index 0000000000..f1d9ebe32f --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/spouting/BlockSpoutingBehaviour.java @@ -0,0 +1,103 @@ +package com.simibubi.create.api.behaviour.spouting; + +import java.util.List; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.Create; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.compat.tconstruct.SpoutCasting; +import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.FarmBlock; +import net.minecraft.world.level.block.LayeredCauldronBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.registries.ForgeRegistries; + +/** + * Interface for custom block-filling behavior for spouts. + *

+ * Behaviors are queried by block first, through {@link #BY_BLOCK}. If no behavior was provided, + * they are then queried by block entity type, through {@link #BY_BLOCK_ENTITY}. + * @see StateChangingBehavior + * @see CauldronSpoutingBehavior + */ +@FunctionalInterface +public interface BlockSpoutingBehaviour { + SimpleRegistry BY_BLOCK = SimpleRegistry.create(); + SimpleRegistry, BlockSpoutingBehaviour> BY_BLOCK_ENTITY = SimpleRegistry.create(); + + /** + * Get the behavior that should be used for the block at the given location. + * Queries both the block and the block entity if needed. + */ + @Nullable + static BlockSpoutingBehaviour get(Level level, BlockPos pos) { + BlockState state = level.getBlockState(pos); + BlockSpoutingBehaviour byBlock = BY_BLOCK.get(state.getBlock()); + if (byBlock != null) + return byBlock; + + BlockEntity be = level.getBlockEntity(pos); + if (be == null) + return null; + + return BY_BLOCK_ENTITY.get(be.getType()); + } + + static void registerDefaults() { + Predicate isWater = fluid -> fluid.isSame(Fluids.WATER); + BlockSpoutingBehaviour toMud = StateChangingBehavior.setTo(250, isWater, Blocks.MUD); + + for (Block dirt : List.of(Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.ROOTED_DIRT)) { + BY_BLOCK.register(dirt, toMud); + } + + BY_BLOCK.register(Blocks.FARMLAND, StateChangingBehavior.incrementingState(100, isWater, FarmBlock.MOISTURE)); + BY_BLOCK.register(Blocks.WATER_CAULDRON, StateChangingBehavior.incrementingState(250, isWater, LayeredCauldronBlock.LEVEL)); + BY_BLOCK.register(Blocks.CAULDRON, CauldronSpoutingBehavior.INSTANCE); + + if (!Mods.TCONSTRUCT.isLoaded()) + return; + + for (String name : List.of("table", "basin")) { + ResourceLocation id = Mods.TCONSTRUCT.rl(name); + if (ForgeRegistries.BLOCK_ENTITY_TYPES.containsKey(id)) { + BlockEntityType table = ForgeRegistries.BLOCK_ENTITY_TYPES.getValue(id); + BY_BLOCK_ENTITY.register(table, SpoutCasting.INSTANCE); + } else { + Create.LOGGER.warn("Block entity {} wasn't found. Outdated compat?", id); + } + } + } + + /** + * While idle, spouts will query the behavior provided by the block below it. + * If one is present, this method will be called every tick with simulate == true. + *

+ * When a value greater than 0 is returned, the spout will begin processing. It will call this method again + * with simulate == false, which is when any filling behavior should actually occur. + *

+ * This method is only called on the server side, except for in Ponder. + * @param level The current level + * @param pos The position of the affected block + * @param spout The spout block entity that is calling this + * @param availableFluid A copy of the fluidStack that is available, modifying this will do nothing, return the amount to be subtracted instead + * @param simulate Whether the spout is testing or actually performing this behaviour + * @return The amount filled into the block, 0 to idle/cancel + */ + int fillBlock(Level level, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, boolean simulate); +} diff --git a/src/main/java/com/simibubi/create/api/behaviour/spouting/CauldronSpoutingBehavior.java b/src/main/java/com/simibubi/create/api/behaviour/spouting/CauldronSpoutingBehavior.java new file mode 100644 index 0000000000..773f5dc2f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/spouting/CauldronSpoutingBehavior.java @@ -0,0 +1,56 @@ +package com.simibubi.create.api.behaviour.spouting; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; + +import net.minecraft.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; + +import net.minecraftforge.fluids.FluidStack; + +/** + * {@link BlockSpoutingBehaviour} for empty cauldrons. Mods can register their fluids + * to {@link #CAULDRON_INFO} to allow spouts to fill empty cauldrons with their fluids. + */ +public enum CauldronSpoutingBehavior implements BlockSpoutingBehaviour { + INSTANCE; + + public static final SimpleRegistry CAULDRON_INFO = Util.make(() -> { + SimpleRegistry registry = SimpleRegistry.create(); + registry.register(Fluids.WATER, new CauldronInfo(250, Blocks.WATER_CAULDRON)); + registry.register(Fluids.LAVA, new CauldronInfo(1000, Blocks.LAVA_CAULDRON)); + return registry; + }); + + @Override + public int fillBlock(Level level, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, boolean simulate) { + CauldronInfo info = CAULDRON_INFO.get(availableFluid.getFluid()); + if (info == null) + return 0; + + if (availableFluid.getAmount() < info.amount) + return 0; + + if (!simulate) { + level.setBlockAndUpdate(pos, info.cauldron); + } + + return info.amount; + } + + /** + * @param amount the amount of fluid that must be inserted into an empty cauldron + * @param cauldron the BlockState to set after filling an empty cauldron with the given amount of fluid + */ + public record CauldronInfo(int amount, BlockState cauldron) { + public CauldronInfo(int amount, Block block) { + this(amount, block.defaultBlockState()); + } + } +} diff --git a/src/main/java/com/simibubi/create/api/behaviour/spouting/StateChangingBehavior.java b/src/main/java/com/simibubi/create/api/behaviour/spouting/StateChangingBehavior.java new file mode 100644 index 0000000000..e4064c5f3a --- /dev/null +++ b/src/main/java/com/simibubi/create/api/behaviour/spouting/StateChangingBehavior.java @@ -0,0 +1,71 @@ +package com.simibubi.create.api.behaviour.spouting; + +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.material.Fluid; + +import net.minecraftforge.fluids.FluidStack; + +/** + * An implementation of {@link BlockSpoutingBehaviour} that allows for easily modifying a BlockState through spouting. + * @param amount the amount of fluid consumed when filling + * @param fluidTest a predicate for fluids that can be used to fill the target block + * @param canFill a predicate that must match the target BlockState to fill it + * @param fillFunction a function that converts the current state into the filled one + */ +public record StateChangingBehavior(int amount, Predicate fluidTest, Predicate canFill, + UnaryOperator fillFunction) implements BlockSpoutingBehaviour { + @Override + public int fillBlock(Level level, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, boolean simulate) { + if (availableFluid.getAmount() < this.amount || !this.fluidTest.test(availableFluid.getFluid())) + return 0; + + BlockState state = level.getBlockState(pos); + if (!this.canFill.test(state)) + return 0; + + if (!simulate) { + BlockState newState = this.fillFunction.apply(state); + level.setBlockAndUpdate(pos, newState); + } + + return this.amount; + } + + /** + * Shortcut for {@link #setTo(int, Predicate, BlockState)} that uses the Block's default state. + */ + public static BlockSpoutingBehaviour setTo(int amount, Predicate fluidTest, Block block) { + return setTo(amount, fluidTest, block.defaultBlockState()); + } + + /** + * Create a {@link BlockSpoutingBehaviour} that will simply convert the target block to the given state. + * @param newState the state that will be set after filling + */ + public static BlockSpoutingBehaviour setTo(int amount, Predicate fluidTest, BlockState newState) { + return new StateChangingBehavior(amount, fluidTest, state -> true, state -> newState); + } + + /** + * Create a {@link BlockSpoutingBehaviour} that will increment the given {@link IntegerProperty} until it reaches + * its maximum value, consuming {@code amount} each time fluid is filled. + * @param property the property that will be incremented by one on each fill + */ + public static BlockSpoutingBehaviour incrementingState(int amount, Predicate fluidTest, IntegerProperty property) { + int max = property.getPossibleValues().stream().max(Integer::compareTo).orElseThrow(); + + Predicate canFill = state -> state.getValue(property) < max; + UnaryOperator fillFunction = state -> state.setValue(property, state.getValue(property) + 1); + + return new StateChangingBehavior(amount, fluidTest, canFill, fillFunction); + } +} diff --git a/src/main/java/com/simibubi/create/api/boiler/BoilerHeater.java b/src/main/java/com/simibubi/create/api/boiler/BoilerHeater.java new file mode 100644 index 0000000000..71620b24d7 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/boiler/BoilerHeater.java @@ -0,0 +1,51 @@ +package com.simibubi.create.api.boiler; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.fluids.tank.BoilerHeaters; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +/** + * A BoilerHeater provides heat to boilers. + * Boilers will query blocks for heaters through the registry, usually with {@link #findHeat(Level, BlockPos, BlockState) findHeat}. + * Heaters can provide a heat level by returning any positive integer from their {@link #getHeat(Level, BlockPos, BlockState) getHeat} method. + * Returning any negative number counts as no heat - {@link #NO_HEAT} is provided for convenience. + *

+ * Returning {@link #PASSIVE_HEAT} is special - passive heat can be used to provide a small amount of heat, highly limiting + * in its abilities. This is usually used for free sources of heat, such as fire or magma blocks. + */ +@FunctionalInterface +public interface BoilerHeater { + int PASSIVE_HEAT = 0; + int NO_HEAT = -1; + + /** + * The heater used by common passively-heating blocks. Automatically provides + * heat for any block in the {@code create:passive_boiler_heaters} block tag. + */ + BoilerHeater PASSIVE = BoilerHeaters::passive; + /** + * The heater used by Blaze Burners. Addons can register this to their own blocks if they use the same functionality. + */ + BoilerHeater BLAZE_BURNER = BoilerHeaters::blazeBurner; + + SimpleRegistry REGISTRY = SimpleRegistry.create(); + + /** + * Gets the heat at the given location. If a heater is present, queries it for heat. If not, returns {@link #NO_HEAT}. + */ + static float findHeat(Level level, BlockPos pos, BlockState state) { + BoilerHeater heater = REGISTRY.get(state); + return heater != null ? heater.getHeat(level, pos, state) : NO_HEAT; + } + + /** + * @return the amount of heat to provide. + * @see #NO_HEAT + * @see #PASSIVE_HEAT + */ + float getHeat(Level level, BlockPos pos, BlockState state); +} diff --git a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java index a056d4d9fa..364c50ae51 100644 --- a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java +++ b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java @@ -15,14 +15,15 @@ import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; @@ -38,7 +39,7 @@ public class ConnectivityHandler { } private static void formMulti(BlockEntityType type, - BlockGetter level, SearchCache cache, List frontier) { + BlockGetter level, SearchCache cache, List frontier) { PriorityQueue> creationQueue = makeCreationQueue(); Set visited = new HashSet<>(); Direction.Axis mainAxis = frontier.get(0) @@ -110,7 +111,7 @@ public class ConnectivityHandler { } private static int tryToFormNewMulti(T be, SearchCache cache, - boolean simulate) { + boolean simulate) { int bestWidth = 1; int bestAmount = -1; if (!be.isController()) @@ -145,7 +146,7 @@ public class ConnectivityHandler { } private static int tryToFormNewMultiOfWidth(T be, int width, - SearchCache cache, boolean simulate) { + SearchCache cache, boolean simulate) { int amount = 0; int height = 0; BlockEntityType type = be.getType(); @@ -163,13 +164,14 @@ public class ConnectivityHandler { } Direction.Axis axis = be.getMainConnectionAxis(); - Search: for (int yOffset = 0; yOffset < be.getMaxLength(axis, width); yOffset++) { + Search: + for (int yOffset = 0; yOffset < be.getMaxLength(axis, width); yOffset++) { for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { BlockPos pos = switch (axis) { - case X -> origin.offset(yOffset, xOffset, zOffset); - case Y -> origin.offset(xOffset, yOffset, zOffset); - case Z -> origin.offset(xOffset, zOffset, yOffset); + case X -> origin.offset(yOffset, xOffset, zOffset); + case Y -> origin.offset(xOffset, yOffset, zOffset); + case Z -> origin.offset(xOffset, zOffset, yOffset); }; Optional part = cache.getOrCache(type, level, pos); if (part.isEmpty()) @@ -232,9 +234,9 @@ public class ConnectivityHandler { for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { BlockPos pos = switch (axis) { - case X -> origin.offset(yOffset, xOffset, zOffset); - case Y -> origin.offset(xOffset, yOffset, zOffset); - case Z -> origin.offset(xOffset, zOffset, yOffset); + case X -> origin.offset(yOffset, xOffset, zOffset); + case Y -> origin.offset(xOffset, yOffset, zOffset); + case Z -> origin.offset(xOffset, zOffset, yOffset); }; T part = partAt(type, level, pos); if (part == null) @@ -283,7 +285,7 @@ public class ConnectivityHandler { // tryReconnect helps whenever only a few tanks have been removed private static void splitMultiAndInvalidate(T be, - @Nullable SearchCache cache, boolean tryReconnect) { + @Nullable SearchCache cache, boolean tryReconnect) { Level level = be.getLevel(); if (level == null) return; @@ -315,13 +317,13 @@ public class ConnectivityHandler { for (int yOffset = 0; yOffset < height; yOffset++) { for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { - + BlockPos pos = switch (axis) { - case X -> origin.offset(yOffset, xOffset, zOffset); - case Y -> origin.offset(xOffset, yOffset, zOffset); - case Z -> origin.offset(xOffset, zOffset, yOffset); + case X -> origin.offset(yOffset, xOffset, zOffset); + case Y -> origin.offset(xOffset, yOffset, zOffset); + case Z -> origin.offset(xOffset, zOffset, yOffset); }; - + T partAt = partAt(be.getType(), level, pos); if (partAt == null) continue; @@ -353,19 +355,19 @@ public class ConnectivityHandler { frontier.add(partAt); partAt.preventConnectivityUpdate(); } - if (cache != null) + if (cache != null) cache.put(pos, partAt); } } } - + if (be instanceof IMultiBlockEntityContainer.Inventory inv && inv.hasInventory()) be.getCapability(ForgeCapabilities.ITEM_HANDLER) .invalidate(); if (be instanceof IMultiBlockEntityContainer.Fluid fluid && fluid.hasTank()) be.getCapability(ForgeCapabilities.FLUID_HANDLER) .invalidate(); - + if (tryReconnect) formMulti(be.getType(), level, cache == null ? new SearchCache<>() : cache, frontier); } @@ -376,7 +378,7 @@ public class ConnectivityHandler { @Nullable public static T partAt(BlockEntityType type, BlockGetter level, - BlockPos pos) { + BlockPos pos) { BlockEntity be = level.getBlockEntity(pos); if (be != null && be.getType() == type && !be.isRemoved()) return checked(be); @@ -384,7 +386,7 @@ public class ConnectivityHandler { } public static boolean isConnected(BlockGetter level, BlockPos pos, - BlockPos other) { + BlockPos other) { T one = checked(level.getBlockEntity(pos)); T two = checked(level.getBlockEntity(other)); if (one == null || two == null) diff --git a/src/main/java/com/simibubi/create/api/contraption/BlockMovementChecks.java b/src/main/java/com/simibubi/create/api/contraption/BlockMovementChecks.java new file mode 100644 index 0000000000..ea87c8988c --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/BlockMovementChecks.java @@ -0,0 +1,147 @@ +package com.simibubi.create.api.contraption; + +import com.simibubi.create.impl.contraption.BlockMovementChecksImpl; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Provides several interfaces that can define the behavior of blocks when mounting onto contraptions: + *

    + *
  • {@link MovementNecessaryCheck}
  • + *
  • {@link MovementAllowedCheck}
  • + *
  • {@link BrittleCheck}
  • + *
  • {@link AttachedCheck}
  • + *
  • {@link NotSupportiveCheck}
  • + *
+ * See each one for details. + *

+ * For each interface, checks can be registered and queried. + * Registration is thread-safe and can be done in parallel mod init. + * Each query will iterate all registered checks of that type in reverse-registration order. If a check returns + * a non-{@link CheckResult#PASS PASS} result, that is the result of the query. If no check catches a query, then + * a best-effort fallback is used. + */ +public class BlockMovementChecks { + public static void registerMovementNecessaryCheck(MovementNecessaryCheck check) { + BlockMovementChecksImpl.registerMovementNecessaryCheck(check); + } + + public static void registerMovementAllowedCheck(MovementAllowedCheck check) { + BlockMovementChecksImpl.registerMovementAllowedCheck(check); + } + + public static void registerBrittleCheck(BrittleCheck check) { + BlockMovementChecksImpl.registerBrittleCheck(check); + } + + public static void registerAttachedCheck(AttachedCheck check) { + BlockMovementChecksImpl.registerAttachedCheck(check); + } + + public static void registerNotSupportiveCheck(NotSupportiveCheck check) { + BlockMovementChecksImpl.registerNotSupportiveCheck(check); + } + + // queries + + public static boolean isMovementNecessary(BlockState state, Level world, BlockPos pos) { + return BlockMovementChecksImpl.isMovementNecessary(state, world, pos); + } + + public static boolean isMovementAllowed(BlockState state, Level world, BlockPos pos) { + return BlockMovementChecksImpl.isMovementAllowed(state, world, pos); + } + + public static boolean isBrittle(BlockState state) { + return BlockMovementChecksImpl.isBrittle(state); + } + + public static boolean isBlockAttachedTowards(BlockState state, Level world, BlockPos pos, Direction direction) { + return BlockMovementChecksImpl.isBlockAttachedTowards(state, world, pos, direction); + } + + public static boolean isNotSupportive(BlockState state, Direction facing) { + return BlockMovementChecksImpl.isNotSupportive(state, facing); + } + + @FunctionalInterface + public interface MovementNecessaryCheck { + /** + * Determine if it's necessary to move the given block. Contraptions + * will generally ignore blocks that are unnecessary to move. + */ + CheckResult isMovementNecessary(BlockState state, Level world, BlockPos pos); + } + + @FunctionalInterface + public interface MovementAllowedCheck { + /** + * Determine if the given block is movable. Immobile blocks will generally prevent a contraption from assembling. + * @see ContraptionMovementSetting + */ + CheckResult isMovementAllowed(BlockState state, Level world, BlockPos pos); + } + + @FunctionalInterface + public interface BrittleCheck { + /** + * Brittle blocks are blocks that require another block for support, like torches or ladders. + * They're collected first to avoid them breaking when their support block is removed. + */ + CheckResult isBrittle(BlockState state); + } + + @FunctionalInterface + public interface AttachedCheck { + /** + * Determine if the given block is attached to the block in the given direction. + * Attached blocks will be moved together. Examples: + *

    + *
  • Ladders are attached to their support block
  • + *
  • Pressure plates are attached to the floor
  • + *
  • Fluid tanks are attached to others in their multiblock
  • + *
  • Bed halves are attached to each other
  • + *
+ */ + CheckResult isBlockAttachedTowards(BlockState state, Level world, BlockPos pos, Direction direction); + } + + @FunctionalInterface + public interface NotSupportiveCheck { + /** + * Check if the given block is non-supportive in the given direction. + * Non-supportive blocks stop block collection propagation. + * Examples: + *
    + *
  • Drills are not supportive for the block in front of them
  • + *
  • Carpets are not supportive for the block above them
  • + *
  • Non-extended stickers are not supportive of the block in front of them
  • + *
+ */ + CheckResult isNotSupportive(BlockState state, Direction direction); + } + + public enum CheckResult { + SUCCESS, FAIL, PASS; + + public boolean toBoolean() { + if (this == PASS) { + throw new IllegalStateException("PASS does not have a boolean value"); + } + + return this == SUCCESS; + } + + public static CheckResult of(boolean b) { + return b ? SUCCESS : FAIL; + } + + public static CheckResult of(Boolean b) { + return b == null ? PASS : (b ? SUCCESS : FAIL); + } + } + +} diff --git a/src/main/java/com/simibubi/create/api/contraption/ContraptionMovementSetting.java b/src/main/java/com/simibubi/create/api/contraption/ContraptionMovementSetting.java new file mode 100644 index 0000000000..fb7f229191 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/ContraptionMovementSetting.java @@ -0,0 +1,78 @@ +package com.simibubi.create.api.contraption; + +import java.util.Collection; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.simibubi.create.api.registry.SimpleRegistry; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +import net.minecraftforge.common.extensions.IForgeBlock; + +/** + * Defines whether a block is movable by contraptions. + * This is used as a fallback check for {@link BlockMovementChecks#isMovementAllowed(BlockState, Level, BlockPos)}. + * The registry uses suppliers, so the setting of a block can change. This is useful for config options. + */ +public enum ContraptionMovementSetting { + /** + * Block is fully movable with no restrictions. + */ + MOVABLE, + /** + * Block can be mounted and moved, but if it's on a minecart contraption, the contraption cannot be picked up. + */ + NO_PICKUP, + /** + * Block cannot ever be moved by a contraption. + */ + UNMOVABLE; + + public static final SimpleRegistry> REGISTRY = SimpleRegistry.create(); + + /** + * Shortcut that gets the block of the given state. + */ + @Nullable + public static ContraptionMovementSetting get(BlockState state) { + return get(state.getBlock()); + } + + /** + * Get the current movement setting of the given block. + */ + @Nullable + public static ContraptionMovementSetting get(Block block) { + if (block instanceof MovementSettingProvider provider) + return provider.getContraptionMovementSetting(); + Supplier supplier = REGISTRY.get(block); + return supplier == null ? null : supplier.get(); + } + + /** + * Check if any of the blocks in the collection match the given setting. + */ + public static boolean anyAre(Collection blocks, ContraptionMovementSetting setting) { + return blocks.stream().anyMatch(b -> get(b.state().getBlock()) == setting); + } + + /** + * Check if any of the blocks in the collection forbid pickup. + */ + public static boolean isNoPickup(Collection blocks) { + return anyAre(blocks, ContraptionMovementSetting.NO_PICKUP); + } + + /** + * Interface that may optionally be implemented on a Block implementation which will be queried instead of the registry. + */ + public interface MovementSettingProvider extends IForgeBlock { + ContraptionMovementSetting getContraptionMovementSetting(); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/ContraptionType.java b/src/main/java/com/simibubi/create/api/contraption/ContraptionType.java new file mode 100644 index 0000000000..6c6f948937 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/ContraptionType.java @@ -0,0 +1,43 @@ +package com.simibubi.create.api.contraption; + +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllContraptionTypes; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.content.contraptions.Contraption; + +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; + +public final class ContraptionType { + public final Supplier factory; + public final Holder.Reference holder; + + public ContraptionType(Supplier factory) { + this.factory = factory; + this.holder = CreateBuiltInRegistries.CONTRAPTION_TYPE.createIntrusiveHolder(this); + } + + public boolean is(TagKey tag) { + return this.holder.is(tag); + } + + /** + * Lookup the ContraptionType with the given ID, and create a new Contraption from it if present. + * If it doesn't exist, returns null. + */ + @Nullable + public static Contraption fromType(String typeId) { + ContraptionType legacy = AllContraptionTypes.BY_LEGACY_NAME.get(typeId); + if (legacy != null) { + return legacy.factory.get(); + } + + ResourceLocation id = ResourceLocation.tryParse(typeId); + ContraptionType type = CreateBuiltInRegistries.CONTRAPTION_TYPE.get(id); + return type == null ? null : type.factory.get(); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/DefaultMountedDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/DefaultMountedDispenseBehavior.java new file mode 100644 index 0000000000..941b8a0de9 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/DefaultMountedDispenseBehavior.java @@ -0,0 +1,88 @@ +package com.simibubi.create.api.contraption.dispenser; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; +import net.minecraft.world.Container; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.level.block.entity.HopperBlockEntity; +import net.minecraft.world.phys.Vec3; + +/** + * A parallel to {@link DefaultDispenseItemBehavior}, providing a common, default, extendable dispense implementation. + */ +public class DefaultMountedDispenseBehavior implements MountedDispenseBehavior { + /** + * A reusable instance of the default behavior. + */ + public static final MountedDispenseBehavior INSTANCE = new DefaultMountedDispenseBehavior(); + + @Override + public ItemStack dispense(ItemStack stack, MovementContext context, BlockPos pos) { + Vec3 normal = MountedDispenseBehavior.getDispenserNormal(context); + + Direction closestToFacing = MountedDispenseBehavior.getClosestFacingDirection(normal); + Container inventory = HopperBlockEntity.getContainerAt(context.world, pos.relative(closestToFacing)); + if (inventory == null) { + ItemStack remainder = this.execute(stack, context, pos, normal); + this.playSound(context.world, pos); + this.playAnimation(context.world, pos, closestToFacing); + return remainder; + } else { + ItemStack toInsert = stack.copyWithCount(1); + ItemStack remainder = HopperBlockEntity.addItem(null, inventory, toInsert, closestToFacing.getOpposite()); + if (remainder.isEmpty()) { + stack.shrink(1); + } + } + return stack; + } + + /** + * Dispense the given item. Sounds and particles are already handled. + * @return the remaining items after dispensing one + */ + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + ItemStack toDispense = stack.split(1); + spawnItem(context.world, toDispense, 6, facing, pos, context); + return stack; + } + + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_DISPENSER_DISPENSE, pos, 0); + } + + protected void playAnimation(LevelAccessor level, BlockPos pos, Vec3 facing) { + this.playAnimation(level, pos, MountedDispenseBehavior.getClosestFacingDirection(facing)); + } + + protected void playAnimation(LevelAccessor level, BlockPos pos, Direction direction) { + level.levelEvent(LevelEvent.PARTICLES_SHOOT, pos, direction.get3DDataValue()); + } + + public static void spawnItem(Level level, ItemStack stack, int speed, Vec3 facing, BlockPos pos, MovementContext context) { + double x = pos.getX() + facing.x + .5; + double y = pos.getY() + facing.y + .5; + double z = pos.getZ() + facing.z + .5; + if (MountedDispenseBehavior.getClosestFacingDirection(facing).getAxis() == Direction.Axis.Y) { + y = y - 0.125; + } else { + y = y - 0.15625; + } + + ItemEntity entity = new ItemEntity(level, x, y, z, stack); + double d3 = level.random.nextDouble() * 0.1 + 0.2; + entity.setDeltaMovement( + level.random.nextGaussian() * 0.0075 * speed + facing.x() * d3 + context.motion.x, + level.random.nextGaussian() * 0.0075 * speed + facing.y() * d3 + context.motion.y, + level.random.nextGaussian() * 0.0075 * speed + facing.z() * d3 + context.motion.z + ); + level.addFreshEntity(entity); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedDispenseBehavior.java new file mode 100644 index 0000000000..ee58e671c4 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedDispenseBehavior.java @@ -0,0 +1,79 @@ +package com.simibubi.create.api.contraption.dispenser; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.impl.contraption.dispenser.DispenserBehaviorConverter; + +import net.minecraft.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.DispenseItemBehavior; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.DispenserBlock; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +/** + * A parallel to {@link DispenseItemBehavior}, for use by mounted dispensers. + * Create will attempt to wrap existing {@link DispenseItemBehavior}s, but this interface can be used to provide better or fixed behavior. + * @see DefaultMountedDispenseBehavior + * @see MountedProjectileDispenseBehavior + * @see OptionalMountedDispenseBehavior + */ +@FunctionalInterface +public interface MountedDispenseBehavior { + SimpleRegistry REGISTRY = Util.make(() -> { + SimpleRegistry registry = SimpleRegistry.create(); + registry.registerProvider(DispenserBehaviorConverter.INSTANCE); + return registry; + }); + + /** + * Dispense the given stack into the world. + * @param stack the stack to dispense. Safe to modify, behaviors are given a copy + * @param context the MovementContext of the dispenser + * @param pos the BlockPos being visited by the dispenser + * @return the remaining stack after dispensing one item + */ + ItemStack dispense(ItemStack stack, MovementContext context, BlockPos pos); + + // utilities for implementations + + static Vec3 getDispenserNormal(MovementContext ctx) { + Direction facing = ctx.state.getValue(DispenserBlock.FACING); + Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal()); + return ctx.rotation.apply(normal).normalize(); + } + + static Direction getClosestFacingDirection(Vec3 facing) { + return Direction.getNearest(facing.x, facing.y, facing.z); + } + + /** + * Attempt to place an item back into the inventory. This is used in the case of item overflow, such as a stack + * of buckets becoming two separate stacks when one is filled with water. + *

+ * First tries to insert directly into the dispenser inventory. If that fails, it then tries the contraption's + * whole inventory. If that still fails, the stack is dispensed into the world with the default behavior. + * @param stack the stack to store in the inventory + * @param context the MovementContext given to the behavior + * @param pos the position given to the behavior + */ + static void placeItemInInventory(ItemStack stack, MovementContext context, BlockPos pos) { + ItemStack toInsert = stack.copy(); + // try inserting into own inventory first + ItemStack remainder = ItemHandlerHelper.insertItem(context.getItemStorage(), toInsert, false); + if (!remainder.isEmpty()) { + // next, try the whole contraption inventory + CombinedInvWrapper contraption = context.contraption.getStorage().getAllItems(); + ItemStack newRemainder = ItemHandlerHelper.insertItem(contraption, remainder, false); + if (!newRemainder.isEmpty()) { + // if there's *still* something left, dispense into world + DefaultMountedDispenseBehavior.INSTANCE.dispense(remainder, context, pos); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedProjectileDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedProjectileDispenseBehavior.java new file mode 100644 index 0000000000..49a9913ca5 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/MountedProjectileDispenseBehavior.java @@ -0,0 +1,76 @@ +package com.simibubi.create.api.contraption.dispenser; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.foundation.mixin.accessor.AbstractProjectileDispenseBehaviorAccessor; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.PositionImpl; +import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.phys.Vec3; + +/** + * A parallel to {@link AbstractProjectileDispenseBehavior}, providing a base implementation for projectile-shooting behaviors. + */ +public abstract class MountedProjectileDispenseBehavior extends DefaultMountedDispenseBehavior { + @Override + protected ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + double x = pos.getX() + facing.x * .7 + .5; + double y = pos.getY() + facing.y * .7 + .5; + double z = pos.getZ() + facing.z * .7 + .5; + Projectile projectile = this.getProjectile(context.world, x, y, z, stack.copy()); + if (projectile == null) + return stack; + + Vec3 motion = facing.scale(this.getPower()).add(context.motion); + projectile.shoot(motion.x, motion.y, motion.z, (float) motion.length(), this.getUncertainty()); + context.world.addFreshEntity(projectile); + stack.shrink(1); + return stack; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + level.levelEvent(LevelEvent.SOUND_DISPENSER_PROJECTILE_LAUNCH, pos, 0); + } + + @Nullable + protected abstract Projectile getProjectile(Level level, double x, double y, double z, ItemStack stack); + + protected float getUncertainty() { + return 6; + } + + protected float getPower() { + return 1.1f; + } + + /** + * Create a mounted behavior wrapper from a vanilla projectile dispense behavior. + */ + public static MountedDispenseBehavior of(AbstractProjectileDispenseBehavior vanillaBehaviour) { + AbstractProjectileDispenseBehaviorAccessor accessor = (AbstractProjectileDispenseBehaviorAccessor) vanillaBehaviour; + return new MountedProjectileDispenseBehavior() { + @Override + protected Projectile getProjectile(Level level, double x, double y, double z, ItemStack stack) { + return accessor.create$callGetProjectile(level, new PositionImpl(x, y, z), stack); + } + + @Override + protected float getUncertainty() { + return accessor.create$callGetUncertainty(); + } + + @Override + protected float getPower() { + return accessor.create$callGetPower(); + } + }; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/dispenser/OptionalMountedDispenseBehavior.java b/src/main/java/com/simibubi/create/api/contraption/dispenser/OptionalMountedDispenseBehavior.java new file mode 100644 index 0000000000..4be21e7222 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/dispenser/OptionalMountedDispenseBehavior.java @@ -0,0 +1,43 @@ +package com.simibubi.create.api.contraption.dispenser; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.phys.Vec3; + +/** + * A mounted dispenser behavior that might fail, playing the empty sound if it does. + */ +public class OptionalMountedDispenseBehavior extends DefaultMountedDispenseBehavior { + private boolean success; + + @Override + protected final ItemStack execute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + ItemStack remainder = this.doExecute(stack, context, pos, facing); + this.success = remainder != null; + return remainder == null ? stack : remainder; + } + + @Override + protected void playSound(LevelAccessor level, BlockPos pos) { + if (this.success) { + super.playSound(level, pos); + } else { + level.levelEvent(LevelEvent.SOUND_DISPENSER_FAIL, pos, 0); + } + } + + /** + * Dispense the given item. + * @return the remaining items after dispensing one, or null if it failed + */ + @Nullable + protected ItemStack doExecute(ItemStack stack, MovementContext context, BlockPos pos, Vec3 facing) { + return super.execute(stack, context, pos, facing); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/SyncedMountedStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/SyncedMountedStorage.java new file mode 100644 index 0000000000..035ed5d94f --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/SyncedMountedStorage.java @@ -0,0 +1,25 @@ +package com.simibubi.create.api.contraption.storage; + +import com.simibubi.create.content.contraptions.Contraption; + +import net.minecraft.core.BlockPos; + +/** + * Optional interface for mounted storage that is synced with the client. + */ +public interface SyncedMountedStorage { + /** + * @return true if this storage needs to be synced. + */ + boolean isDirty(); + + /** + * Called after this storage has been synced. + */ + void markClean(); + + /** + * Called on the client side after this storage has been synced from the server. + */ + void afterSync(Contraption contraption, BlockPos localPos); +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorage.java new file mode 100644 index 0000000000..449f207afe --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorage.java @@ -0,0 +1,31 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import java.util.Objects; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.capability.IFluidHandler; + +public abstract class MountedFluidStorage implements IFluidHandler { + public static final Codec CODEC = MountedFluidStorageType.CODEC.dispatch( + storage -> storage.type, type -> type.codec + ); + + public final MountedFluidStorageType type; + + protected MountedFluidStorage(MountedFluidStorageType type) { + this.type = Objects.requireNonNull(type); + } + + /** + * Un-mount this storage back into the world. The expected storage type of the target + * block has already been checked to make sure it matches this storage's type. + */ + public abstract void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java new file mode 100644 index 0000000000..c2d91dad13 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java @@ -0,0 +1,39 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.util.entry.RegistryEntry; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class MountedFluidStorageType { + public static final Codec> CODEC = CreateBuiltInRegistries.MOUNTED_FLUID_STORAGE_TYPE.byNameCodec(); + public static final SimpleRegistry> REGISTRY = SimpleRegistry.create(); + + public final Codec codec; + + protected MountedFluidStorageType(Codec codec) { + this.codec = codec; + } + + @Nullable + public abstract T mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); + + /** + * Utility for use with Registrate builders. Creates a builder transformer + * that will register the given MountedFluidStorageType to a block when ready. + */ + public static NonNullUnaryOperator> mountedFluidStorage(RegistryEntry> type) { + return builder -> builder.onRegisterAfter(CreateRegistries.MOUNTED_FLUID_STORAGE_TYPE, block -> REGISTRY.register(block, type.get())); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageWrapper.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageWrapper.java new file mode 100644 index 0000000000..9d983e5395 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageWrapper.java @@ -0,0 +1,20 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import com.google.common.collect.ImmutableMap; +import com.simibubi.create.foundation.fluid.CombinedTankWrapper; + +import net.minecraft.core.BlockPos; +import net.minecraftforge.fluids.capability.IFluidHandler; + +/** + * Wrapper around many MountedFluidStorages, providing access to all of them as one storage. + * They can still be accessed individually through the map. + */ +public class MountedFluidStorageWrapper extends CombinedTankWrapper { + public final ImmutableMap storages; + + public MountedFluidStorageWrapper(ImmutableMap storages) { + super(storages.values().toArray(IFluidHandler[]::new)); + this.storages = storages; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/WrapperMountedFluidStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/WrapperMountedFluidStorage.java new file mode 100644 index 0000000000..63d445f8f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/WrapperMountedFluidStorage.java @@ -0,0 +1,56 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import org.jetbrains.annotations.NotNull; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; + +/** + * Partial implementation of a MountedFluidStorage that wraps a fluid handler. + */ +public abstract class WrapperMountedFluidStorage extends MountedFluidStorage { + protected final T wrapped; + + protected WrapperMountedFluidStorage(MountedFluidStorageType type, T wrapped) { + super(type); + this.wrapped = wrapped; + } + + @Override + public int getTanks() { + return this.wrapped.getTanks(); + } + + @Override + @NotNull + public FluidStack getFluidInTank(int tank) { + return this.wrapped.getFluidInTank(tank); + } + + @Override + public int getTankCapacity(int tank) { + return this.wrapped.getTankCapacity(tank); + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return this.wrapped.isFluidValid(tank, stack); + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + return this.wrapped.fill(resource, action); + } + + @Override + @NotNull + public FluidStack drain(FluidStack resource, FluidAction action) { + return this.wrapped.drain(resource, action); + } + + @Override + @NotNull + public FluidStack drain(int maxDrain, FluidAction action) { + return this.wrapped.drain(maxDrain, action); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java new file mode 100644 index 0000000000..4b7ba3fe74 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java @@ -0,0 +1,130 @@ +package com.simibubi.create.api.contraption.storage.item; + +import java.util.Objects; +import java.util.OptionalInt; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.item.menu.MountedStorageMenus; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.items.IItemHandlerModifiable; + +public abstract class MountedItemStorage implements IItemHandlerModifiable { + public static final Codec CODEC = MountedItemStorageType.CODEC.dispatch( + storage -> storage.type, type -> type.codec + ); + + public final MountedItemStorageType type; + + protected MountedItemStorage(MountedItemStorageType type) { + this.type = Objects.requireNonNull(type); + } + + /** + * Un-mount this storage back into the world. The expected storage type of the target + * block has already been checked to make sure it matches this storage's type. + */ + public abstract void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); + + /** + * Handle a player clicking on this mounted storage. This is always called on the server. + * The default implementation will try to open a generic GUI for standard inventories. + * For this to work, this storage must have 1-6 complete rows of 9 slots. + * @return true if the interaction was successful + */ + public boolean handleInteraction(ServerPlayer player, Contraption contraption, StructureBlockInfo info) { + ServerLevel level = player.serverLevel(); + BlockPos localPos = info.pos(); + Vec3 localPosVec = Vec3.atCenterOf(localPos); + Predicate stillValid = p -> { + Vec3 currentPos = contraption.entity.toGlobalVector(localPosVec, 0); + return this.isMenuValid(player, contraption, currentPos); + }; + Component menuName = this.getMenuName(info, contraption); + IItemHandlerModifiable handler = this.getHandlerForMenu(info, contraption); + Consumer onClose = p -> { + Vec3 newPos = contraption.entity.toGlobalVector(localPosVec, 0); + this.playClosingSound(level, newPos); + }; + + OptionalInt id = player.openMenu(this.createMenuProvider(menuName, handler, stillValid, onClose)); + if (id.isPresent()) { + Vec3 globalPos = contraption.entity.toGlobalVector(localPosVec, 0); + this.playOpeningSound(level, globalPos); + return true; + } else { + return false; + } + } + + /** + * Get the item handler that will be used by this storage's menu. This is useful for + * handling multi-blocks, such as double chests. + */ + protected IItemHandlerModifiable getHandlerForMenu(StructureBlockInfo info, Contraption contraption) { + return this; + } + + /** + * @param player the player who opened the menu + * @param pos the center of this storage in-world + * @return true if a GUI opened for this storage is still valid + */ + protected boolean isMenuValid(ServerPlayer player, Contraption contraption, Vec3 pos) { + return contraption.entity.isAlive() && player.distanceToSqr(pos) < (8 * 8); + } + + /** + * @return the title to be shown in the GUI when this storage is opened + */ + protected Component getMenuName(StructureBlockInfo info, Contraption contraption) { + MutableComponent blockName = info.state().getBlock().getName(); + return CreateLang.translateDirect("contraptions.moving_container", blockName); + } + + /** + * @return a MenuProvider that provides the menu players will see when opening this storage + */ + @Nullable + protected MenuProvider createMenuProvider(Component name, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + return MountedStorageMenus.createGeneric(name, handler, stillValid, onClose); + } + + /** + * Play the sound made by opening this storage's GUI. + */ + protected void playOpeningSound(ServerLevel level, Vec3 pos) { + level.playSound( + null, BlockPos.containing(pos), + SoundEvents.BARREL_OPEN, SoundSource.BLOCKS, + 0.75f, 1f + ); + } + + /** + * Play the sound made by closing this storage's GUI. + */ + protected void playClosingSound(ServerLevel level, Vec3 pos) { + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java new file mode 100644 index 0000000000..a78297d76d --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java @@ -0,0 +1,53 @@ +package com.simibubi.create.api.contraption.storage.item; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.impl.contraption.storage.MountedItemStorageFallbackProvider; +import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.util.entry.RegistryEntry; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; + +import net.minecraft.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class MountedItemStorageType { + public static final Codec> CODEC = CreateBuiltInRegistries.MOUNTED_ITEM_STORAGE_TYPE.byNameCodec(); + public static final SimpleRegistry> REGISTRY = Util.make(() -> { + SimpleRegistry> registry = SimpleRegistry.create(); + registry.registerProvider(MountedItemStorageFallbackProvider.INSTANCE); + return registry; + }); + + public final Codec codec; + public final Holder.Reference> holder; + + protected MountedItemStorageType(Codec codec) { + this.codec = codec; + this.holder = CreateBuiltInRegistries.MOUNTED_ITEM_STORAGE_TYPE.createIntrusiveHolder(this); + } + + public final boolean is(TagKey> tag) { + return this.holder.is(tag); + } + + @Nullable + public abstract T mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); + + /** + * Utility for use with Registrate builders. Creates a builder transformer + * that will register the given MountedItemStorageType to a block when ready. + */ + public static NonNullUnaryOperator> mountedItemStorage(RegistryEntry> type) { + return builder -> builder.onRegisterAfter(CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE, block -> REGISTRY.register(block, type.get())); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageWrapper.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageWrapper.java new file mode 100644 index 0000000000..641d3ea21e --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageWrapper.java @@ -0,0 +1,20 @@ +package com.simibubi.create.api.contraption.storage.item; + +import com.google.common.collect.ImmutableMap; + +import net.minecraft.core.BlockPos; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +/** + * Wrapper around many MountedItemStorages, providing access to all of them as one storage. + * They can still be accessed individually through the map. + */ +public class MountedItemStorageWrapper extends CombinedInvWrapper { + public final ImmutableMap storages; + + public MountedItemStorageWrapper(ImmutableMap storages) { + super(storages.values().toArray(IItemHandlerModifiable[]::new)); + this.storages = storages; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/WrapperMountedItemStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/WrapperMountedItemStorage.java new file mode 100644 index 0000000000..5fb1c1ac51 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/WrapperMountedItemStorage.java @@ -0,0 +1,66 @@ +package com.simibubi.create.api.contraption.storage.item; + +import org.jetbrains.annotations.NotNull; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +/** + * Partial implementation of a MountedItemStorage that wraps an item handler. + */ +public abstract class WrapperMountedItemStorage extends MountedItemStorage { + protected final T wrapped; + + protected WrapperMountedItemStorage(MountedItemStorageType type, T wrapped) { + super(type); + this.wrapped = wrapped; + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + this.wrapped.setStackInSlot(slot, stack); + } + + @Override + public int getSlots() { + return this.wrapped.getSlots(); + } + + @Override + @NotNull + public ItemStack getStackInSlot(int slot) { + return this.wrapped.getStackInSlot(slot); + } + + @Override + @NotNull + public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return this.wrapped.insertItem(slot, stack, simulate); + } + + @Override + @NotNull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + return this.wrapped.extractItem(slot, amount, simulate); + } + + @Override + public int getSlotLimit(int slot) { + return this.wrapped.getSlotLimit(slot); + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return this.wrapped.isItemValid(slot, stack); + } + + public static ItemStackHandler copyToItemStackHandler(IItemHandler handler) { + ItemStackHandler copy = new ItemStackHandler(handler.getSlots()); + for (int i = 0; i < handler.getSlots(); i++) { + copy.setStackInSlot(i, handler.getStackInSlot(i).copy()); + } + return copy; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorage.java new file mode 100644 index 0000000000..31e1f7249c --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorage.java @@ -0,0 +1,111 @@ +package com.simibubi.create.api.contraption.storage.item.chest; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.item.ItemHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.Container; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.ChestType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; +import net.minecraftforge.items.wrapper.InvWrapper; + +/** + * Mounted storage that handles opening a combined GUI for double chests. + */ +public class ChestMountedStorage extends SimpleMountedStorage { + public static final Codec CODEC = SimpleMountedStorage.codec(ChestMountedStorage::new); + + protected ChestMountedStorage(MountedItemStorageType type, IItemHandler handler) { + super(type, handler); + } + + public ChestMountedStorage(IItemHandler handler) { + this(AllMountedStorageTypes.CHEST.get(), handler); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + // the capability will include both sides of chests, but mounted storage is 1:1 + if (be instanceof Container container && this.getSlots() == container.getContainerSize()) { + ItemHelper.copyContents(this, new InvWrapper(container)); + } + } + + @Override + protected IItemHandlerModifiable getHandlerForMenu(StructureBlockInfo info, Contraption contraption) { + BlockState state = info.state(); + ChestType type = state.getValue(ChestBlock.TYPE); + if (type == ChestType.SINGLE) + return this; + + Direction facing = state.getValue(ChestBlock.FACING); + Direction connectedDirection = ChestBlock.getConnectedDirection(state); + BlockPos otherHalfPos = info.pos().relative(connectedDirection); + + MountedItemStorage otherHalf = this.getOtherHalf(contraption, otherHalfPos, state.getBlock(), facing, type); + if (otherHalf == null) + return this; + + if (type == ChestType.RIGHT) { + return new CombinedInvWrapper(this, otherHalf); + } else { + return new CombinedInvWrapper(otherHalf, this); + } + } + + @Nullable + protected MountedItemStorage getOtherHalf(Contraption contraption, BlockPos localPos, Block block, + Direction thisFacing, ChestType thisType) { + StructureBlockInfo info = contraption.getBlocks().get(localPos); + if (info == null) + return null; + BlockState state = info.state(); + if (!state.is(block)) + return null; + + Direction facing = state.getValue(ChestBlock.FACING); + ChestType type = state.getValue(ChestBlock.TYPE); + + return facing == thisFacing && type == thisType.getOpposite() + ? contraption.getStorage().getMountedItems().storages.get(localPos) + : null; + } + + @Override + protected void playOpeningSound(ServerLevel level, Vec3 pos) { + level.playSound( + null, BlockPos.containing(pos), + SoundEvents.CHEST_OPEN, SoundSource.BLOCKS, + 0.75f, 1f + ); + } + + @Override + protected void playClosingSound(ServerLevel level, Vec3 pos) { + level.playSound( + null, BlockPos.containing(pos), + SoundEvents.CHEST_CLOSE, SoundSource.BLOCKS, + 0.75f, 1f + ); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorageType.java new file mode 100644 index 0000000000..e6a6054312 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorageType.java @@ -0,0 +1,25 @@ +package com.simibubi.create.api.contraption.storage.item.chest; + +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorageType; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.wrapper.InvWrapper; +import net.minecraft.world.Container; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class ChestMountedStorageType extends SimpleMountedStorageType { + public ChestMountedStorageType() { + super(ChestMountedStorage.CODEC); + } + + @Override + protected IItemHandler getHandler(BlockEntity be) { + return be instanceof Container container ? new InvWrapper(container) : null; + } + + @Override + protected SimpleMountedStorage createStorage(IItemHandler handler) { + return new ChestMountedStorage(handler); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/MountedStorageMenus.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/MountedStorageMenus.java new file mode 100644 index 0000000000..4da152b688 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/MountedStorageMenus.java @@ -0,0 +1,57 @@ +package com.simibubi.create.api.contraption.storage.item.menu; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.Container; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.DispenserMenu; +import net.minecraft.world.inventory.MenuConstructor; +import net.minecraft.world.inventory.MenuType; + +import net.minecraftforge.items.IItemHandlerModifiable; + +/** + * Methods for creating generic menus usable by mounted storages. + */ +public class MountedStorageMenus { + public static final List> GENERIC_CHEST_MENUS = List.of( + MenuType.GENERIC_9x1, MenuType.GENERIC_9x2, MenuType.GENERIC_9x3, + MenuType.GENERIC_9x4, MenuType.GENERIC_9x5, MenuType.GENERIC_9x6 + ); + + @Nullable + public static MenuProvider createGeneric(Component menuName, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + int rows = handler.getSlots() / 9; + if (rows < 1 || rows > 6) + return null; + + // make sure rows are full + if (handler.getSlots() % 9 != 0) + return null; + + MenuType type = GENERIC_CHEST_MENUS.get(rows - 1); + Container wrapper = new StorageInteractionWrapper(handler, stillValid, onClose); + MenuConstructor constructor = (id, inv, player) -> new ChestMenu(type, id, inv, wrapper, rows); + return new SimpleMenuProvider(constructor, menuName); + } + + @Nullable + public static MenuProvider createGeneric9x9(Component name, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + if (handler.getSlots() != 9) + return null; + + Container wrapper = new StorageInteractionWrapper(handler, stillValid, onClose); + MenuConstructor constructor = (id, inv, player) -> new DispenserMenu(id, inv, wrapper); + return new SimpleMenuProvider(constructor, name); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/StorageInteractionWrapper.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/StorageInteractionWrapper.java new file mode 100644 index 0000000000..d509f81c3c --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/StorageInteractionWrapper.java @@ -0,0 +1,35 @@ +package com.simibubi.create.api.contraption.storage.item.menu; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +import net.minecraft.world.entity.player.Player; + +public class StorageInteractionWrapper extends RecipeWrapper { + private final Predicate stillValid; + private final Consumer onClose; + + public StorageInteractionWrapper(IItemHandlerModifiable inv, Predicate stillValid, Consumer onClose) { + super(inv); + this.stillValid = stillValid; + this.onClose = onClose; + } + + @Override + public boolean stillValid(Player player) { + return this.stillValid.test(player); + } + + @Override + public int getMaxStackSize() { + return 64; + } + + @Override + public void stopOpen(Player player) { + this.onClose.accept(player); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorage.java new file mode 100644 index 0000000000..fce14d1cdd --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorage.java @@ -0,0 +1,76 @@ +package com.simibubi.create.api.contraption.storage.item.simple; + +import java.util.Optional; +import java.util.function.Function; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; + +import com.simibubi.create.AllTags; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.WrapperMountedItemStorage; + +import com.simibubi.create.foundation.utility.CreateCodecs; + +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Widely-applicable mounted storage implementation. + * Gets an item handler from the mounted block, copies it to an ItemStackHandler, + * and then copies the inventory back to the target when unmounting. + * All blocks for which this mounted storage is registered must provide an + * {@link IItemHandlerModifiable} to {@link ForgeCapabilities#ITEM_HANDLER}. + *
+ * To use this implementation, either register {@link AllMountedStorageTypes#SIMPLE} to your block + * manually, or add your block to the {@link AllTags.AllBlockTags#SIMPLE_MOUNTED_STORAGE} tag. + * It is also possible to extend this class to create your own implementation. + */ +public class SimpleMountedStorage extends WrapperMountedItemStorage { + public static final Codec CODEC = codec(SimpleMountedStorage::new); + + public SimpleMountedStorage(MountedItemStorageType type, IItemHandler handler) { + super(type, copyToItemStackHandler(handler)); + } + + public SimpleMountedStorage(IItemHandler handler) { + this(AllMountedStorageTypes.SIMPLE.get(), handler); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be == null) + return; + + be.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve().flatMap(this::validate).ifPresent(handler -> { + for (int i = 0; i < handler.getSlots(); i++) { + handler.setStackInSlot(i, this.getStackInSlot(i)); + } + }); + } + + /** + * Make sure the targeted handler is valid for copying items back into. + * It is highly recommended to call super in overrides. + */ + protected Optional validate(IItemHandler handler) { + if (handler.getSlots() == this.getSlots() && handler instanceof IItemHandlerModifiable modifiable) { + return Optional.of(modifiable); + } else { + return Optional.empty(); + } + } + + public static Codec codec(Function factory) { + return CreateCodecs.ITEM_STACK_HANDLER.xmap(factory, storage -> storage.wrapped); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorageType.java new file mode 100644 index 0000000000..61748939cf --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorageType.java @@ -0,0 +1,49 @@ +package com.simibubi.create.api.contraption.storage.item.simple; + +import java.util.Optional; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import net.minecraftforge.common.capabilities.ForgeCapabilities; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class SimpleMountedStorageType extends MountedItemStorageType { + protected SimpleMountedStorageType(Codec codec) { + super(codec); + } + + @Override + @Nullable + public SimpleMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + return Optional.ofNullable(be) + .map(this::getHandler) + .map(this::createStorage) + .orElse(null); + } + + protected IItemHandler getHandler(BlockEntity be) { + IItemHandler handler = be.getCapability(ForgeCapabilities.ITEM_HANDLER).orElse(null); + // make sure the handler is modifiable so new contents can be moved over on disassembly + return handler instanceof IItemHandlerModifiable modifiable ? modifiable : null; + } + + protected SimpleMountedStorage createStorage(IItemHandler handler) { + return new SimpleMountedStorage(this, handler); + } + + public static final class Impl extends SimpleMountedStorageType { + public Impl() { + super(SimpleMountedStorage.CODEC); + } + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/train/PortalTrackProvider.java b/src/main/java/com/simibubi/create/api/contraption/train/PortalTrackProvider.java new file mode 100644 index 0000000000..39b2beadd5 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/train/PortalTrackProvider.java @@ -0,0 +1,91 @@ +package com.simibubi.create.api.contraption.train; + +import java.util.function.BiFunction; +import java.util.function.Function; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; +import com.simibubi.create.content.trains.track.AllPortalTracks; + +import net.createmod.catnip.math.BlockFace; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.portal.PortalInfo; + +import net.minecraftforge.common.util.ITeleporter; + +/** + * A provider for portal track connections. + * Takes a track inbound through a portal and finds the exit location for the outbound track. + */ +@FunctionalInterface +public interface PortalTrackProvider { + SimpleRegistry REGISTRY = SimpleRegistry.create(); + + /** + * Find the exit location for a track going through a portal. + * @param level the level of the inbound track + * @param face the face of the inbound track + */ + Exit findExit(ServerLevel level, BlockFace face); + + /** + * Checks if a given {@link BlockState} represents a supported portal block. + * @param state The block state to check. + * @return {@code true} if the block state represents a supported portal; {@code false} otherwise. + */ + static boolean isSupportedPortal(BlockState state) { + return REGISTRY.get(state) != null; + } + + /** + * Retrieves the corresponding outbound track on the other side of a portal. + * @param level The current {@link ServerLevel}. + * @param inboundTrack The inbound track {@link BlockFace}. + * @return the found outbound track, or null if one wasn't found. + */ + @Nullable + static Exit getOtherSide(ServerLevel level, BlockFace inboundTrack) { + BlockPos portalPos = inboundTrack.getConnectedPos(); + BlockState portalState = level.getBlockState(portalPos); + PortalTrackProvider provider = REGISTRY.get(portalState); + return provider == null ? null : provider.findExit(level, inboundTrack); + } + + /** + * Find an exit location by using an {@link ITeleporter} instance. + * @param level The level of the inbound track + * @param face The face of the inbound track + * @param firstDimension The first dimension (typically the Overworld) + * @param secondDimension The second dimension (e.g., Nether, Aether) + * @param customPortalForcer A function to obtain the {@link ITeleporter} for the target level + * @return A found exit, or null if one wasn't found + */ + static Exit fromTeleporter(ServerLevel level, BlockFace face, ResourceKey firstDimension, + ResourceKey secondDimension, Function customPortalForcer) { + return AllPortalTracks.fromTeleporter(level, face, firstDimension, secondDimension, customPortalForcer); + } + + /** + * Find an exit location by teleporting a probe entity to find a {@link PortalInfo}. + * @param level The level of the inbound track + * @param face The face of the inbound track + * @param firstDimension The first dimension + * @param secondDimension The second dimension + * @param portalInfoProvider A function that provides the {@link PortalInfo} given the target level and probe entity. + * @return A found exit, or null if one wasn't found + */ + static Exit fromProbe(ServerLevel level, BlockFace face, ResourceKey firstDimension, + ResourceKey secondDimension, BiFunction portalInfoProvider) { + return AllPortalTracks.fromProbe(level, face, firstDimension, secondDimension, portalInfoProvider); + } + + record Exit(ServerLevel level, BlockFace face) { + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java b/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java deleted file mode 100644 index 05cd1e09e3..0000000000 --- a/src/main/java/com/simibubi/create/api/contraption/train/TrainConductorHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.api.contraption.train; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllInteractionBehaviours; -import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; - -import com.simibubi.create.content.processing.burner.BlockBasedTrainConductorInteractionBehaviour; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.state.BlockState; - - -import org.jetbrains.annotations.ApiStatus; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Predicate; - - -/** - * All required methods to make your block a train conductor similar to the blaze burner - */ -public interface TrainConductorHandler { - - @ApiStatus.Internal - List CONDUCTOR_HANDLERS = new ArrayList<>(); - - - - boolean isValidConductor(BlockState state); - - private static void registerHandler(TrainConductorHandler handler) { - CONDUCTOR_HANDLERS.add(handler); - } - - static void registerConductor(ResourceLocation blockRl, Predicate isValidConductor, UpdateScheduleCallback updateScheduleCallback) { - AllInteractionBehaviours.registerBehaviour(blockRl, new BlockBasedTrainConductorInteractionBehaviour(isValidConductor, updateScheduleCallback)); - registerHandler(isValidConductor::test); - } - - @ApiStatus.Internal - static void registerBlazeBurner() { - registerConductor(AllBlocks.BLAZE_BURNER.getId(), blockState -> AllBlocks.BLAZE_BURNER.has(blockState) - && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != BlazeBurnerBlock.HeatLevel.NONE, UpdateScheduleCallback.EMPTY); - } - - interface UpdateScheduleCallback { - - UpdateScheduleCallback EMPTY = (hasSchedule, blockState, blockStateSetter) -> {}; - - void update(boolean hasSchedule, BlockState currentBlockState, Consumer blockStateSetter); - } -} diff --git a/src/main/java/com/simibubi/create/api/contraption/transformable/MovedBlockTransformerRegistries.java b/src/main/java/com/simibubi/create/api/contraption/transformable/MovedBlockTransformerRegistries.java new file mode 100644 index 0000000000..c9f4142970 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/transformable/MovedBlockTransformerRegistries.java @@ -0,0 +1,28 @@ +package com.simibubi.create.api.contraption.transformable; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.contraptions.StructureTransform; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Registry for custom transformations to apply to blocks after they've been moved by a contraption. + * These interfaces are alternatives to the {@link TransformableBlock} and {@link TransformableBlockEntity} interfaces. + */ +public class MovedBlockTransformerRegistries { + public static final SimpleRegistry BLOCK_TRANSFORMERS = SimpleRegistry.create(); + public static final SimpleRegistry, BlockEntityTransformer> BLOCK_ENTITY_TRANSFORMERS = SimpleRegistry.create(); + + @FunctionalInterface + public interface BlockTransformer { + BlockState transform(BlockState state, StructureTransform transform); + } + + @FunctionalInterface + public interface BlockEntityTransformer { + void transform(BlockEntity be, StructureTransform transform); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/transformable/TransformableBlock.java b/src/main/java/com/simibubi/create/api/contraption/transformable/TransformableBlock.java new file mode 100644 index 0000000000..15d7d5fa26 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/transformable/TransformableBlock.java @@ -0,0 +1,10 @@ +package com.simibubi.create.api.contraption.transformable; + +import com.simibubi.create.content.contraptions.StructureTransform; + +import net.minecraft.world.level.block.state.BlockState; + +@FunctionalInterface +public interface TransformableBlock { + BlockState transform(BlockState state, StructureTransform transform); +} diff --git a/src/main/java/com/simibubi/create/api/contraption/transformable/TransformableBlockEntity.java b/src/main/java/com/simibubi/create/api/contraption/transformable/TransformableBlockEntity.java new file mode 100644 index 0000000000..d7182381b4 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/transformable/TransformableBlockEntity.java @@ -0,0 +1,9 @@ +package com.simibubi.create.api.contraption.transformable; + +import com.simibubi.create.content.contraptions.StructureTransform; + +import net.minecraft.world.level.block.entity.BlockEntity; + +public interface TransformableBlockEntity { + void transform(BlockEntity blockEntity, StructureTransform transform); +} diff --git a/src/main/java/com/simibubi/create/api/data/TrainHatInfoProvider.java b/src/main/java/com/simibubi/create/api/data/TrainHatInfoProvider.java index 95ec9efd48..0ed91ec8d1 100644 --- a/src/main/java/com/simibubi/create/api/data/TrainHatInfoProvider.java +++ b/src/main/java/com/simibubi/create/api/data/TrainHatInfoProvider.java @@ -1,9 +1,12 @@ package com.simibubi.create.api.data; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + import com.mojang.serialization.JsonOps; import com.simibubi.create.Create; import com.simibubi.create.content.trains.schedule.hat.TrainHatInfo; - import com.simibubi.create.content.trains.schedule.hat.TrainHatInfoReloadListener; import net.minecraft.data.CachedOutput; @@ -14,13 +17,9 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.phys.Vec3; import net.minecraftforge.registries.ForgeRegistries; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - public abstract class TrainHatInfoProvider implements DataProvider { - private final PackOutput.PathProvider path; protected final Map trainHatOffsets = new HashMap<>(); + private final PackOutput.PathProvider path; public TrainHatInfoProvider(PackOutput output) { this.path = output.createPathProvider(PackOutput.Target.RESOURCE_PACK, TrainHatInfoReloadListener.HAT_INFO_DIRECTORY); @@ -53,11 +52,11 @@ public abstract class TrainHatInfoProvider implements DataProvider { this.trainHatOffsets.clear(); this.createOffsets(); return CompletableFuture.allOf( - this.trainHatOffsets.entrySet().stream().map(entry -> - DataProvider.saveStable(output, - TrainHatInfo.CODEC.encodeStart(JsonOps.INSTANCE, entry.getValue()).resultOrPartial(Create.LOGGER::error).orElseThrow(), - this.path.json(entry.getKey())) - ).toArray(CompletableFuture[]::new)); + this.trainHatOffsets.entrySet().stream().map(entry -> + DataProvider.saveStable(output, + TrainHatInfo.CODEC.encodeStart(JsonOps.INSTANCE, entry.getValue()).resultOrPartial(Create.LOGGER::error).orElseThrow(), + this.path.json(entry.getKey())) + ).toArray(CompletableFuture[]::new)); } @Override diff --git a/src/main/java/com/simibubi/create/api/effect/OpenPipeEffectHandler.java b/src/main/java/com/simibubi/create/api/effect/OpenPipeEffectHandler.java new file mode 100644 index 0000000000..ea772eb142 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/effect/OpenPipeEffectHandler.java @@ -0,0 +1,28 @@ +package com.simibubi.create.api.effect; + +import com.simibubi.create.api.registry.SimpleRegistry; + +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +import net.minecraftforge.fluids.FluidStack; + +/** + * Interface for custom behavior for fluids spilling out of open pipes. Examples: + *

    + *
  • Potions: applying potion effects
  • + *
  • Milk: clearing effects
  • + *
  • Water: extinguishing fire
  • + *
+ */ +@FunctionalInterface +public interface OpenPipeEffectHandler { + SimpleRegistry REGISTRY = SimpleRegistry.create(); + + /** + * @param area the area to apply effects in + * @param fluid the fluid in the pipe. Do not modify, it will do nothing + */ + void apply(Level level, AABB area, FluidStack fluid); +} diff --git a/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveCustomOverlayIcon.java b/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveCustomOverlayIcon.java new file mode 100644 index 0000000000..fb75545547 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveCustomOverlayIcon.java @@ -0,0 +1,18 @@ +package com.simibubi.create.api.equipment.goggles; + +import com.simibubi.create.AllItems; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; + +public sealed interface IHaveCustomOverlayIcon permits IHaveGoggleInformation, IHaveHoveringInformation { + /** + * This method will be called when looking at a {@link BlockEntity} that implements {@link IHaveGoggleInformation} + * or {@link IHaveHoveringInformation} + * + * @return The {@link ItemStack} you want the overlay to show instead of the goggles + */ + default ItemStack getIcon(boolean isPlayerSneaking) { + return AllItems.GOGGLES.asStack(); + } +} diff --git a/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveGoggleInformation.java b/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveGoggleInformation.java new file mode 100644 index 0000000000..270c955b2b --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveGoggleInformation.java @@ -0,0 +1,87 @@ +package com.simibubi.create.api.equipment.goggles; + +import java.util.List; +import java.util.Optional; + +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.lang.LangBuilder; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.block.entity.BlockEntity; + +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; + +/** + * Implement this interface on the {@link BlockEntity} that wants to add info to the goggle overlay + */ +public non-sealed interface IHaveGoggleInformation extends IHaveCustomOverlayIcon { + /** + * This method will be called when looking at a {@link BlockEntity} that implements this interface + * + * @return {@code true} if the tooltip creation was successful and should be + * displayed, or {@code false} if the overlay should not be displayed + */ + default boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + return false; + } + + default boolean containedFluidTooltip(List tooltip, boolean isPlayerSneaking, + LazyOptional handler) { + Optional resolve = handler.resolve(); + if (!resolve.isPresent()) + return false; + + IFluidHandler tank = resolve.get(); + if (tank.getTanks() == 0) + return false; + + LangBuilder mb = CreateLang.translate("generic.unit.millibuckets"); + CreateLang.translate("gui.goggles.fluid_container") + .forGoggles(tooltip); + + boolean isEmpty = true; + for (int i = 0; i < tank.getTanks(); i++) { + FluidStack fluidStack = tank.getFluidInTank(i); + if (fluidStack.isEmpty()) + continue; + + CreateLang.fluidName(fluidStack) + .style(ChatFormatting.GRAY) + .forGoggles(tooltip, 1); + + CreateLang.builder() + .add(CreateLang.number(fluidStack.getAmount()) + .add(mb) + .style(ChatFormatting.GOLD)) + .text(ChatFormatting.GRAY, " / ") + .add(CreateLang.number(tank.getTankCapacity(i)) + .add(mb) + .style(ChatFormatting.DARK_GRAY)) + .forGoggles(tooltip, 1); + + isEmpty = false; + } + + if (tank.getTanks() > 1) { + if (isEmpty) + tooltip.remove(tooltip.size() - 1); + return true; + } + + if (!isEmpty) + return true; + + CreateLang.translate("gui.goggles.fluid_container.capacity") + .add(CreateLang.number(tank.getTankCapacity(0)) + .add(mb) + .style(ChatFormatting.GOLD)) + .style(ChatFormatting.GRAY) + .forGoggles(tooltip, 1); + + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveHoveringInformation.java b/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveHoveringInformation.java new file mode 100644 index 0000000000..bb89af6824 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/goggles/IHaveHoveringInformation.java @@ -0,0 +1,21 @@ +package com.simibubi.create.api.equipment.goggles; + +import java.util.List; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.block.entity.BlockEntity; + +/** + * Implement this interface on the {@link BlockEntity} that wants to add info to the hovering overlay + */ +public non-sealed interface IHaveHoveringInformation extends IHaveCustomOverlayIcon { + /** + * This method will be called when looking at a {@link BlockEntity} that implements this interface + * + * @return {@code true} if the tooltip creation was successful and should be + * displayed, or {@code false} if the overlay should not be displayed + */ + default boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + return false; + } +} diff --git a/src/main/java/com/simibubi/create/api/equipment/goggles/IProxyHoveringInformation.java b/src/main/java/com/simibubi/create/api/equipment/goggles/IProxyHoveringInformation.java new file mode 100644 index 0000000000..ba2697fa78 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/goggles/IProxyHoveringInformation.java @@ -0,0 +1,13 @@ +package com.simibubi.create.api.equipment.goggles; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Implement this interface on the {@link BlockEntity} that wants proxy the information + */ +public interface IProxyHoveringInformation { + BlockPos getInformationSource(Level level, BlockPos pos, BlockState state); +} diff --git a/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoCannonProjectileType.java b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoCannonProjectileType.java new file mode 100644 index 0000000000..3f237eab92 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoCannonProjectileType.java @@ -0,0 +1,207 @@ +package com.simibubi.create.api.equipment.potatoCannon; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileEntityHitAction.Type; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileRenderModes.Billboard; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileRenderModes.TowardMotion; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileRenderModes.Tumble; + +import net.minecraft.core.Holder; +import net.minecraft.core.Holder.Reference; +import net.minecraft.core.HolderSet; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.RegistryCodecs; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; + +public record PotatoCannonProjectileType(HolderSet items, int reloadTicks, int damage, int split, float knockback, + float drag, float velocityMultiplier, float gravityMultiplier, + float soundPitch, boolean sticky, ItemStack dropStack, + PotatoProjectileRenderMode renderMode, + Optional preEntityHit, + Optional onEntityHit, + Optional onBlockHit) { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + RegistryCodecs.homogeneousList(Registries.ITEM).fieldOf("items").forGetter(PotatoCannonProjectileType::items), + Codec.INT.optionalFieldOf("reload_ticks", 10).forGetter(PotatoCannonProjectileType::reloadTicks), + Codec.INT.optionalFieldOf("damage", 1).forGetter(PotatoCannonProjectileType::damage), + Codec.INT.optionalFieldOf("split", 1).forGetter(PotatoCannonProjectileType::split), + Codec.FLOAT.optionalFieldOf("knockback", 1f).forGetter(PotatoCannonProjectileType::knockback), + Codec.FLOAT.optionalFieldOf("drag", .99f).forGetter(PotatoCannonProjectileType::drag), + Codec.FLOAT.optionalFieldOf("velocity_multiplier", 1f).forGetter(PotatoCannonProjectileType::velocityMultiplier), + Codec.FLOAT.optionalFieldOf("gravity_multiplier", 1f).forGetter(PotatoCannonProjectileType::gravityMultiplier), + Codec.FLOAT.optionalFieldOf("sound_pitch", 1f).forGetter(PotatoCannonProjectileType::soundPitch), + Codec.BOOL.optionalFieldOf("sticky", false).forGetter(PotatoCannonProjectileType::sticky), + ItemStack.CODEC.optionalFieldOf("drop_stack", ItemStack.EMPTY).forGetter(PotatoCannonProjectileType::dropStack), + PotatoProjectileRenderMode.CODEC.optionalFieldOf("render_mode", Billboard.INSTANCE).forGetter(PotatoCannonProjectileType::renderMode), + PotatoProjectileEntityHitAction.CODEC.optionalFieldOf("pre_entity_hit").forGetter(p -> p.preEntityHit), + PotatoProjectileEntityHitAction.CODEC.optionalFieldOf("on_entity_hit").forGetter(p -> p.onEntityHit), + PotatoProjectileBlockHitAction.CODEC.optionalFieldOf("on_block_hit").forGetter(p -> p.onBlockHit) + ).apply(i, PotatoCannonProjectileType::new)); + + public static Optional> getTypeForItem(RegistryAccess registryAccess, Item item) { + // Cache this if it causes performance issues, but it probably won't + return registryAccess.lookupOrThrow(CreateRegistries.POTATO_PROJECTILE_TYPE) + .listElements() + .filter(ref -> ref.value().items.contains(item.builtInRegistryHolder())) + .findFirst(); + } + + public boolean preEntityHit(ItemStack stack, EntityHitResult ray) { + return preEntityHit.map(i -> i.execute(stack, ray, Type.PRE_HIT)).orElse(false); + } + + public boolean onEntityHit(ItemStack stack, EntityHitResult ray) { + return onEntityHit.map(i -> i.execute(stack, ray, Type.ON_HIT)).orElse(false); + } + + public boolean onBlockHit(LevelAccessor level, ItemStack stack, BlockHitResult ray) { + return onBlockHit.map(i -> i.execute(level, stack, ray)).orElse(false); + } + + // Copy the stack so it's not mutated and lost + @Override + public ItemStack dropStack() { + return dropStack.copy(); + } + + public static class Builder { + private final List> items = new ArrayList<>(); + private int reloadTicks = 10; + private int damage = 1; + private int split = 1; + private float knockback = 1f; + private float drag = 0.99f; + private float velocityMultiplier = 1f; + private float gravityMultiplier = 1f; + private float soundPitch = 1f; + private boolean sticky = false; + private ItemStack dropStack = ItemStack.EMPTY; + private PotatoProjectileRenderMode renderMode = Billboard.INSTANCE; + private PotatoProjectileEntityHitAction preEntityHit = null; + private PotatoProjectileEntityHitAction onEntityHit = null; + private PotatoProjectileBlockHitAction onBlockHit = null; + + public Builder reloadTicks(int reload) { + this.reloadTicks = reload; + return this; + } + + public Builder damage(int damage) { + this.damage = damage; + return this; + } + + public Builder splitInto(int split) { + this.split = split; + return this; + } + + public Builder knockback(float knockback) { + this.knockback = knockback; + return this; + } + + public Builder drag(float drag) { + this.drag = drag; + return this; + } + + public Builder velocity(float velocity) { + this.velocityMultiplier = velocity; + return this; + } + + public Builder gravity(float modifier) { + this.gravityMultiplier = modifier; + return this; + } + + public Builder soundPitch(float pitch) { + this.soundPitch = pitch; + return this; + } + + public Builder sticky() { + this.sticky = true; + return this; + } + + public Builder dropStack(ItemStack stack) { + this.dropStack = stack; + return this; + } + + public Builder renderMode(PotatoProjectileRenderMode renderMode) { + this.renderMode = renderMode; + return this; + } + + public Builder renderBillboard() { + renderMode(Billboard.INSTANCE); + return this; + } + + public Builder renderTumbling() { + renderMode(Tumble.INSTANCE); + return this; + } + + public Builder renderTowardMotion(int spriteAngle, float spin) { + renderMode(new TowardMotion(spriteAngle, spin)); + return this; + } + + public Builder preEntityHit(PotatoProjectileEntityHitAction entityHitAction) { + this.preEntityHit = entityHitAction; + return this; + } + + public Builder onEntityHit(PotatoProjectileEntityHitAction entityHitAction) { + this.onEntityHit = entityHitAction; + return this; + } + + public Builder onBlockHit(PotatoProjectileBlockHitAction blockHitAction) { + this.onBlockHit = blockHitAction; + return this; + } + + public Builder addItems(ItemLike... items) { + for (ItemLike provider : items) + this.items.add(provider.asItem().builtInRegistryHolder()); + return this; + } + + public PotatoCannonProjectileType build() { + return new PotatoCannonProjectileType( + HolderSet.direct(items), + reloadTicks, + damage, + split, + knockback, + drag, + velocityMultiplier, + gravityMultiplier, + soundPitch, + sticky, + dropStack, + renderMode, + Optional.ofNullable(preEntityHit), + Optional.ofNullable(onEntityHit), + Optional.ofNullable(onBlockHit) + ); + } + } +} diff --git a/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileBlockHitAction.java b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileBlockHitAction.java new file mode 100644 index 0000000000..effc988e58 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileBlockHitAction.java @@ -0,0 +1,19 @@ +package com.simibubi.create.api.equipment.potatoCannon; + +import java.util.function.Function; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.phys.BlockHitResult; + +public interface PotatoProjectileBlockHitAction { + Codec CODEC = CreateBuiltInRegistries.POTATO_PROJECTILE_BLOCK_HIT_ACTION.byNameCodec() + .dispatch(PotatoProjectileBlockHitAction::codec, Function.identity()); + + boolean execute(LevelAccessor level, ItemStack projectile, BlockHitResult ray); + + Codec codec(); +} diff --git a/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileEntityHitAction.java b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileEntityHitAction.java new file mode 100644 index 0000000000..9c9106f07e --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileEntityHitAction.java @@ -0,0 +1,27 @@ +package com.simibubi.create.api.equipment.potatoCannon; + +import java.util.function.Function; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.EntityHitResult; + +public interface PotatoProjectileEntityHitAction { + Codec CODEC = CreateBuiltInRegistries.POTATO_PROJECTILE_ENTITY_HIT_ACTION.byNameCodec() + .dispatch(PotatoProjectileEntityHitAction::codec, Function.identity()); + + enum Type { + PRE_HIT, + ON_HIT + } + + /** + * @return true if the hit should be canceled if the type is {@link Type#PRE_HIT PRE_HIT}, + * true if this shouldn't recover the projectile if the type is {@link Type#ON_HIT ON_HIT} + */ + boolean execute(ItemStack projectile, EntityHitResult ray, Type type); + + Codec codec(); +} diff --git a/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileRenderMode.java b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileRenderMode.java new file mode 100644 index 0000000000..e0611dde20 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/equipment/potatoCannon/PotatoProjectileRenderMode.java @@ -0,0 +1,21 @@ +package com.simibubi.create.api.equipment.potatoCannon; + +import java.util.function.Function; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.serialization.Codec; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileEntity; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface PotatoProjectileRenderMode { + Codec CODEC = CreateBuiltInRegistries.POTATO_PROJECTILE_RENDER_MODE.byNameCodec() + .dispatch(PotatoProjectileRenderMode::codec, Function.identity()); + + @OnlyIn(Dist.CLIENT) + void transform(PoseStack ms, PotatoProjectileEntity entity, float pt); + + Codec codec(); +} diff --git a/src/main/java/com/simibubi/create/api/event/BlockEntityBehaviourEvent.java b/src/main/java/com/simibubi/create/api/event/BlockEntityBehaviourEvent.java index 398783d74a..b0154691eb 100644 --- a/src/main/java/com/simibubi/create/api/event/BlockEntityBehaviourEvent.java +++ b/src/main/java/com/simibubi/create/api/event/BlockEntityBehaviourEvent.java @@ -26,8 +26,8 @@ import net.minecraftforge.eventbus.api.GenericEvent; */ public class BlockEntityBehaviourEvent extends GenericEvent { - private T smartBlockEntity; - private Map, BlockEntityBehaviour> behaviours; + private final T smartBlockEntity; + private final Map, BlockEntityBehaviour> behaviours; public BlockEntityBehaviourEvent(T blockEntity, Map, BlockEntityBehaviour> behaviours) { smartBlockEntity = blockEntity; diff --git a/src/main/java/com/simibubi/create/api/event/PipeCollisionEvent.java b/src/main/java/com/simibubi/create/api/event/PipeCollisionEvent.java index 995199c02c..753f15ebca 100644 --- a/src/main/java/com/simibubi/create/api/event/PipeCollisionEvent.java +++ b/src/main/java/com/simibubi/create/api/event/PipeCollisionEvent.java @@ -18,15 +18,14 @@ import net.minecraftforge.eventbus.api.Event; */ public class PipeCollisionEvent extends Event { + protected final Fluid firstFluid, secondFluid; private final Level level; private final BlockPos pos; - protected final Fluid firstFluid, secondFluid; - @Nullable private BlockState state; protected PipeCollisionEvent(Level level, BlockPos pos, Fluid firstFluid, Fluid secondFluid, - @Nullable BlockState defaultState) { + @Nullable BlockState defaultState) { this.level = level; this.pos = pos; this.firstFluid = firstFluid; diff --git a/src/main/java/com/simibubi/create/api/event/TrackGraphMergeEvent.java b/src/main/java/com/simibubi/create/api/event/TrackGraphMergeEvent.java index d48e2a3a79..137f8f4f53 100644 --- a/src/main/java/com/simibubi/create/api/event/TrackGraphMergeEvent.java +++ b/src/main/java/com/simibubi/create/api/event/TrackGraphMergeEvent.java @@ -4,18 +4,19 @@ import com.simibubi.create.content.trains.graph.TrackGraph; import net.minecraftforge.eventbus.api.Event; -public class TrackGraphMergeEvent extends Event{ - private TrackGraph mergedInto, mergedFrom; - +public class TrackGraphMergeEvent extends Event { + private final TrackGraph mergedInto; + private final TrackGraph mergedFrom; + public TrackGraphMergeEvent(TrackGraph from, TrackGraph into) { mergedInto = into; mergedFrom = from; } - + public TrackGraph getGraphMergedInto() { return mergedInto; } - + public TrackGraph getGraphMergedFrom() { return mergedFrom; } diff --git a/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java b/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java new file mode 100644 index 0000000000..57039384c8 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/registry/CreateBuiltInRegistries.java @@ -0,0 +1,64 @@ +package com.simibubi.create.api.registry; + +import org.jetbrains.annotations.ApiStatus; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.Lifecycle; +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplayTarget; +import com.simibubi.create.api.contraption.ContraptionType; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileBlockHitAction; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileEntityHitAction; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileRenderMode; +import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointType; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; +import com.simibubi.create.foundation.mixin.accessor.BuiltInRegistriesAccessor; + +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.core.WritableRegistry; +import net.minecraft.resources.ResourceKey; + +/** + * Static registries added by Create. + * + * @see CreateRegistries + */ +public class CreateBuiltInRegistries { + public static final Registry ARM_INTERACTION_POINT_TYPE = simple(CreateRegistries.ARM_INTERACTION_POINT_TYPE); + public static final Registry FAN_PROCESSING_TYPE = simple(CreateRegistries.FAN_PROCESSING_TYPE); + public static final Registry ITEM_ATTRIBUTE_TYPE = simple(CreateRegistries.ITEM_ATTRIBUTE_TYPE); + public static final Registry DISPLAY_SOURCE = simple(CreateRegistries.DISPLAY_SOURCE); + public static final Registry DISPLAY_TARGET = simple(CreateRegistries.DISPLAY_TARGET); + public static final Registry> MOUNTED_ITEM_STORAGE_TYPE = withIntrusiveHolders(CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE); + public static final Registry> MOUNTED_FLUID_STORAGE_TYPE = simple(CreateRegistries.MOUNTED_FLUID_STORAGE_TYPE); + public static final Registry CONTRAPTION_TYPE = withIntrusiveHolders(CreateRegistries.CONTRAPTION_TYPE); + public static final Registry> POTATO_PROJECTILE_RENDER_MODE = simple(CreateRegistries.POTATO_PROJECTILE_RENDER_MODE); + public static final Registry> POTATO_PROJECTILE_ENTITY_HIT_ACTION = simple(CreateRegistries.POTATO_PROJECTILE_ENTITY_HIT_ACTION); + public static final Registry> POTATO_PROJECTILE_BLOCK_HIT_ACTION = simple(CreateRegistries.POTATO_PROJECTILE_BLOCK_HIT_ACTION); + + private static Registry simple(ResourceKey> key) { + return register(key, new MappedRegistry<>(key, Lifecycle.stable(), false)); + } + + private static Registry withIntrusiveHolders(ResourceKey> key) { + return register(key, new MappedRegistry<>(key, Lifecycle.stable(), true)); + } + + @SuppressWarnings("unchecked") + private static Registry register(ResourceKey> key, WritableRegistry registry) { + BuiltInRegistriesAccessor.create$getWRITABLE_REGISTRY().register( + (ResourceKey>) (Object) key, registry, Lifecycle.stable() + ); + return registry; + } + + @ApiStatus.Internal + public static void init() { + // make sure the class is loaded. + // this method is called at the tail of BuiltInRegistries, injected by BuiltInRegistriesMixin. + } +} diff --git a/src/main/java/com/simibubi/create/api/registry/CreateRegistries.java b/src/main/java/com/simibubi/create/api/registry/CreateRegistries.java new file mode 100644 index 0000000000..73efe5aed1 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/registry/CreateRegistries.java @@ -0,0 +1,43 @@ +package com.simibubi.create.api.registry; + +import com.mojang.serialization.Codec; +import com.simibubi.create.Create; +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplayTarget; +import com.simibubi.create.api.contraption.ContraptionType; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileBlockHitAction; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileEntityHitAction; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileRenderMode; +import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointType; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; + +/** + * Keys for registries added by Create. + * + * @see CreateBuiltInRegistries + */ +public class CreateRegistries { + public static final ResourceKey> ARM_INTERACTION_POINT_TYPE = key("arm_interaction_point_type"); + public static final ResourceKey> FAN_PROCESSING_TYPE = key("fan_processing_type"); + public static final ResourceKey> ITEM_ATTRIBUTE_TYPE = key("item_attribute_type"); + public static final ResourceKey> DISPLAY_SOURCE = key("display_source"); + public static final ResourceKey> DISPLAY_TARGET = key("display_target"); + public static final ResourceKey>> MOUNTED_ITEM_STORAGE_TYPE = key("mounted_item_storage_type"); + public static final ResourceKey>> MOUNTED_FLUID_STORAGE_TYPE = key("mounted_fluid_storage_type"); + public static final ResourceKey> CONTRAPTION_TYPE = key("contraption_type"); + public static final ResourceKey> POTATO_PROJECTILE_TYPE = key("potato_projectile/type"); + public static final ResourceKey>> POTATO_PROJECTILE_RENDER_MODE = key("potato_projectile/render_mode"); + public static final ResourceKey>> POTATO_PROJECTILE_ENTITY_HIT_ACTION = key("potato_projectile/entity_hit_action"); + public static final ResourceKey>> POTATO_PROJECTILE_BLOCK_HIT_ACTION = key("potato_projectile/block_hit_action"); + + private static ResourceKey> key(String name) { + return ResourceKey.createRegistryKey(Create.asResource(name)); + } +} diff --git a/src/main/java/com/simibubi/create/api/registry/SimpleRegistry.java b/src/main/java/com/simibubi/create/api/registry/SimpleRegistry.java new file mode 100644 index 0000000000..34131bfe53 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/registry/SimpleRegistry.java @@ -0,0 +1,167 @@ +package com.simibubi.create.api.registry; + +import java.util.List; +import java.util.function.Function; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.impl.registry.SimpleRegistryImpl; +import com.simibubi.create.impl.registry.TagProviderImpl; + +import net.minecraft.core.Holder; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.StateHolder; +import net.minecraft.world.level.material.Fluid; + +/** + * A simple registry mapping between objects with identity semantics. + * Provides simple registration functionality, as well as lazy providers. + * This class is thread-safe, and may be safely used during parallel mod init. + */ +@ApiStatus.NonExtendable +public interface SimpleRegistry { + /** + * Register an association between a key and a value. + * Direct registrations here always take priority over providers. + * @throws IllegalArgumentException if the object already has an associated value + */ + void register(K object, V value); + + /** + * Add a new provider to this registry. For information on providers, see {@link Provider}. + * @throws IllegalArgumentException if the provider has already been registered to this registry + */ + void registerProvider(Provider provider); + + /** + * Invalidate the cached values provided by all providers, so they get re-computed on the next query. + * This should be called by providers when something changes that would affect their results, such as + * a resource reload in the case of providers based on tags. + */ + void invalidate(); + + /** + * Query the value associated with the given object. May be null if no association is present. + */ + @Nullable + V get(K object); + + /** + * Shortcut for {@link #get(Object)} that accepts a StateHolder, such as BlockState or FluidState. + */ + @Nullable + V get(StateHolder state); + + static SimpleRegistry create() { + return SimpleRegistryImpl.single(); + } + + /** + * A provider can provide values to the registry in a lazy fashion. When a key does not have an + * associated value, all providers will be queried in reverse-registration order (newest first). + *

+ * The values returned by providers are cached so that repeated queries always return the same value. + * To invalidate the cache of a registry, call {@link SimpleRegistry#invalidate()}. + */ + @FunctionalInterface + interface Provider { + @Nullable + V get(K object); + + /** + * Called by the SimpleRegistry this provider is registered to after it's registered. + * This is useful for behavior that should only happen if a provider is actually registered, + * such as registering event listeners. + */ + default void onRegister(Runnable invalidate) { + } + + // factory methods for common Providers + + /** + * Create a provider that will return the same value for all entries in a tag. + * The Provider will invalidate itself when tags are reloaded. + */ + static Provider forTag(TagKey tag, Function> holderGetter, V value) { + return new TagProviderImpl<>(tag, holderGetter, value); + } + + /** + * Shortcut for {@link #forTag} when the registry's type is Block. + */ + @SuppressWarnings("deprecation") + static Provider forBlockTag(TagKey tag, V value) { + return new TagProviderImpl<>(tag, Block::builtInRegistryHolder, value); + } + + /** + * Shortcut for {@link #forTag} when the registry's type is BlockEntityType. + */ + static Provider, V> forBlockEntityTag(TagKey> tag, V value) { + return new TagProviderImpl<>(tag, TagProviderImpl::getBeHolder, value); + } + + /** + * Shortcut for {@link #forTag} when the registry's type is Item. + */ + @SuppressWarnings("deprecation") + static Provider forItemTag(TagKey tag, V value) { + return new TagProviderImpl<>(tag, Item::builtInRegistryHolder, value); + } + + /** + * Shortcut for {@link #forTag} when the registry's type is EntityType. + */ + @SuppressWarnings("deprecation") + static Provider, V> forEntityTag(TagKey> tag, V value) { + return new TagProviderImpl<>(tag, EntityType::builtInRegistryHolder, value); + } + + /** + * Shortcut for {@link #forTag} when the registry's type is Fluid. + */ + @SuppressWarnings("deprecation") + static Provider forFluidTag(TagKey tag, V value) { + return new TagProviderImpl<>(tag, Fluid::builtInRegistryHolder, value); + } + } + + /** + * An extension of SimpleRegistry that handles multiple registrations per object. + * {@link #register(Object, Object)} Will set a whole list of registrations - use {@link #add(Object, Object)} to add one. + * Here, all Providers are always queried, and all of their results are returned. Their provided values are also + * provided on top of explicit registrations - they do not take priority. + */ + interface Multi extends SimpleRegistry> { + void add(K object, V value); + + /** + * Shortcut that wraps a single-value provider into one that provides a List. + */ + void addProvider(Provider provider); + + /** + * Never returns null, will return an empty list if no registrations are present + */ + @Override + @NotNull + List get(K object); + + /** + * Never returns null, will return an empty list if no registrations are present + */ + @Override + @NotNull + List get(StateHolder state); + + static Multi create() { + return SimpleRegistryImpl.multi(); + } + } +} diff --git a/src/main/java/com/simibubi/create/api/registry/registrate/SimpleBuilder.java b/src/main/java/com/simibubi/create/api/registry/registrate/SimpleBuilder.java new file mode 100644 index 0000000000..81e6e9fbc2 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/registry/registrate/SimpleBuilder.java @@ -0,0 +1,162 @@ +package com.simibubi.create.api.registry.registrate; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.api.registry.SimpleRegistry.Provider; +import com.simibubi.create.impl.registry.TagProviderImpl; +import com.tterrag.registrate.AbstractRegistrate; +import com.tterrag.registrate.builders.AbstractBuilder; +import com.tterrag.registrate.builders.BuilderCallback; + +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.material.Fluid; + +public class SimpleBuilder extends AbstractBuilder> { + private final Supplier value; + + private SimpleRegistryAccess byBlock; + private SimpleRegistryAccess, R> byBlockEntity; + private SimpleRegistryAccess, R> byEntity; + private SimpleRegistryAccess byFluid; + + public SimpleBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, ResourceKey> registryKey, Supplier value) { + super(owner, parent, name, callback, registryKey); + this.value = value; + } + + @Override + protected T createEntry() { + return this.value.get(); + } + + // for setup + + @SuppressWarnings("deprecation") + public SimpleBuilder byBlock(SimpleRegistry registry) { + this.byBlock = SimpleRegistryAccess.of(registry, Block::builtInRegistryHolder); + return this; + } + + @SuppressWarnings("deprecation") + public SimpleBuilder byBlock(SimpleRegistry.Multi registry) { + this.byBlock = SimpleRegistryAccess.of(registry, Block::builtInRegistryHolder); + return this; + } + + public SimpleBuilder byBlockEntity(SimpleRegistry, R> registry) { + this.byBlockEntity = SimpleRegistryAccess.of(registry, TagProviderImpl::getBeHolder); + return this; + } + + public SimpleBuilder byBlockEntity(SimpleRegistry.Multi, R> registry) { + this.byBlockEntity = SimpleRegistryAccess.of(registry, TagProviderImpl::getBeHolder); + return this; + } + + @SuppressWarnings("deprecation") + public SimpleBuilder byEntity(SimpleRegistry, R> registry) { + this.byEntity = SimpleRegistryAccess.of(registry, EntityType::builtInRegistryHolder); + return this; + } + + @SuppressWarnings("deprecation") + public SimpleBuilder byEntity(SimpleRegistry.Multi, R> registry) { + this.byEntity = SimpleRegistryAccess.of(registry, EntityType::builtInRegistryHolder); + return this; + } + + @SuppressWarnings("deprecation") + public SimpleBuilder byFluid(SimpleRegistry registry) { + this.byFluid = SimpleRegistryAccess.of(registry, Fluid::builtInRegistryHolder); + return this; + } + + @SuppressWarnings("deprecation") + public SimpleBuilder byFluid(SimpleRegistry.Multi registry) { + this.byFluid = SimpleRegistryAccess.of(registry, Fluid::builtInRegistryHolder); + return this; + } + + // association methods + + public SimpleBuilder associate(Block block) { + assertPresent(this.byBlock, "Block"); + this.onRegister(value -> this.byBlock.adder.accept(block, value)); + return this; + } + + public SimpleBuilder associateBlockTag(TagKey tag) { + assertPresent(this.byBlock, "Block"); + this.onRegister(value -> this.byBlock.tagAdder.accept(tag, value)); + return this; + } + + public SimpleBuilder associate(BlockEntityType type) { + assertPresent(this.byBlockEntity, "BlockEntityType"); + this.onRegister(value -> this.byBlockEntity.adder.accept(type, value)); + return this; + } + + public SimpleBuilder associateBeTag(TagKey> tag) { + assertPresent(this.byBlockEntity, "BlockEntityType"); + this.onRegister(value -> this.byBlockEntity.tagAdder.accept(tag, value)); + return this; + } + + public SimpleBuilder associate(EntityType type) { + assertPresent(this.byEntity, "EntityType"); + this.onRegister(value -> this.byEntity.adder.accept(type, value)); + return this; + } + + public SimpleBuilder associateEntityTag(TagKey> tag) { + assertPresent(this.byEntity, "EntityType"); + this.onRegister(value -> this.byEntity.tagAdder.accept(tag, value)); + return this; + } + + public SimpleBuilder associate(Fluid fluid) { + assertPresent(this.byFluid, "Fluid"); + this.onRegister(value -> this.byFluid.adder.accept(fluid, value)); + return this; + } + + public SimpleBuilder associateFluidTag(TagKey tag) { + assertPresent(this.byFluid, "Fluid"); + this.onRegister(value -> this.byFluid.tagAdder.accept(tag, value)); + return this; + } + + private static void assertPresent(@Nullable Object object, String type) { + if (object == null) { + throw new IllegalStateException("This type does not support " + type + " associations"); + } + } + + protected record SimpleRegistryAccess(BiConsumer adder, BiConsumer, V> tagAdder) { + public static SimpleRegistryAccess of(SimpleRegistry registry, Function> holderGetter) { + return new SimpleRegistryAccess<>( + registry::register, + (tag, value) -> registry.registerProvider(Provider.forTag(tag, holderGetter, value)) + ); + } + + public static SimpleRegistryAccess of(SimpleRegistry.Multi registry, Function> holderGetter) { + return new SimpleRegistryAccess<>( + registry::add, + (tag, value) -> registry.addProvider(Provider.forTag(tag, holderGetter, value)) + ); + } + } +} diff --git a/src/main/java/com/simibubi/create/api/schematic/nbt/PartialSafeNBT.java b/src/main/java/com/simibubi/create/api/schematic/nbt/PartialSafeNBT.java new file mode 100644 index 0000000000..95d2c928e8 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/nbt/PartialSafeNBT.java @@ -0,0 +1,10 @@ +package com.simibubi.create.api.schematic.nbt; + +import net.minecraft.nbt.CompoundTag; + +public interface PartialSafeNBT { + /** + * This will always be called from the logical server + */ + void writeSafe(CompoundTag compound); +} diff --git a/src/main/java/com/simibubi/create/api/schematic/nbt/SafeNbtWriterRegistry.java b/src/main/java/com/simibubi/create/api/schematic/nbt/SafeNbtWriterRegistry.java new file mode 100644 index 0000000000..4f8f73b6a5 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/nbt/SafeNbtWriterRegistry.java @@ -0,0 +1,27 @@ +package com.simibubi.create.api.schematic.nbt; + +import com.simibubi.create.api.registry.SimpleRegistry; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; + +/** + * Registry for safe NBT writers, used for filtering unsafe BlockEntity data out of schematics. + *

+ * This is used to exclude specific tags that would result in exploits, ex. signs that execute commands when clicked. + *

+ * This is provided as an alternative to {@link PartialSafeNBT}. + */ +public class SafeNbtWriterRegistry { + public static final SimpleRegistry, SafeNbtWriter> REGISTRY = SimpleRegistry.create(); + + @FunctionalInterface + public interface SafeNbtWriter { + /** + * Write filtered, safe NBT to the given tag. This is always called on the logical server. + * @param tag the NBT tag to write to + */ + void writeSafe(BlockEntity be, CompoundTag tag); + } +} diff --git a/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementRegistries.java b/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementRegistries.java new file mode 100644 index 0000000000..8e4dfc023a --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/requirement/SchematicRequirementRegistries.java @@ -0,0 +1,45 @@ +package com.simibubi.create.api.schematic.requirement; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Registries for custom schematic requirements for blocks, block entities, and entities. These requirements determine + * the items that are needed for placement into the world through schematics. + *

+ * This is provided as an alternative to the following interfaces: + *

    + *
  • {@link SpecialBlockItemRequirement}
  • + *
  • {@link SpecialBlockEntityItemRequirement}
  • + *
  • {@link SpecialEntityItemRequirement}
  • + *
+ */ +public class SchematicRequirementRegistries { + public static final SimpleRegistry BLOCKS = SimpleRegistry.create(); + public static final SimpleRegistry, BlockEntityRequirement> BLOCK_ENTITIES = SimpleRegistry.create(); + public static final SimpleRegistry, EntityRequirement> ENTITIES = SimpleRegistry.create(); + + @FunctionalInterface + public interface BlockRequirement { + ItemRequirement getRequiredItems(BlockState state, @Nullable BlockEntity blockEntity); + } + + @FunctionalInterface + public interface BlockEntityRequirement { + ItemRequirement getRequiredItems(BlockEntity blockEntity, BlockState state); + } + + @FunctionalInterface + public interface EntityRequirement { + ItemRequirement getRequiredItems(Entity entity); + } +} diff --git a/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialBlockEntityItemRequirement.java b/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialBlockEntityItemRequirement.java new file mode 100644 index 0000000000..9d8764d012 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialBlockEntityItemRequirement.java @@ -0,0 +1,9 @@ +package com.simibubi.create.api.schematic.requirement; + +import com.simibubi.create.content.schematics.requirement.ItemRequirement; + +import net.minecraft.world.level.block.state.BlockState; + +public interface SpecialBlockEntityItemRequirement { + ItemRequirement getRequiredItems(BlockState state); +} diff --git a/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialBlockItemRequirement.java b/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialBlockItemRequirement.java new file mode 100644 index 0000000000..39ca485dfb --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialBlockItemRequirement.java @@ -0,0 +1,12 @@ +package com.simibubi.create.api.schematic.requirement; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.content.schematics.requirement.ItemRequirement; + +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public interface SpecialBlockItemRequirement { + ItemRequirement getRequiredItems(BlockState state, @Nullable BlockEntity blockEntity); +} diff --git a/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialEntityItemRequirement.java b/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialEntityItemRequirement.java new file mode 100644 index 0000000000..9623dd4147 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/schematic/requirement/SpecialEntityItemRequirement.java @@ -0,0 +1,7 @@ +package com.simibubi.create.api.schematic.requirement; + +import com.simibubi.create.content.schematics.requirement.ItemRequirement; + +public interface SpecialEntityItemRequirement { + ItemRequirement getRequiredItems(); +} diff --git a/src/main/java/com/simibubi/create/api/stress/BlockStressValues.java b/src/main/java/com/simibubi/create/api/stress/BlockStressValues.java new file mode 100644 index 0000000000..47c137aa87 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/stress/BlockStressValues.java @@ -0,0 +1,50 @@ +package com.simibubi.create.api.stress; + +import java.util.function.DoubleSupplier; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.tterrag.registrate.util.nullness.NonNullConsumer; + +import net.minecraft.world.level.block.Block; + +public class BlockStressValues { + /** + * Registry for suppliers of stress impacts. Determine the base impact at 1 RPM. + */ + public static final SimpleRegistry IMPACTS = SimpleRegistry.create(); + /** + * Registry for suppliers of stress capacities. Determine the base capacity at 1 RPM. + */ + public static final SimpleRegistry CAPACITIES = SimpleRegistry.create(); + /** + * Registry for generator RPM values. This is only used for tooltips; actual functionality is determined by the block. + */ + public static final SimpleRegistry RPM = SimpleRegistry.create(); + + public static double getImpact(Block block) { + DoubleSupplier supplier = IMPACTS.get(block); + return supplier == null ? 0 : supplier.getAsDouble(); + } + + public static double getCapacity(Block block) { + DoubleSupplier supplier = CAPACITIES.get(block); + return supplier == null ? 0 : supplier.getAsDouble(); + } + + /** + * Shortcut for when a generator always generates the same RPM. + */ + public static NonNullConsumer setGeneratorSpeed(int value) { + return block -> RPM.register(block, new GeneratedRpm(value, false)); + } + + /** + * Utility for Registrate. Registers the given RPM generation info to blocks passed to the returned consumer. + */ + public static NonNullConsumer setGeneratorSpeed(int value, boolean mayGenerateLess) { + return block -> RPM.register(block, new GeneratedRpm(value, mayGenerateLess)); + } + + public record GeneratedRpm(int value, boolean mayGenerateLess) { + } +} diff --git a/src/main/java/com/simibubi/create/compat/Mods.java b/src/main/java/com/simibubi/create/compat/Mods.java index df64a92df0..37418fe6a7 100644 --- a/src/main/java/com/simibubi/create/compat/Mods.java +++ b/src/main/java/com/simibubi/create/compat/Mods.java @@ -3,13 +3,13 @@ package com.simibubi.create.compat; import java.util.Optional; import java.util.function.Supplier; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.RegisteredObjects; - +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; + import net.minecraftforge.fml.ModList; import net.minecraftforge.registries.ForgeRegistries; @@ -18,8 +18,8 @@ import net.minecraftforge.registries.ForgeRegistries; */ public enum Mods { AETHER, + BETTEREND, COMPUTERCRAFT, - CONNECTIVITY, CURIOS, DYNAMICTREES, FUNCTIONALSTORAGE, @@ -34,7 +34,7 @@ public enum Mods { MODERNUI, FTBCHUNKS, JOURNEYMAP, - BETTEREND; + FTBLIBRARY; private final String id; @@ -65,7 +65,7 @@ public enum Mods { if (!isLoaded()) return false; Item asItem = entry.asItem(); - return asItem != null && RegisteredObjects.getKeyOrThrow(asItem) + return asItem != null && CatnipServices.REGISTRIES.getKeyOrThrow(asItem) .getNamespace() .equals(id); } diff --git a/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java b/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java index b8f40c387b..d058ab59cd 100644 --- a/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java +++ b/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java @@ -1,18 +1,18 @@ package com.simibubi.create.compat.computercraft; -import java.util.function.Function; - import com.simibubi.create.compat.Mods; import com.simibubi.create.compat.computercraft.implementation.ComputerBehaviour; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import java.util.function.Function; + public class ComputerCraftProxy { public static void register() { fallbackFactory = FallbackComputerBehaviour::new; Mods.COMPUTERCRAFT.executeIfInstalled(() -> ComputerCraftProxy::registerWithDependency); } - + private static void registerWithDependency() { /* Comment if computercraft.implementation is not in the source set */ computerFactory = ComputerBehaviour::new; diff --git a/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java b/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java index e63b487763..b3bf6600ad 100644 --- a/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java +++ b/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java @@ -1,23 +1,21 @@ package com.simibubi.create.compat.computercraft; -import java.util.function.Supplier; - -import javax.annotation.Nullable; - import com.simibubi.create.compat.Mods; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; -import com.simibubi.create.foundation.gui.widget.ElementWidget; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.utility.Lang; - +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; +import net.createmod.catnip.gui.widget.ElementWidget; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import javax.annotation.Nullable; +import java.util.function.Supplier; + public class ComputerScreen extends AbstractSimiScreen { private final AllGuiTextures background = AllGuiTextures.COMPUTER; @@ -52,7 +50,7 @@ public class ComputerScreen extends AbstractSimiScreen { @Override protected void init() { - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); super.init(); int x = guiLeft; @@ -61,11 +59,11 @@ public class ComputerScreen extends AbstractSimiScreen { Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { computerWidget = new ElementWidget(x + 33, y + 38) .showingElement(GuiGameElement.of(Mods.COMPUTERCRAFT.getBlock("computer_advanced"))); - computerWidget.getToolTip().add(Lang.translate("gui.attached_computer.hint").component()); + computerWidget.getToolTip().add(CreateLang.translate("gui.attached_computer.hint").component()); addRenderableWidget(computerWidget); }); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(this::onClose); addRenderableWidget(confirmButton); } @@ -80,8 +78,8 @@ public class ComputerScreen extends AbstractSimiScreen { background.render(graphics, x, y); graphics.drawString(font, displayTitle.get(), - Math.round(x + background.width / 2.0F - font.width(displayTitle.get()) / 2.0F), y + 4, 0x442000, false); - graphics.drawWordWrap(font, Lang.translate("gui.attached_computer.controlled") + Math.round(x + background.getWidth() / 2.0F - font.width(displayTitle.get()) / 2.0F), y + 4, 0x442000, false); + graphics.drawWordWrap(font, CreateLang.translate("gui.attached_computer.controlled") .component(), x + 55, y + 32, 111, 0x7A7A7A); if (additional != null) diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java index 693a72aa71..2c3008b9c1 100644 --- a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java @@ -1,5 +1,7 @@ package com.simibubi.create.compat.computercraft.implementation.peripherals; +import java.nio.charset.StandardCharsets; +import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.jetbrains.annotations.NotNull; @@ -8,7 +10,11 @@ import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.LuaValues; +import dan200.computercraft.api.lua.ObjectLuaTable; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; @@ -53,6 +59,28 @@ public class DisplayLinkPeripheral extends SyncedPeripheral map) { + ObjectLuaTable table = new ObjectLuaTable(map); + bytes = new byte[table.length()]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) (table.getInt(i + 1) & 0xff); + } + } else { + throw LuaValues.badArgumentOf(args, 0, "string or table"); + } + writeImpl(new String(bytes, StandardCharsets.UTF_8)); + } + + protected final void writeImpl(String text) { ListTag tag = blockEntity.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING); int x = cursorX.get(); diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java index 146742b3bf..3f40a9f210 100644 --- a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java @@ -13,7 +13,6 @@ import com.simibubi.create.content.trains.schedule.Schedule; import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.content.trains.station.StationBlockEntity; import com.simibubi.create.content.trains.station.TrainEditPacket; -import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.StringHelper; import dan200.computercraft.api.lua.IArguments; @@ -28,6 +27,8 @@ import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NumericTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; + import net.minecraftforge.network.PacketDistributor; public class StationPeripheral extends SyncedPeripheral { @@ -128,7 +129,7 @@ public class StationPeripheral extends SyncedPeripheral { @LuaFunction(mainThread = true) public final void setTrainName(String name) throws LuaException { Train train = getTrainOrThrow(); - train.name = Components.literal(name); + train.name = Component.literal(name); AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainEditPacket.TrainEditReturnPacket(train.id, name, train.icon.getId(), train.mapColorIndex)); } @@ -209,8 +210,8 @@ public class StationPeripheral extends SyncedPeripheral { for (String compoundKey : compoundTag.getAllKeys()) { table.put( - StringHelper.camelCaseToSnakeCase(compoundKey), - fromNBTTag(compoundKey, compoundTag.get(compoundKey)) + StringHelper.camelCaseToSnakeCase(compoundKey), + fromNBTTag(compoundKey, compoundTag.get(compoundKey)) ); } @@ -254,11 +255,11 @@ public class StationPeripheral extends SyncedPeripheral { throw new LuaException("table key is not of type string"); compound.put( - // Items serialize their resource location as "id" and not as "Id". - // This check is needed to see if the 'i' should be left lowercase or not. - // Items store "count" in the same compound tag, so we can check for its presence to see if this is a serialized item - compoundKey.equals("id") && v.containsKey("count") ? "id" : StringHelper.snakeCaseToCamelCase(compoundKey), - toNBTTag(compoundKey, v.get(compoundKey)) + // Items serialize their resource location as "id" and not as "Id". + // This check is needed to see if the 'i' should be left lowercase or not. + // Items store "count" in the same compound tag, so we can check for its presence to see if this is a serialized item + compoundKey.equals("id") && v.containsKey("count") ? "id" : StringHelper.snakeCaseToCamelCase(compoundKey), + toNBTTag(compoundKey, v.get(compoundKey)) ); } diff --git a/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java b/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java index ad1971ec51..e17fbc899b 100644 --- a/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java +++ b/src/main/java/com/simibubi/create/compat/curios/GogglesCurioRenderer.java @@ -3,7 +3,6 @@ package com.simibubi.create.compat.curios; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.Create; - import net.minecraft.client.Minecraft; import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.HumanoidModel; @@ -46,6 +45,7 @@ public class GogglesCurioRenderer implements ICurioRenderer { // Translate and rotate with our head matrixStack.pushPose(); matrixStack.translate(model.head.x / 16.0, model.head.y / 16.0, model.head.z / 16.0); + matrixStack.mulPose(Axis.ZP.rotation(model.head.zRot)); matrixStack.mulPose(Axis.YP.rotation(model.head.yRot)); matrixStack.mulPose(Axis.XP.rotation(model.head.xRot)); diff --git a/src/main/java/com/simibubi/create/compat/ftb/FTBIntegration.java b/src/main/java/com/simibubi/create/compat/ftb/FTBIntegration.java new file mode 100644 index 0000000000..32864b7aae --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/ftb/FTBIntegration.java @@ -0,0 +1,40 @@ +package com.simibubi.create.compat.ftb; + +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; + +import dev.ftb.mods.ftblibrary.FTBLibraryClient; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.minecraft.client.gui.screens.Screen; +import net.minecraftforge.client.event.ScreenEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.IEventBus; + +public class FTBIntegration { + + private static int buttonStatePreviously = 0; + + public static void init(IEventBus modEventBus, IEventBus forgeEventBus) { + forgeEventBus.addListener(EventPriority.HIGH, FTBIntegration::removeGUIClutterOpen); + forgeEventBus.addListener(EventPriority.LOW, FTBIntegration::removeGUIClutterClose); + } + + private static void removeGUIClutterOpen(ScreenEvent.Opening event) { + if (isCreate(event.getCurrentScreen())) + return; + if (!isCreate(event.getNewScreen())) + return; + buttonStatePreviously = FTBLibraryClient.showButtons; + FTBLibraryClient.showButtons = 0; + } + + private static void removeGUIClutterClose(ScreenEvent.Closing event) { + if (!isCreate(event.getScreen())) + return; + FTBLibraryClient.showButtons = buttonStatePreviously; + } + + private static boolean isCreate(Screen screen) { + return screen instanceof AbstractSimiContainerScreen || screen instanceof AbstractSimiScreen; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index 56351d019b..c36ee88ba5 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -3,12 +3,15 @@ package com.simibubi.create.compat.jei; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; @@ -56,18 +59,18 @@ import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe; import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity; import com.simibubi.create.content.kinetics.press.PressingRecipe; import com.simibubi.create.content.kinetics.saw.CuttingRecipe; -import com.simibubi.create.content.kinetics.saw.SawBlockEntity; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSetItemScreen; import com.simibubi.create.content.logistics.filter.AbstractFilterScreen; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterScreen; import com.simibubi.create.content.processing.basin.BasinRecipe; import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; import com.simibubi.create.content.redstone.link.controller.LinkedControllerScreen; import com.simibubi.create.content.trains.schedule.ScheduleScreen; -import com.simibubi.create.foundation.config.ConfigBase.ConfigBool; import com.simibubi.create.foundation.data.recipe.LogStrippingFakeRecipes; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CRecipes; @@ -86,9 +89,11 @@ import mezz.jei.api.registration.IRecipeRegistration; import mezz.jei.api.registration.IRecipeTransferRegistration; import mezz.jei.api.registration.ISubtypeRegistration; import mezz.jei.api.runtime.IIngredientManager; +import net.createmod.catnip.config.ConfigBase.ConfigBool; import net.minecraft.client.Minecraft; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffect; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.alchemy.Potion; @@ -101,7 +106,6 @@ import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Blocks; import net.minecraftforge.common.crafting.IShapedRecipe; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.ModList; import net.minecraftforge.registries.ForgeRegistries; @JeiPlugin @@ -238,15 +242,6 @@ public class CreateJEI implements IModPlugin { .emptyBackground(177, 70) .build("block_cutting", BlockCuttingCategory::new), - woodCutting = builder(CondensedBlockCuttingRecipe.class) - .enableIf(c -> c.allowWoodcuttingOnSaw.get() && ModList.get() - .isLoaded("druidcraft")) - .addRecipes(() -> BlockCuttingCategory.condenseRecipes(getTypedRecipesExcluding(SawBlockEntity.woodcuttingRecipeType.get(), AllRecipeTypes::shouldIgnoreInAutomation))) - .catalyst(AllBlocks.MECHANICAL_SAW::get) - .doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_STAIRS) - .emptyBackground(177, 70) - .build("wood_cutting", BlockCuttingCategory::new), - polishing = builder(SandPaperPolishingRecipe.class) .addTypedRecipes(AllRecipeTypes.SANDPAPER_POLISHING) .catalyst(AllItems.SAND_PAPER::get) @@ -357,6 +352,7 @@ public class CreateJEI implements IModPlugin { @Override public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { registration.addRecipeTransferHandler(new BlueprintTransferHandler(), RecipeTypes.CRAFTING); + registration.addUniversalRecipeTransferHandler(new StockKeeperTransferHandler(registration.getJeiHelpers())); } @Override @@ -371,14 +367,22 @@ public class CreateJEI implements IModPlugin { public void registerExtraIngredients(IExtraIngredientRegistration registration) { Collection potions = ForgeRegistries.POTIONS.getValues(); Collection potionFluids = new ArrayList<>(potions.size() * 3); + Set> visitedEffects = new HashSet<>(); for (Potion potion : potions) { // @goshante: Ingame potion fluids always have Bottle tag that specifies // to what bottle type this potion belongs // Potion fluid without this tag wouldn't be recognized by other mods - for (PotionFluid.BottleType bottleType : PotionFluid.BottleType.values()) { - FluidStack potionFluid = PotionFluid.of(1000, potion, bottleType); - potionFluids.add(potionFluid); - } + +// for (PotionFluid.BottleType bottleType : PotionFluid.BottleType.values()) { +// FluidStack potionFluid = PotionFluid.of(1000, potion, bottleType); +// potionFluids.add(potionFluid); +// } + + if (!potion.getEffects().isEmpty()) + if (!visitedEffects.add(potion.getEffects().stream().map(mei -> mei.getEffect()).collect(Collectors.toSet()))) + continue; + + potionFluids.add(PotionFluid.of(1000, potion, PotionFluid.BottleType.REGULAR)); } registration.addExtraIngredients(ForgeTypes.FLUID_STACK, potionFluids); } @@ -392,6 +396,8 @@ public class CreateJEI implements IModPlugin { registration.addGhostIngredientHandler(BlueprintScreen.class, new GhostIngredientHandler()); registration.addGhostIngredientHandler(LinkedControllerScreen.class, new GhostIngredientHandler()); registration.addGhostIngredientHandler(ScheduleScreen.class, new GhostIngredientHandler()); + registration.addGhostIngredientHandler(RedstoneRequesterScreen.class, new GhostIngredientHandler()); + registration.addGhostIngredientHandler(FactoryPanelSetItemScreen.class, new GhostIngredientHandler()); } private class CategoryBuilder> { @@ -427,11 +433,11 @@ public class CreateJEI implements IModPlugin { return addRecipeListConsumer(recipes -> recipes.addAll(collection.get())); } + @SuppressWarnings("unchecked") public CategoryBuilder addAllRecipesIf(Predicate> pred) { return addRecipeListConsumer(recipes -> consumeAllRecipes(recipe -> { - if (pred.test(recipe)) { + if (pred.test(recipe)) recipes.add((T) recipe); - } })); } @@ -544,7 +550,7 @@ public class CreateJEI implements IModPlugin { CreateRecipeCategory.Info info = new CreateRecipeCategory.Info<>( new mezz.jei.api.recipe.RecipeType<>(Create.asResource(name), recipeClass), - Lang.translateDirect("recipe." + name), background, icon, recipesSupplier, catalysts); + CreateLang.translateDirect("recipe." + name), background, icon, recipesSupplier, catalysts); CreateRecipeCategory category = factory.create(info); allCategories.add(category); return category; @@ -559,13 +565,13 @@ public class CreateJEI implements IModPlugin { .forEach(consumer); } + @SuppressWarnings("unchecked") public static > void consumeTypedRecipes(Consumer consumer, RecipeType type) { Map> map = Minecraft.getInstance() .getConnection() .getRecipeManager().recipes.get(type); - if (map != null) { + if (map != null) map.values().forEach(recipe -> consumer.accept((T) recipe)); - } } public static List> getTypedRecipes(RecipeType type) { diff --git a/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java b/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java index 65b595a090..288bef8978 100644 --- a/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java +++ b/src/main/java/com/simibubi/create/compat/jei/DoubleItemIcon.java @@ -1,15 +1,14 @@ package com.simibubi.create.compat.jei; -import java.util.function.Supplier; - import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.gui.element.GuiGameElement; - import mezz.jei.api.gui.drawable.IDrawable; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.ItemStack; +import java.util.function.Supplier; + public class DoubleItemIcon implements IDrawable { private Supplier primarySupplier; diff --git a/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java index 96668a0080..f9e2dd0094 100644 --- a/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java +++ b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java @@ -1,16 +1,10 @@ package com.simibubi.create.compat.jei; -import java.util.LinkedList; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.AllPackets; import com.simibubi.create.content.logistics.filter.AttributeFilterScreen; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.menu.GhostItemMenu; import com.simibubi.create.foundation.gui.menu.GhostItemSubmitPacket; - import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.handlers.IGhostIngredientHandler; import mezz.jei.api.ingredients.ITypedIngredient; @@ -19,6 +13,10 @@ import net.minecraft.client.renderer.Rect2i; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.LinkedList; +import java.util.List; + @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public class GhostIngredientHandler> diff --git a/src/main/java/com/simibubi/create/compat/jei/ItemIcon.java b/src/main/java/com/simibubi/create/compat/jei/ItemIcon.java index 7a4d223af4..29212fca45 100644 --- a/src/main/java/com/simibubi/create/compat/jei/ItemIcon.java +++ b/src/main/java/com/simibubi/create/compat/jei/ItemIcon.java @@ -1,15 +1,14 @@ package com.simibubi.create.compat.jei; -import java.util.function.Supplier; - import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.gui.element.GuiGameElement; - import mezz.jei.api.gui.drawable.IDrawable; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.ItemStack; +import java.util.function.Supplier; + public class ItemIcon implements IDrawable { private Supplier supplier; diff --git a/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java b/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java index 68b6d61516..4eb0abceb7 100644 --- a/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java +++ b/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java @@ -3,14 +3,15 @@ package com.simibubi.create.compat.jei; import java.util.List; import com.simibubi.create.content.fluids.potion.PotionFluid.BottleType; -import com.simibubi.create.foundation.utility.NBTHelper; import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter; import mezz.jei.api.ingredients.subtypes.UidContext; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraftforge.fluids.FluidStack; /* From JEI's Potion item subtype interpreter */ diff --git a/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java b/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java index c3a826b69a..6280dfe312 100644 --- a/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java +++ b/src/main/java/com/simibubi/create/compat/jei/ScreenResourceWrapper.java @@ -1,7 +1,6 @@ package com.simibubi.create.compat.jei; import com.simibubi.create.foundation.gui.AllGuiTextures; - import mezz.jei.api.gui.drawable.IDrawable; import net.minecraft.client.gui.GuiGraphics; @@ -15,18 +14,18 @@ public class ScreenResourceWrapper implements IDrawable { @Override public int getWidth() { - return resource.width; + return resource.getWidth(); } @Override public int getHeight() { - return resource.height; + return resource.getHeight(); } @Override public void draw(GuiGraphics graphics, int xOffset, int yOffset) { - graphics.blit(resource.location, xOffset, yOffset, 0, resource.startX, resource.startY, resource.width, - resource.height, 256, 256); + graphics.blit(resource.location, xOffset, yOffset, 0, resource.getStartX(), resource.getStartY(), resource.getWidth(), + resource.getHeight(), 256, 256); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/StockKeeperTransferHandler.java b/src/main/java/com/simibubi/create/compat/jei/StockKeeperTransferHandler.java new file mode 100644 index 0000000000..705014a65c --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/StockKeeperTransferHandler.java @@ -0,0 +1,137 @@ +package com.simibubi.create.compat.jei; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.annotation.ParametersAreNonnullByDefault; + +import org.apache.commons.lang3.mutable.MutableObject; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.stockTicker.CraftableBigItemStack; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperRequestMenu; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperRequestScreen; +import com.simibubi.create.foundation.utility.CreateLang; + +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.helpers.IJeiHelpers; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.transfer.IRecipeTransferError; +import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import mezz.jei.common.transfer.RecipeTransferOperationsResult; +import mezz.jei.common.transfer.RecipeTransferUtil; +import mezz.jei.library.transfer.RecipeTransferErrorMissingSlots; +import mezz.jei.library.transfer.RecipeTransferErrorTooltip; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class StockKeeperTransferHandler implements IRecipeTransferHandler { + + private IJeiHelpers helpers; + + public StockKeeperTransferHandler(IJeiHelpers helpers) { + this.helpers = helpers; + } + + @Override + public Class getContainerClass() { + return StockKeeperRequestMenu.class; + } + + @Override + public Optional> getMenuType() { + return Optional.of(AllMenuTypes.STOCK_KEEPER_REQUEST.get()); + } + + @Override + public RecipeType getRecipeType() { + return null; + } + + @Override + public @Nullable IRecipeTransferError transferRecipe(StockKeeperRequestMenu container, Object object, + IRecipeSlotsView recipeSlots, Player player, boolean maxTransfer, boolean doTransfer) { + Level level = player.level(); + if (!(object instanceof Recipe recipe)) + return null; + MutableObject result = new MutableObject<>(); + if (level.isClientSide()) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> result + .setValue(transferRecipeOnClient(container, recipe, recipeSlots, player, maxTransfer, doTransfer))); + return result.getValue(); + } + + private @Nullable IRecipeTransferError transferRecipeOnClient(StockKeeperRequestMenu container, Recipe recipe, + IRecipeSlotsView recipeSlots, Player player, boolean maxTransfer, boolean doTransfer) { + if (!(container.screenReference instanceof StockKeeperRequestScreen screen)) + return null; + + for (CraftableBigItemStack cbis : screen.recipesToOrder) + if (cbis.recipe == recipe) + return new RecipeTransferErrorTooltip(CreateLang.translate("gui.stock_keeper.already_ordering_recipe") + .component()); + + if (screen.itemsToOrder.size() >= 9) + return new RecipeTransferErrorTooltip(CreateLang.translate("gui.stock_keeper.slots_full") + .component()); + + InventorySummary summary = screen.getMenu().contentHolder.getLastClientsideStockSnapshotAsSummary(); + if (summary == null) + return null; + + Container outputDummy = new RecipeWrapper(new ItemStackHandler(9)); + List craftingSlots = new ArrayList<>(); + for (int i = 0; i < outputDummy.getContainerSize(); i++) + craftingSlots.add(new Slot(outputDummy, i, 0, 0)); + + List stacksByCount = summary.getStacksByCount(); + Container inputDummy = new RecipeWrapper(new ItemStackHandler(stacksByCount.size())); + Map availableItemStacks = new HashMap<>(); + for (int j = 0; j < stacksByCount.size(); j++) { + BigItemStack bigItemStack = stacksByCount.get(j); + availableItemStacks.put(new Slot(inputDummy, j, 0, 0), + bigItemStack.stack.copyWithCount(bigItemStack.count)); + } + + RecipeTransferOperationsResult transferOperations = + RecipeTransferUtil.getRecipeTransferOperations(helpers.getStackHelper(), availableItemStacks, + recipeSlots.getSlotViews(RecipeIngredientRole.INPUT), craftingSlots); + + if (!transferOperations.missingItems.isEmpty()) + return new RecipeTransferErrorMissingSlots(CreateLang.translate("gui.stock_keeper.not_in_stock") + .component(), transferOperations.missingItems); + + if (!doTransfer) + return null; + + CraftableBigItemStack cbis = new CraftableBigItemStack(recipe.getResultItem(player.level() + .registryAccess()), recipe); + + screen.recipesToOrder.add(cbis); + screen.searchBox.setValue(""); + screen.refreshSearchNextTick = true; + screen.requestCraftable(cbis, maxTransfer ? cbis.stack.getMaxStackSize() : 1); + + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/ToolboxColoringRecipeMaker.java b/src/main/java/com/simibubi/create/compat/jei/ToolboxColoringRecipeMaker.java index 7529bee617..3c1f4dd387 100644 --- a/src/main/java/com/simibubi/create/compat/jei/ToolboxColoringRecipeMaker.java +++ b/src/main/java/com/simibubi/create/compat/jei/ToolboxColoringRecipeMaker.java @@ -1,11 +1,7 @@ package com.simibubi.create.compat.jei; -import java.util.Arrays; -import java.util.stream.Stream; - import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; - import net.minecraft.core.NonNullList; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -19,6 +15,9 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.level.block.Block; +import java.util.Arrays; +import java.util.stream.Stream; + public final class ToolboxColoringRecipeMaker { // From JEI's ShulkerBoxColoringRecipeMaker diff --git a/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java index c07d4cec34..0fe97a817f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java @@ -16,18 +16,19 @@ import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; import mezz.jei.api.forge.ForgeTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; +import net.createmod.catnip.data.Pair; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; + import net.minecraftforge.fluids.FluidStack; @ParametersAreNonnullByDefault @@ -130,7 +131,7 @@ public class BasinCategory extends CreateRecipeCategory { AllGuiTextures heatBar = noHeat ? AllGuiTextures.JEI_NO_HEAT_BAR : AllGuiTextures.JEI_HEAT_BAR; heatBar.render(graphics, 4, 80); - graphics.drawString(Minecraft.getInstance().font, Lang.translateDirect(requiredHeat.getTranslationKey()), 9, + graphics.drawString(Minecraft.getInstance().font, CreateLang.translateDirect(requiredHeat.getTranslationKey()), 9, 86, requiredHeat.getColor(), false); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java index 86cc92264b..d5c53cd804 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java @@ -1,16 +1,9 @@ package com.simibubi.create.compat.jei.category; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe; import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.item.ItemHelper; - import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; @@ -22,6 +15,11 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.StonecutterRecipe; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + @ParametersAreNonnullByDefault public class BlockCuttingCategory extends CreateRecipeCategory { @@ -99,7 +97,7 @@ public class BlockCuttingCategory extends CreateRecipeCategory condenseRecipes(List> stoneCuttingRecipes) { List condensed = new ArrayList<>(); Recipes: for (Recipe recipe : stoneCuttingRecipes) { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java index 6517830e18..26ff647411 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java @@ -8,20 +8,17 @@ import java.util.stream.Collectors; import javax.annotation.ParametersAreNonnullByDefault; -import mezz.jei.api.gui.ingredient.IRecipeSlotRichTooltipCallback; - import org.jetbrains.annotations.NotNull; import com.simibubi.create.AllFluids; import com.simibubi.create.content.fluids.potion.PotionFluidHandler; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import mezz.jei.api.forge.ForgeTypes; import mezz.jei.api.gui.drawable.IDrawable; -import mezz.jei.api.gui.ingredient.IRecipeSlotTooltipCallback; +import mezz.jei.api.gui.ingredient.IRecipeSlotRichTooltipCallback; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.registration.IRecipeCatalystRegistration; @@ -34,6 +31,7 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; + import net.minecraftforge.fluids.FluidStack; @ParametersAreNonnullByDefault @@ -114,7 +112,7 @@ public abstract class CreateRecipeCategory> implements IReci return (view, tooltip) -> { float chance = output.getChance(); if (chance != 1) - tooltip.add(Lang.translateDirect("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100)) + tooltip.add(CreateLang.translateDirect("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100)) .withStyle(ChatFormatting.GOLD)); }; } @@ -151,7 +149,7 @@ public abstract class CreateRecipeCategory> implements IReci } int amount = mbAmount == -1 ? fluidStack.getAmount() : mbAmount; - Component text = Components.literal(String.valueOf(amount)).append(Lang.translateDirect("generic.unit.millibuckets")).withStyle(ChatFormatting.GOLD); + Component text = Component.literal(String.valueOf(amount)).append(CreateLang.translateDirect("generic.unit.millibuckets")).withStyle(ChatFormatting.GOLD); tooltip.add(text); }; } @@ -160,12 +158,12 @@ public abstract class CreateRecipeCategory> implements IReci return new IDrawable() { @Override public int getWidth() { - return texture.width; + return texture.getWidth(); } @Override public int getHeight() { - return texture.height; + return texture.getHeight(); } @Override @@ -175,7 +173,9 @@ public abstract class CreateRecipeCategory> implements IReci }; } - public record Info>(RecipeType recipeType, Component title, IDrawable background, IDrawable icon, Supplier> recipes, List> catalysts) { + public record Info>(RecipeType recipeType, Component title, IDrawable background, + IDrawable icon, Supplier> recipes, + List> catalysts) { } public interface Factory> { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java index e3b8279d8e..1709dc2b4e 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java @@ -10,12 +10,12 @@ import com.simibubi.create.content.kinetics.crusher.AbstractCrushingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.ponder.ui.LayoutHelper; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; +import net.createmod.catnip.layout.LayoutHelper; import net.minecraft.client.gui.GuiGraphics; @ParametersAreNonnullByDefault diff --git a/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java index ece64e0d1f..eafc555976 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java @@ -1,15 +1,10 @@ package com.simibubi.create.compat.jei.category; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer; import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.utility.Lang; - +import com.simibubi.create.foundation.utility.CreateLang; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.builder.IRecipeSlotBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; @@ -18,6 +13,9 @@ import mezz.jei.api.recipe.RecipeIngredientRole; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + @ParametersAreNonnullByDefault public class DeployingCategory extends CreateRecipeCategory { @@ -37,7 +35,7 @@ public class DeployingCategory extends CreateRecipeCategory results = recipe.getRollableResults(); boolean single = results.size() == 1; for (int i = 0; i < results.size(); i++) { @@ -51,7 +49,7 @@ public class DeployingCategory extends CreateRecipeCategory tooltip.add(1, Lang.translateDirect("recipe.deploying.not_consumed").withStyle(ChatFormatting.GOLD))); + handItemSlot.addTooltipCallback((recipeSlotView, tooltip) -> tooltip.add(1, CreateLang.translateDirect("recipe.deploying.not_consumed").withStyle(ChatFormatting.GOLD))); } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java index 8d8590fa96..b524c8d10f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanBlastingCategory.java @@ -2,8 +2,7 @@ package com.simibubi.create.compat.jei.category; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.GuiGameElement; - +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.level.material.Fluids; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java index 323eb5049d..14e7849a5f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java @@ -3,8 +3,7 @@ package com.simibubi.create.compat.jei.category; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.GuiGameElement; - +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.level.block.Blocks; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanSmokingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanSmokingCategory.java index e0bbcdde21..41a98987f0 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanSmokingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanSmokingCategory.java @@ -2,8 +2,7 @@ package com.simibubi.create.compat.jei.category; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.GuiGameElement; - +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.crafting.SmokingRecipe; import net.minecraft.world.level.block.Blocks; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java index 9f45f6ba3f..bfb09f3621 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java @@ -2,8 +2,7 @@ package com.simibubi.create.compat.jei.category; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe; -import com.simibubi.create.foundation.gui.element.GuiGameElement; - +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.level.material.Fluids; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java index 49d3b2a14c..235fe03575 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java @@ -1,24 +1,18 @@ package com.simibubi.create.compat.jei.category; -import java.util.List; -import java.util.Optional; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.content.kinetics.deployer.ItemApplicationRecipe; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.utility.Lang; - +import com.simibubi.create.foundation.utility.CreateLang; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.BlockItem; @@ -26,6 +20,10 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; +import java.util.Optional; + @ParametersAreNonnullByDefault public class ItemApplicationCategory extends CreateRecipeCategory { @@ -44,7 +42,7 @@ public class ItemApplicationCategory extends CreateRecipeCategory tooltip.add(1, Lang.translateDirect("recipe.deploying.not_consumed") + ? (view, tooltip) -> tooltip.add(1, CreateLang.translateDirect("recipe.deploying.not_consumed") .withStyle(ChatFormatting.GOLD)) : (view, tooltip) -> {} ); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java index 98e59102bc..f2bdad5fe8 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java @@ -10,8 +10,8 @@ import com.simibubi.create.content.fluids.potion.PotionFluidHandler; import com.simibubi.create.content.fluids.transfer.EmptyingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.foundation.gui.AllGuiTextures; + import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.utility.RegisteredObjects; import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; import mezz.jei.api.constants.VanillaTypes; @@ -21,12 +21,12 @@ import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.runtime.IIngredientManager; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStackLinkedSet; import net.minecraft.world.item.Items; -import net.minecraft.world.item.PotionItem; import net.minecraft.world.item.crafting.Ingredient; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; @@ -78,8 +78,8 @@ public class ItemDrainCategory extends CreateRecipeCategory { result = ItemHelper.sameItem(stack, result) ? stack : emptiedItems.addOrGet(result); Ingredient ingredient = Ingredient.of(stack); - ResourceLocation itemName = RegisteredObjects.getKeyOrThrow(stack.getItem()); - ResourceLocation fluidName = RegisteredObjects.getKeyOrThrow(extracted.getFluid()); + ResourceLocation itemName = CatnipServices.REGISTRIES.getKeyOrThrow(stack.getItem()); + ResourceLocation fluidName = CatnipServices.REGISTRIES.getKeyOrThrow(extracted.getFluid()); consumer.accept(new ProcessingRecipeBuilder<>(EmptyingRecipe::new, Create.asResource("empty_" + itemName.getNamespace() + "_" + itemName.getPath() + "_of_" diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java index 0bf8309dad..f313f8cf74 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java @@ -11,7 +11,6 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.utility.Components; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; @@ -30,6 +29,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.Ingredient; + import net.minecraftforge.common.crafting.IShapedRecipe; @ParametersAreNonnullByDefault @@ -188,7 +188,7 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory list = new ArrayList<>(); - MutableComponent crash = Components.translatable("jei.tooltip.error.crash"); + MutableComponent crash = Component.translatable("jei.tooltip.error.crash"); list.add(crash.withStyle(ChatFormatting.RED)); return list; } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java index 0a7b4d73f0..07cd3dddcd 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java @@ -1,20 +1,18 @@ package com.simibubi.create.compat.jei.category; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.compat.jei.category.animations.AnimatedMillstone; import com.simibubi.create.content.kinetics.crusher.AbstractCrushingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; - import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import net.minecraft.client.gui.GuiGraphics; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + @ParametersAreNonnullByDefault public class MillingCategory extends CreateRecipeCategory { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java index 7089b3a441..2c8c621fb4 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java @@ -1,15 +1,14 @@ package com.simibubi.create.compat.jei.category; -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.compat.jei.category.animations.AnimatedBlazeBurner; import com.simibubi.create.compat.jei.category.animations.AnimatedMixer; import com.simibubi.create.content.processing.basin.BasinRecipe; import com.simibubi.create.content.processing.recipe.HeatCondition; - import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import net.minecraft.client.gui.GuiGraphics; +import javax.annotation.ParametersAreNonnullByDefault; + @ParametersAreNonnullByDefault public class MixingCategory extends BasinCategory { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java index a95b9838d8..55764361b5 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MysteriousItemConversionCategory.java @@ -1,21 +1,19 @@ package com.simibubi.create.compat.jei.category; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.compat.jei.ConversionRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; - import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import net.minecraft.client.gui.GuiGraphics; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.List; + @ParametersAreNonnullByDefault public class MysteriousItemConversionCategory extends CreateRecipeCategory { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java index 69b87d829f..1b207bf247 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java @@ -1,13 +1,10 @@ package com.simibubi.create.compat.jei.category; -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.compat.jei.category.animations.AnimatedBlazeBurner; import com.simibubi.create.compat.jei.category.animations.AnimatedPress; import com.simibubi.create.content.processing.basin.BasinRecipe; import com.simibubi.create.content.processing.recipe.HeatCondition; import com.simibubi.create.foundation.gui.AllGuiTextures; - import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; @@ -16,6 +13,8 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.NonNullList; import net.minecraft.world.item.crafting.Ingredient; +import javax.annotation.ParametersAreNonnullByDefault; + @ParametersAreNonnullByDefault public class PackingCategory extends BasinCategory { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java index 1046a01510..1042510260 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java @@ -1,23 +1,22 @@ package com.simibubi.create.compat.jei.category; -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.AllItems; import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.GuiGameElement; - import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; +import javax.annotation.ParametersAreNonnullByDefault; + @ParametersAreNonnullByDefault public class PolishingCategory extends CreateRecipeCategory { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java index d54fc22da4..194fd9c82b 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java @@ -1,20 +1,18 @@ package com.simibubi.create.compat.jei.category; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.compat.jei.category.animations.AnimatedPress; import com.simibubi.create.content.kinetics.press.PressingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; - import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import net.minecraft.client.gui.GuiGraphics; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + @ParametersAreNonnullByDefault public class PressingCategory extends CreateRecipeCategory { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java index a116a29e0b..548af1f483 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java @@ -1,10 +1,5 @@ package com.simibubi.create.compat.jei.category; -import java.util.List; -import java.util.function.Supplier; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; @@ -13,8 +8,7 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.utility.Lang; - +import com.simibubi.create.foundation.utility.CreateLang; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; @@ -23,6 +17,10 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; +import java.util.function.Supplier; + @ParametersAreNonnullByDefault public abstract class ProcessingViaFanCategory> extends CreateRecipeCategory { @@ -34,7 +32,7 @@ public abstract class ProcessingViaFanCategory> extends Crea public static Supplier getFan(String name) { return () -> AllBlocks.ENCASED_FAN.asStack() - .setHoverName(Lang.translateDirect("recipe." + name + ".fan").withStyle(style -> style.withItalic(false))); + .setHoverName(CreateLang.translateDirect("recipe." + name + ".fan").withStyle(style -> style.withItalic(false))); } @Override @@ -52,7 +50,7 @@ public abstract class ProcessingViaFanCategory> extends Crea @Override public void draw(T recipe, IRecipeSlotsView iRecipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) { renderWidgets(graphics, recipe, mouseX, mouseY); - + PoseStack matrixStack = graphics.pose(); matrixStack.pushPose(); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java index 63b48c62d6..f15482bda5 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java @@ -1,20 +1,18 @@ package com.simibubi.create.compat.jei.category; -import java.util.List; - -import javax.annotation.ParametersAreNonnullByDefault; - import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; import com.simibubi.create.content.kinetics.saw.CuttingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; - import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import net.minecraft.client.gui.GuiGraphics; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + @ParametersAreNonnullByDefault public class SawingCategory extends CreateRecipeCategory { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java index 5867ad153d..0055946559 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java @@ -15,14 +15,13 @@ import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; import com.simibubi.create.content.processing.sequenced.SequencedRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.simibubi.create.foundation.utility.CreateLang; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; @@ -76,8 +75,8 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory sequencedRecipe) { - return subCategories.computeIfAbsent(RegisteredObjects.getKeyOrThrow(sequencedRecipe.getRecipe() - .getSerializer()), + return subCategories.computeIfAbsent(CatnipServices.REGISTRIES.getKeyOrThrow(sequencedRecipe.getRecipe() + .getSerializer()), rl -> sequencedRecipe.getAsAssemblyRecipe() .getJEISubCategory() .get() @@ -101,7 +100,7 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory sequencedRecipe = sequence.get(i); SequencedAssemblySubCategory subCategory = getSubCategory(sequencedRecipe); int subWidth = subCategory.getWidth(); - MutableComponent component = Components.literal("" + romans[Math.min(i, 6)]); + MutableComponent component = Component.literal("" + romans[Math.min(i, 6)]); graphics.drawString(font, component, font.width(component) / -2 + subWidth / 2, 2, 0x888888, false); subCategory.draw(sequencedRecipe, graphics, mouseX, mouseY, i); matrixStack.translate(subWidth + margin, 0, 0); @@ -145,7 +144,7 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory getTooltipStrings(SequencedAssemblyRecipe recipe, IRecipeSlotsView iRecipeSlotsView, double mouseX, double mouseY) { List tooltip = new ArrayList<>(); - MutableComponent junk = Lang.translateDirect("recipe.assembly.junk"); + MutableComponent junk = CreateLang.translateDirect("recipe.assembly.junk"); boolean singleOutput = recipe.getOutputChance() == 1; boolean willRepeat = recipe.getLoops() > 1; @@ -167,7 +166,7 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY) { - tooltip.add(Lang.translateDirect("recipe.assembly.repeat", recipe.getLoops())); + tooltip.add(CreateLang.translateDirect("recipe.assembly.repeat", recipe.getLoops())); return tooltip; } @@ -185,7 +184,7 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory sequencedRecipe = sequence.get(i); SequencedAssemblySubCategory subCategory = getSubCategory(sequencedRecipe); if (relativeX >= 0 && relativeX < subCategory.getWidth()) { - tooltip.add(Lang.translateDirect("recipe.assembly.step", i + 1)); + tooltip.add(CreateLang.translateDirect("recipe.assembly.step", i + 1)); tooltip.add(sequencedRecipe.getAsAssemblyRecipe() .getDescriptionForAssembly() .plainCopy() @@ -201,7 +200,7 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory 0.99 ? ">99" : String.valueOf(Math.round(chance * 100)); - return Lang.translateDirect("recipe.processing.chance", number) + return CreateLang.translateDirect("recipe.processing.chance", number) .withStyle(ChatFormatting.GOLD); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java index 72bca8604a..a54dc1241b 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java @@ -14,7 +14,6 @@ import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.utility.RegisteredObjects; import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.forge.ForgeTypes; @@ -23,11 +22,11 @@ import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.runtime.IIngredientManager; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.PotionItem; import net.minecraft.world.item.crafting.Ingredient; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; @@ -88,8 +87,8 @@ public class SpoutCategory extends CreateRecipeCategory { return; Ingredient bucket = Ingredient.of(stack); - ResourceLocation itemName = RegisteredObjects.getKeyOrThrow(stack.getItem()); - ResourceLocation fluidName = RegisteredObjects.getKeyOrThrow(fluidCopy.getFluid()); + ResourceLocation itemName = CatnipServices.REGISTRIES.getKeyOrThrow(stack.getItem()); + ResourceLocation fluidName = CatnipServices.REGISTRIES.getKeyOrThrow(fluidCopy.getFluid()); consumer.accept(new ProcessingRecipeBuilder<>(FillingRecipe::new, Create.asResource("fill_" + itemName.getNamespace() + "_" + itemName.getPath() + "_with_" + fluidName.getNamespace() + "_" + fluidName.getPath())) diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java index c71ed7271f..5696e636b6 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java @@ -6,11 +6,11 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SpriteShiftEntry; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.LightTexture; @@ -82,7 +82,7 @@ public class AnimatedBlazeBurner extends AnimatedKinetics { uScroll = uScroll - Math.floor(uScroll); uScroll = uScroll * spriteWidth / 2; - CachedBufferer.partial(AllPartialModels.BLAZE_BURNER_FLAME, Blocks.AIR.defaultBlockState()) + CachedBuffers.partial(AllPartialModels.BLAZE_BURNER_FLAME, Blocks.AIR.defaultBlockState()) .shiftUVScrolling(spriteShift, (float) uScroll, (float) vScroll) .light(LightTexture.FULL_BRIGHT) .renderInto(matrixStack, graphics.bufferSource().getBuffer(RenderType.cutoutMipped())); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java index 513a1cbb81..9f087c1cec 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java @@ -3,7 +3,6 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; - import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java index 42f39d6d89..b0302fb69c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java @@ -5,8 +5,8 @@ import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.deployer.DeployerBlock; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java index 0261b64446..7c9d97818b 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedItemDrain.java @@ -5,8 +5,7 @@ import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.gui.UIRenderHelper; - +import net.createmod.catnip.gui.UIRenderHelper; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; @@ -41,7 +40,7 @@ public class AnimatedItemDrain extends AnimatedKinetics { matrixStack.scale(scale, scale, scale); float from = 2/16f; float to = 1f - from; - FluidRenderer.renderFluidBox(fluid, from, from, from, to, 3/4f, to, buffer, matrixStack, LightTexture.FULL_BRIGHT, false); + FluidRenderer.renderFluidBox(fluid.getFluid(), fluid.getAmount(), from, from, from, to, 3/4f, to, buffer, matrixStack, LightTexture.FULL_BRIGHT, false, true, fluid.getTag()); buffer.endBatch(); matrixStack.popPose(); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java index 16cde6f09c..82d554caf6 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java @@ -3,12 +3,12 @@ package com.simibubi.create.compat.jei.category.animations; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.gui.CustomLightingSettings; -import com.simibubi.create.foundation.gui.ILightingSettings; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import mezz.jei.api.gui.drawable.IDrawable; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.gui.ILightingSettings; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.core.Direction.Axis; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java index e6e83dd0f8..945b53d3de 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java @@ -4,7 +4,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.gui.AllGuiTextures; - import net.minecraft.client.gui.GuiGraphics; public class AnimatedMillstone extends AnimatedKinetics { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java index c752b1ca5b..b4c3398c62 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java @@ -4,8 +4,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java index c95d912fba..eac104209f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java @@ -4,8 +4,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java index 8cab72002e..db14904bb7 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java @@ -5,7 +5,6 @@ import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.saw.SawBlock; - import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java index fc4b51de1d..4827f6b9c9 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java @@ -9,14 +9,15 @@ import com.mojang.math.Axis; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.gui.UIRenderHelper; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource.BufferSource; import net.minecraft.util.Mth; + import net.minecraftforge.fluids.FluidStack; public class AnimatedSpout extends AnimatedKinetics { @@ -75,7 +76,8 @@ public class AnimatedSpout extends AnimatedKinetics { matrixStack.scale(16, 16, 16); float from = 3f / 16f; float to = 17f / 16f; - FluidRenderer.renderFluidBox(fluids.get(0), from, from, from, to, to, to, buffer, matrixStack, LightTexture.FULL_BRIGHT, false); + FluidStack fluidStack = fluids.get(0); + FluidRenderer.renderFluidBox(fluidStack.getFluid(), fluidStack.getAmount(), from, from, from, to, to, to, buffer, matrixStack, LightTexture.FULL_BRIGHT, false, true, fluidStack.getTag()); matrixStack.popPose(); float width = 1 / 128f * squeeze; @@ -85,8 +87,7 @@ public class AnimatedSpout extends AnimatedKinetics { matrixStack.translate(-0.5f, 0, -0.5f); from = -width / 2 + 0.5f; to = width / 2 + 0.5f; - FluidRenderer.renderFluidBox(fluids.get(0), from, 0, from, to, 2, to, buffer, matrixStack, LightTexture.FULL_BRIGHT, - false); + FluidRenderer.renderFluidBox(fluidStack.getFluid(), fluidStack.getAmount(), from, 0, from, to, 2, to, buffer, matrixStack, LightTexture.FULL_BRIGHT, false, true, fluidStack.getTag()); buffer.endBatch(); Lighting.setupFor3DItems(); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java index 2976ba5e8b..cd452c18a1 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java @@ -9,8 +9,7 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedSpout; import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe; import com.simibubi.create.content.processing.sequenced.SequencedRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; -import com.simibubi.create.foundation.utility.Lang; - +import com.simibubi.create.foundation.utility.CreateLang; import mezz.jei.api.forge.ForgeTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.builder.IRecipeSlotBuilder; @@ -114,7 +113,7 @@ public abstract class SequencedAssemblySubCategory { if (recipe.getAsAssemblyRecipe() instanceof DeployerApplicationRecipe deployerRecipe && deployerRecipe.shouldKeepHeldItem()) { slot.addTooltipCallback( - (recipeSlotView, tooltip) -> tooltip.add(1, Lang.translateDirect("recipe.deploying.not_consumed").withStyle(ChatFormatting.GOLD)) + (recipeSlotView, tooltip) -> tooltip.add(1, CreateLang.translateDirect("recipe.deploying.not_consumed").withStyle(ChatFormatting.GOLD)) ); } } diff --git a/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java b/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java index d3e3ea1ed0..f777cce56b 100644 --- a/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java +++ b/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java @@ -1,32 +1,25 @@ package com.simibubi.create.compat.tconstruct; -import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; -import com.simibubi.create.compat.Mods; +import com.simibubi.create.api.behaviour.spouting.BlockSpoutingBehaviour; import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.RegisteredObjects; import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -public class SpoutCasting extends BlockSpoutingBehaviour { - - static Boolean TICON_PRESENT = null; - - ResourceLocation TABLE = new ResourceLocation("tconstruct", "table"); - ResourceLocation BASIN = new ResourceLocation("tconstruct", "basin"); +public enum SpoutCasting implements BlockSpoutingBehaviour { + INSTANCE; @Override - public int fillBlock(Level level, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, - boolean simulate) { + public int fillBlock(Level level, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, boolean simulate) { if (!enabled()) return 0; @@ -41,9 +34,6 @@ public class SpoutCasting extends BlockSpoutingBehaviour { if (handler.getTanks() != 1) return 0; - ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(blockEntity.getType()); - if (!registryName.equals(TABLE) && !registryName.equals(BASIN)) - return 0; if (!handler.isFluidValid(0, availableFluid)) return 0; @@ -62,11 +52,6 @@ public class SpoutCasting extends BlockSpoutingBehaviour { } private boolean enabled() { - if (TICON_PRESENT == null) - TICON_PRESENT = Mods.TCONSTRUCT.isLoaded(); - if (!TICON_PRESENT) - return false; return AllConfigs.server().recipes.allowCastingBySpout.get(); } - } diff --git a/src/main/java/com/simibubi/create/compat/thresholdSwitch/FunctionalStorage.java b/src/main/java/com/simibubi/create/compat/thresholdSwitch/FunctionalStorage.java index a4421dbcd9..4441b2f022 100644 --- a/src/main/java/com/simibubi/create/compat/thresholdSwitch/FunctionalStorage.java +++ b/src/main/java/com/simibubi/create/compat/thresholdSwitch/FunctionalStorage.java @@ -1,8 +1,8 @@ package com.simibubi.create.compat.thresholdSwitch; import com.simibubi.create.compat.Mods; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.items.IItemHandler; @@ -11,7 +11,7 @@ public class FunctionalStorage implements ThresholdSwitchCompat { @Override public boolean isFromThisMod(BlockEntity blockEntity) { return blockEntity != null && Mods.FUNCTIONALSTORAGE.id() - .equals(RegisteredObjects.getKeyOrThrow(blockEntity.getType()) + .equals(CatnipServices.REGISTRIES.getKeyOrThrow(blockEntity.getType()) .getNamespace()); } diff --git a/src/main/java/com/simibubi/create/compat/thresholdSwitch/SophisticatedStorage.java b/src/main/java/com/simibubi/create/compat/thresholdSwitch/SophisticatedStorage.java index f8d5652e18..7638c9a801 100644 --- a/src/main/java/com/simibubi/create/compat/thresholdSwitch/SophisticatedStorage.java +++ b/src/main/java/com/simibubi/create/compat/thresholdSwitch/SophisticatedStorage.java @@ -1,8 +1,8 @@ package com.simibubi.create.compat.thresholdSwitch; import com.simibubi.create.compat.Mods; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.items.IItemHandler; @@ -13,7 +13,7 @@ public class SophisticatedStorage implements ThresholdSwitchCompat { if (be == null) return false; - String namespace = RegisteredObjects.getKeyOrThrow(be.getType()) + String namespace = CatnipServices.REGISTRIES.getKeyOrThrow(be.getType()) .getNamespace(); return diff --git a/src/main/java/com/simibubi/create/compat/thresholdSwitch/StorageDrawers.java b/src/main/java/com/simibubi/create/compat/thresholdSwitch/StorageDrawers.java index 895397a19c..0932ef6031 100644 --- a/src/main/java/com/simibubi/create/compat/thresholdSwitch/StorageDrawers.java +++ b/src/main/java/com/simibubi/create/compat/thresholdSwitch/StorageDrawers.java @@ -1,8 +1,8 @@ package com.simibubi.create.compat.thresholdSwitch; import com.simibubi.create.compat.Mods; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.items.IItemHandler; @@ -11,7 +11,7 @@ public class StorageDrawers implements ThresholdSwitchCompat { @Override public boolean isFromThisMod(BlockEntity blockEntity) { return blockEntity != null && Mods.STORAGEDRAWERS.id() - .equals(RegisteredObjects.getKeyOrThrow(blockEntity.getType()) + .equals(CatnipServices.REGISTRIES.getKeyOrThrow(blockEntity.getType()) .getNamespace()); } diff --git a/src/main/java/com/simibubi/create/compat/trainmap/FTBChunksTrainMap.java b/src/main/java/com/simibubi/create/compat/trainmap/FTBChunksTrainMap.java index f60921ae47..1234313176 100644 --- a/src/main/java/com/simibubi/create/compat/trainmap/FTBChunksTrainMap.java +++ b/src/main/java/com/simibubi/create/compat/trainmap/FTBChunksTrainMap.java @@ -4,11 +4,12 @@ import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.gui.RemovedGuiUtils; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import dev.ftb.mods.ftbchunks.client.gui.LargeMapScreen; import dev.ftb.mods.ftbchunks.client.gui.RegionMapPanel; +import dev.ftb.mods.ftblibrary.ui.BaseScreen; import dev.ftb.mods.ftblibrary.ui.ScreenWrapper; import dev.ftb.mods.ftblibrary.ui.Widget; import net.minecraft.client.Minecraft; @@ -31,14 +32,17 @@ public class FTBChunksTrainMap { public static void tick() { if (cancelTooltips > 0) cancelTooltips--; - if (!AllConfigs.client().showTrainMapOverlay.get() - || getAsLargeMapScreen(Minecraft.getInstance().screen) == null) { + + LargeMapScreen mapScreen = getAsLargeMapScreen(Minecraft.getInstance().screen); + + if (!AllConfigs.client().showTrainMapOverlay.get() || mapScreen == null) { if (requesting) TrainMapSyncClient.stopRequesting(); requesting = false; return; } - TrainMapManager.tick(); + + TrainMapManager.tick(mapScreen.currentDimension()); requesting = true; TrainMapSyncClient.requestData(); } @@ -138,7 +142,7 @@ public class FTBChunksTrainMap { return false; renderingTooltip = true; - RemovedGuiUtils.drawHoveringText(graphics, List.of(Lang.translate("train_map.toggle") + RemovedGuiUtils.drawHoveringText(graphics, List.of(CreateLang.translate("train_map.toggle") .component()), event.getMouseX(), event.getMouseY() + 20, largeMapScreen.width, largeMapScreen.height, 256, Minecraft.getInstance().font); renderingTooltip = false; @@ -149,7 +153,7 @@ public class FTBChunksTrainMap { private static LargeMapScreen getAsLargeMapScreen(Screen screen) { if (!(screen instanceof ScreenWrapper screenWrapper)) return null; - Object wrapped = ObfuscationReflectionHelper.getPrivateValue(ScreenWrapper.class, screenWrapper, "wrappedGui"); + BaseScreen wrapped = screenWrapper.getGui(); if (!(wrapped instanceof LargeMapScreen largeMapScreen)) return null; return largeMapScreen; diff --git a/src/main/java/com/simibubi/create/compat/trainmap/JourneyTrainMap.java b/src/main/java/com/simibubi/create/compat/trainmap/JourneyTrainMap.java index 74beed9a51..e05b26c369 100644 --- a/src/main/java/com/simibubi/create/compat/trainmap/JourneyTrainMap.java +++ b/src/main/java/com/simibubi/create/compat/trainmap/JourneyTrainMap.java @@ -5,7 +5,7 @@ import java.util.List; import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.gui.RemovedGuiUtils; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import journeymap.client.api.display.Context.UI; @@ -100,7 +100,7 @@ public class JourneyTrainMap { if (!TrainMapManager.isToggleWidgetHovered(mouseX, mouseY, 3, 30)) return false; - RemovedGuiUtils.drawHoveringText(graphics, List.of(Lang.translate("train_map.toggle") + RemovedGuiUtils.drawHoveringText(graphics, List.of(CreateLang.translate("train_map.toggle") .component()), mouseX, mouseY + 20, screen.width, screen.height, 256, Minecraft.getInstance().font); return true; } diff --git a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapManager.java b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapManager.java index f9afac323b..66c6b28a47 100644 --- a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapManager.java +++ b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapManager.java @@ -24,20 +24,20 @@ import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.content.trains.track.BezierConnection; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CClient; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.Rect2i; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; import net.minecraft.resources.ResourceKey; import net.minecraft.util.FastColor; @@ -48,18 +48,21 @@ import net.minecraft.world.phys.Vec3; public class TrainMapManager { public static void tick() { + tick(Minecraft.getInstance().level.dimension()); + } + + public static void tick(ResourceKey dimension) { TrainMapRenderer map = TrainMapRenderer.INSTANCE; - if (map.trackingVersion != CreateClient.RAILWAYS.version - || map.trackingDim != Minecraft.getInstance().level.dimension() + if (map.trackingVersion != CreateClient.RAILWAYS.version || map.trackingDim != dimension || map.trackingTheme != AllConfigs.client().trainMapColorTheme.get()) { - redrawAll(); + redrawAll(dimension); } } public static List renderAndPick(GuiGraphics graphics, int mouseX, int mouseY, float pt, boolean linearFiltering, Rect2i bounds) { Object hoveredElement = null; - + int offScreenMargin = 32; bounds.setX(bounds.getX() - offScreenMargin); bounds.setY(bounds.getY() - offScreenMargin); @@ -73,8 +76,9 @@ public class TrainMapManager { graphics.bufferSource() .endBatch(); - if (hoveredElement instanceof GlobalStation station) - return List.of(Components.literal(station.name)); + if (hoveredElement instanceof GlobalStation station) { + return List.of(Component.literal(station.name)); + } if (hoveredElement instanceof Train train) return listTrainDetails(train); @@ -107,9 +111,9 @@ public class TrainMapManager { public static boolean isToggleWidgetHovered(int mouseX, int mouseY, int x, int y) { if (CreateClient.RAILWAYS.trackNetworks.isEmpty()) return false; - if (mouseX < x || mouseX >= x + AllGuiTextures.TRAINMAP_TOGGLE_PANEL.width) + if (mouseX < x || mouseX >= x + AllGuiTextures.TRAINMAP_TOGGLE_PANEL.getWidth()) return false; - if (mouseY < y || mouseY >= y + AllGuiTextures.TRAINMAP_TOGGLE_PANEL.height) + if (mouseY < y || mouseY >= y + AllGuiTextures.TRAINMAP_TOGGLE_PANEL.getHeight()) return false; return true; } @@ -127,39 +131,39 @@ public class TrainMapManager { TrainState state = trainEntry.state; SignalState signalState = trainEntry.signalState; - Lang.text(train.name.getString()) + CreateLang.text(train.name.getString()) .color(bright) .addTo(output); if (!trainEntry.ownerName.isBlank()) - Lang.translate("train_map.train_owned_by", trainEntry.ownerName) + CreateLang.translate("train_map.train_owned_by", trainEntry.ownerName) .color(blue) .addTo(output); switch (state) { case CONDUCTOR_MISSING: - Lang.translate("train_map.conductor_missing") + CreateLang.translate("train_map.conductor_missing") .color(orange) .addTo(output); return output; case DERAILED: - Lang.translate("train_map.derailed") + CreateLang.translate("train_map.derailed") .color(orange) .addTo(output); return output; case NAVIGATION_FAILED: - Lang.translate("train_map.navigation_failed") + CreateLang.translate("train_map.navigation_failed") .color(orange) .addTo(output); return output; case SCHEDULE_INTERRUPTED: - Lang.translate("train_map.schedule_interrupted") + CreateLang.translate("train_map.schedule_interrupted") .color(orange) .addTo(output); return output; case RUNNING_MANUALLY: - Lang.translate("train_map.player_controlled") + CreateLang.translate("train_map.player_controlled") .color(blue) .addTo(output); break; @@ -174,23 +178,23 @@ public class TrainMapManager { if (!currentStation.isBlank()) { if (targetStationDistance == 0) - Lang.translate("train_map.train_at_station", currentStation) + CreateLang.translate("train_map.train_at_station", currentStation) .color(darkBlue) .addTo(output); else - Lang.translate("train_map.train_moving_to_station", currentStation, targetStationDistance) + CreateLang.translate("train_map.train_moving_to_station", currentStation, targetStationDistance) .color(darkBlue) .addTo(output); } if (signalState != SignalState.NOT_WAITING) { boolean chainSignal = signalState == SignalState.CHAIN_SIGNAL; - Lang.translate("train_map.waiting_at_signal") + CreateLang.translate("train_map.waiting_at_signal") .color(orange) .addTo(output); if (signalState == SignalState.WAITING_FOR_REDSTONE) - Lang.translate("train_map.redstone_powered") + CreateLang.translate("train_map.redstone_powered") .color(blue) .addTo(output); else { @@ -200,7 +204,7 @@ public class TrainMapManager { if (waitingFor != null) { Train trainWaitingFor = CreateClient.RAILWAYS.trains.get(waitingFor); if (trainWaitingFor != null) { - Lang.translate("train_map.for_other_train", trainWaitingFor.name.getString()) + CreateLang.translate("train_map.for_other_train", trainWaitingFor.name.getString()) .color(blue) .addTo(output); trainFound = true; @@ -209,11 +213,11 @@ public class TrainMapManager { if (!trainFound) { if (chainSignal) - Lang.translate("train_map.cannot_traverse_section") + CreateLang.translate("train_map.cannot_traverse_section") .color(blue) .addTo(output); else - Lang.translate("train_map.section_reserved") + CreateLang.translate("train_map.section_reserved") .color(blue) .addTo(output); } @@ -221,7 +225,7 @@ public class TrainMapManager { } if (trainEntry.fueled) - Lang.translate("train_map.fuel_boosted") + CreateLang.translate("train_map.fuel_boosted") .color(darkBlue) .addTo(output); @@ -276,9 +280,9 @@ public class TrainMapManager { pose.pushPose(); pose.translate(x - 2, y - 2, 5); - pose.translate(sprite.width / 2.0, sprite.height / 2.0, 0); + pose.translate(sprite.getWidth() / 2.0, sprite.getHeight() / 2.0, 0); pose.mulPose(Axis.ZP.rotationDegrees(90 * (rotation / 2))); - pose.translate(-sprite.width / 2.0, -sprite.height / 2.0, 0); + pose.translate(-sprite.getWidth() / 2.0, -sprite.getHeight() / 2.0, 0); sprite.render(graphics, 0, 0); sprite.render(graphics, 0, 0); @@ -408,8 +412,8 @@ public class TrainMapManager { int sheetX = col * 16 + colorCol * 128; int sheetY = row * 16 + colorRow * 64; - graphics.blit(sprite.location, positionX, positionY, sheetX, sheetY, 16, 16, sprite.width, - sprite.height); + graphics.blit(sprite.location, positionX, positionY, sheetX, sheetY, 16, 16, sprite.getWidth(), + sprite.getHeight()); } pose.popPose(); @@ -444,10 +448,10 @@ public class TrainMapManager { static final int PHASE_STRAIGHTS = 1; static final int PHASE_CURVES = 2; - public static void redrawAll() { + public static void redrawAll(ResourceKey dimension) { TrainMapRenderer map = TrainMapRenderer.INSTANCE; map.trackingVersion = CreateClient.RAILWAYS.version; - map.trackingDim = Minecraft.getInstance().level.dimension(); + map.trackingDim = dimension; map.trackingTheme = AllConfigs.client().trainMapColorTheme.get(); map.startDrawing(); diff --git a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapRenderer.java b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapRenderer.java index e5335bb4d0..a1c0d206ed 100644 --- a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapRenderer.java +++ b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapRenderer.java @@ -9,11 +9,11 @@ import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.foundation.render.RenderTypes; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.infrastructure.config.CClient; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.createmod.catnip.data.Couple; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.LightTexture; diff --git a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSync.java b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSync.java index 0de7783dbe..c79e23210f 100644 --- a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSync.java +++ b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSync.java @@ -1,13 +1,11 @@ package com.simibubi.create.compat.trainmap; import java.lang.ref.WeakReference; -import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.UUID; import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import com.simibubi.create.AllPackets; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Carriage; @@ -21,8 +19,9 @@ import com.simibubi.create.content.trains.signal.SignalBlock.SignalType; import com.simibubi.create.content.trains.signal.SignalBoundary; import com.simibubi.create.content.trains.signal.SignalEdgeGroup; import com.simibubi.create.content.trains.station.GlobalStation; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.TickBasedCache; +import net.createmod.catnip.data.Pair; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; @@ -30,6 +29,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.event.TickEvent.ServerTickEvent; import net.minecraftforge.network.PacketDistributor; @@ -169,9 +169,7 @@ public class TrainMapSync { } - public static Cache> requestingPlayers = CacheBuilder.newBuilder() - .expireAfterWrite(Duration.ofSeconds(1)) - .build(); + public static Cache> requestingPlayers = new TickBasedCache<>(20, false); public static void requestReceived(ServerPlayer sender) { boolean sendImmediately = requestingPlayers.getIfPresent(sender.getUUID()) == null; diff --git a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncClient.java b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncClient.java index 321b40fc4b..986df7d378 100644 --- a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncClient.java +++ b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncClient.java @@ -8,8 +8,9 @@ import java.util.UUID; import com.simibubi.create.AllPackets; import com.simibubi.create.compat.trainmap.TrainMapSync.TrainMapSyncEntry; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Pair; + +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Pair; public class TrainMapSyncClient { @@ -34,7 +35,7 @@ public class TrainMapSyncClient { public static void receive(TrainMapSyncPacket packet) { if (ticks == 0) return; - + lastPacket = AnimationTickHolder.getTicks(); lastPacket += AnimationTickHolder.getPartialTicks(); diff --git a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncPacket.java b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncPacket.java index 0c37037596..269449fc3e 100644 --- a/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncPacket.java +++ b/src/main/java/com/simibubi/create/compat/trainmap/TrainMapSyncPacket.java @@ -7,9 +7,10 @@ import java.util.UUID; import com.simibubi.create.compat.trainmap.TrainMapSync.TrainMapSyncEntry; import com.simibubi.create.content.trains.graph.DimensionPalette; import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Pair; import net.minecraft.network.FriendlyByteBuf; + import net.minecraftforge.network.NetworkEvent.Context; public class TrainMapSyncPacket extends SimplePacketBase { diff --git a/src/main/java/com/simibubi/create/content/contraptions/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/AbstractContraptionEntity.java index 3e254604d5..73b3cd1584 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/AbstractContraptionEntity.java @@ -15,16 +15,15 @@ import org.apache.commons.lang3.tuple.MutablePair; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllItems; -import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.Create; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceMovement; import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; import com.simibubi.create.content.contraptions.actors.trainControls.ControlsStopControllingPacket; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.data.ContraptionSyncLimiting; import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.mounted.MountedContraption; @@ -37,9 +36,10 @@ import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import dev.engine_room.flywheel.api.backend.BackendManager; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -72,6 +72,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.entity.IEntityAdditionalSpawnData; @@ -242,8 +243,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit Vec3 transformedVector = toGlobalVector(Vec3.atLowerCornerOf(seat) .add(.5, passenger.getMyRidingOffset() + ySize - .15f, .5), partialTicks) - .add(VecHelper.getCenterOf(BlockPos.ZERO)) - .subtract(0.5, ySize, 0.5); + .add(VecHelper.getCenterOf(BlockPos.ZERO)) + .subtract(0.5, ySize, 0.5); return transformedVector; } @@ -253,7 +254,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return true; return contraption.getSeatMapping() .size() < contraption.getSeats() - .size(); + .size(); } public Component getContraptionName() { @@ -285,7 +286,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } public boolean handlePlayerInteraction(Player player, BlockPos localPos, Direction side, - InteractionHand interactionHand) { + InteractionHand interactionHand) { int indexOfSeat = contraption.getSeats() .indexOf(localPos); if (indexOfSeat == -1 || AllItems.WRENCH.isIn(player.getItemInHand(interactionHand))) { @@ -380,7 +381,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit if (level().isClientSide()) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - if (!contraption.deferInvalidate) + // The visual will handle this with flywheel on. + if (!contraption.deferInvalidate || BackendManager.isBackendOn()) return; contraption.deferInvalidate = false; ContraptionRenderInfo.invalidate(contraption); @@ -445,7 +447,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit for (MutablePair pair : contraption.getActors()) { MovementContext context = pair.right; StructureBlockInfo blockInfo = pair.left; - MovementBehaviour actor = AllMovementBehaviours.getBehaviour(blockInfo.state()); + MovementBehaviour actor = MovementBehaviour.REGISTRY.get(blockInfo.state()); if (actor == null) continue; @@ -484,11 +486,10 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit skipActorStop = false; for (Entity entity : getPassengers()) { - if (!(entity instanceof OrientedContraptionEntity)) + if (!(entity instanceof OrientedContraptionEntity orientedCE)) continue; if (!contraption.stabilizedSubContraptions.containsKey(entity.getUUID())) continue; - OrientedContraptionEntity orientedCE = (OrientedContraptionEntity) entity; if (orientedCE.contraption != null && orientedCE.contraption.stalled) { contraption.stalled = true; break; @@ -509,7 +510,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit for (MutablePair pair : contraption.getActors()) { MovementContext context = pair.right; StructureBlockInfo blockInfo = pair.left; - MovementBehaviour actor = AllMovementBehaviours.getBehaviour(blockInfo.state()); + MovementBehaviour actor = MovementBehaviour.REGISTRY.get(blockInfo.state()); if (actor instanceof PortableStorageInterfaceMovement && isActorActive(context, actor)) if (context.position != null) actor.visitNewPosition(context, BlockPos.containing(context.position)); @@ -526,7 +527,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } protected boolean shouldActorTrigger(MovementContext context, StructureBlockInfo blockInfo, MovementBehaviour actor, - Vec3 actorPosition, BlockPos gridPosition) { + Vec3 actorPosition, BlockPos gridPosition) { Vec3 previousPosition = context.position; if (previousPosition == null) return false; @@ -612,11 +613,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit CompoundTag compound = new CompoundTag(); writeAdditional(compound, true); - if (ContraptionData.isTooLargeForSync(compound)) { - String info = getContraption().getType().id + " @" + position() + " (" + getStringUUID() + ")"; - Create.LOGGER.warn("Could not send Contraption Spawn Data (Packet too big): " + info); - compound = null; - } + if (ContraptionSyncLimiting.isTooLargeForSync(compound)) + compound = null; // don't sync contraption data buffer.writeNbt(compound); } @@ -731,7 +729,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } @Override - protected void doWaterSplashEffect() {} + protected void doWaterSplashEffect() { + } public Contraption getContraption() { return contraption; @@ -798,7 +797,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @Override // Make sure nothing can move contraptions out of the way - public void setDeltaMovement(Vec3 motionIn) {} + public void setDeltaMovement(Vec3 motionIn) { + } @Override public PushReaction getPistonPushReaction() { @@ -878,7 +878,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit public float yRotation = 0; public float zRotation = 0; public float secondYRotation = 0; - + Matrix3d matrix; public Matrix3d asMatrix() { @@ -925,6 +925,12 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit // Contraptions no longer catch fire } + // Contraptions shouldn't activate pressure plates and tripwires + @Override + public boolean isIgnoringBlockTriggers() { + return true; + } + public boolean isReadyForRender() { return initialized; } @@ -933,4 +939,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return isAlive() || level().isClientSide() ? staleTicks > 0 : false; } + public boolean isPrevPosInvalid() { + return prevPosInvalid; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/AssemblyException.java b/src/main/java/com/simibubi/create/content/contraptions/AssemblyException.java index 8bb1675d44..5e53e00329 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/AssemblyException.java +++ b/src/main/java/com/simibubi/create/content/contraptions/AssemblyException.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.contraptions; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; @@ -45,7 +45,7 @@ public class AssemblyException extends Exception { } public AssemblyException(String langKey, Object... objects) { - this(Lang.translateDirect("gui.assembly.exception." + langKey, objects)); + this(CreateLang.translateDirect("gui.assembly.exception." + langKey, objects)); } public static AssemblyException unmovableBlock(BlockPos pos, BlockState state) { @@ -72,7 +72,7 @@ public class AssemblyException extends Exception { public static AssemblyException noPistonPoles() { return new AssemblyException("noPistonPoles"); } - + public static AssemblyException notEnoughSails(int sails) { return new AssemblyException("not_enough_sails", sails, AllConfigs.server().kinetics.minimumWindmillSails.get()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/BlockMovementChecks.java b/src/main/java/com/simibubi/create/content/contraptions/BlockMovementChecks.java deleted file mode 100644 index d602238779..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/BlockMovementChecks.java +++ /dev/null @@ -1,437 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.api.connectivity.ConnectivityHandler; -import com.simibubi.create.content.contraptions.actors.AttachedActorBlock; -import com.simibubi.create.content.contraptions.actors.harvester.HarvesterBlock; -import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceBlock; -import com.simibubi.create.content.contraptions.bearing.ClockworkBearingBlock; -import com.simibubi.create.content.contraptions.bearing.ClockworkBearingBlockEntity; -import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlock; -import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlockEntity; -import com.simibubi.create.content.contraptions.bearing.SailBlock; -import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; -import com.simibubi.create.content.contraptions.chassis.StickerBlock; -import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlock; -import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock; -import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.content.contraptions.pulley.PulleyBlock; -import com.simibubi.create.content.contraptions.pulley.PulleyBlockEntity; -import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; -import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock; -import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock; -import com.simibubi.create.content.fluids.tank.FluidTankBlock; -import com.simibubi.create.content.kinetics.crank.HandCrankBlock; -import com.simibubi.create.content.kinetics.fan.NozzleBlock; -import com.simibubi.create.content.logistics.vault.ItemVaultBlock; -import com.simibubi.create.content.redstone.link.RedstoneLinkBlock; -import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; -import com.simibubi.create.content.trains.station.StationBlock; -import com.simibubi.create.content.trains.track.ITrackBlock; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.BasePressurePlateBlock; -import net.minecraft.world.level.block.BaseRailBlock; -import net.minecraft.world.level.block.BedBlock; -import net.minecraft.world.level.block.BellBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.DiodeBlock; -import net.minecraft.world.level.block.DoorBlock; -import net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock; -import net.minecraft.world.level.block.FlowerPotBlock; -import net.minecraft.world.level.block.GrindstoneBlock; -import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.LadderBlock; -import net.minecraft.world.level.block.RedStoneWireBlock; -import net.minecraft.world.level.block.RedstoneWallTorchBlock; -import net.minecraft.world.level.block.SignBlock; -import net.minecraft.world.level.block.StandingSignBlock; -import net.minecraft.world.level.block.TorchBlock; -import net.minecraft.world.level.block.WallSignBlock; -import net.minecraft.world.level.block.WallTorchBlock; -import net.minecraft.world.level.block.WoolCarpetBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.AttachFace; -import net.minecraft.world.level.block.state.properties.BedPart; -import net.minecraft.world.level.block.state.properties.BellAttachType; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.material.PushReaction; - -public class BlockMovementChecks { - - private static final List MOVEMENT_NECESSARY_CHECKS = new ArrayList<>(); - private static final List MOVEMENT_ALLOWED_CHECKS = new ArrayList<>(); - private static final List BRITTLE_CHECKS = new ArrayList<>(); - private static final List ATTACHED_CHECKS = new ArrayList<>(); - private static final List NOT_SUPPORTIVE_CHECKS = new ArrayList<>(); - - // Registration - // Add new checks to the front instead of the end - - public static void registerMovementNecessaryCheck(MovementNecessaryCheck check) { - MOVEMENT_NECESSARY_CHECKS.add(0, check); - } - - public static void registerMovementAllowedCheck(MovementAllowedCheck check) { - MOVEMENT_ALLOWED_CHECKS.add(0, check); - } - - public static void registerBrittleCheck(BrittleCheck check) { - BRITTLE_CHECKS.add(0, check); - } - - public static void registerAttachedCheck(AttachedCheck check) { - ATTACHED_CHECKS.add(0, check); - } - - public static void registerNotSupportiveCheck(NotSupportiveCheck check) { - NOT_SUPPORTIVE_CHECKS.add(0, check); - } - - public static void registerAllChecks(AllChecks checks) { - registerMovementNecessaryCheck(checks); - registerMovementAllowedCheck(checks); - registerBrittleCheck(checks); - registerAttachedCheck(checks); - registerNotSupportiveCheck(checks); - } - - // Actual check methods - - public static boolean isMovementNecessary(BlockState state, Level world, BlockPos pos) { - for (MovementNecessaryCheck check : MOVEMENT_NECESSARY_CHECKS) { - CheckResult result = check.isMovementNecessary(state, world, pos); - if (result != CheckResult.PASS) { - return result.toBoolean(); - } - } - return isMovementNecessaryFallback(state, world, pos); - } - - public static boolean isMovementAllowed(BlockState state, Level world, BlockPos pos) { - for (MovementAllowedCheck check : MOVEMENT_ALLOWED_CHECKS) { - CheckResult result = check.isMovementAllowed(state, world, pos); - if (result != CheckResult.PASS) { - return result.toBoolean(); - } - } - return isMovementAllowedFallback(state, world, pos); - } - - /** - * Brittle blocks will be collected first, as they may break when other blocks - * are removed before them - */ - public static boolean isBrittle(BlockState state) { - for (BrittleCheck check : BRITTLE_CHECKS) { - CheckResult result = check.isBrittle(state); - if (result != CheckResult.PASS) { - return result.toBoolean(); - } - } - return isBrittleFallback(state); - } - - /** - * Attached blocks will move if blocks they are attached to are moved - */ - public static boolean isBlockAttachedTowards(BlockState state, Level world, BlockPos pos, Direction direction) { - for (AttachedCheck check : ATTACHED_CHECKS) { - CheckResult result = check.isBlockAttachedTowards(state, world, pos, direction); - if (result != CheckResult.PASS) { - return result.toBoolean(); - } - } - return isBlockAttachedTowardsFallback(state, world, pos, direction); - } - - /** - * Non-Supportive blocks will not continue a chain of blocks picked up by e.g. a - * piston - */ - public static boolean isNotSupportive(BlockState state, Direction facing) { - for (NotSupportiveCheck check : NOT_SUPPORTIVE_CHECKS) { - CheckResult result = check.isNotSupportive(state, facing); - if (result != CheckResult.PASS) { - return result.toBoolean(); - } - } - return isNotSupportiveFallback(state, facing); - } - - // Fallback checks - - private static boolean isMovementNecessaryFallback(BlockState state, Level world, BlockPos pos) { - if (isBrittle(state)) - return true; - if (AllBlockTags.MOVABLE_EMPTY_COLLIDER.matches(state)) - return true; - if (state.getCollisionShape(world, pos) - .isEmpty()) - return false; - if (state.canBeReplaced()) - return false; - return true; - } - - private static boolean isMovementAllowedFallback(BlockState state, Level world, BlockPos pos) { - Block block = state.getBlock(); - if (block instanceof AbstractChassisBlock) - return true; - if (state.getDestroySpeed(world, pos) == -1) - return false; - if (AllBlockTags.RELOCATION_NOT_SUPPORTED.matches(state)) - return false; - if (AllBlockTags.NON_MOVABLE.matches(state)) - return false; - if (ContraptionMovementSetting.get(state.getBlock()) == ContraptionMovementSetting.UNMOVABLE) - return false; - - // Move controllers only when they aren't moving - if (block instanceof MechanicalPistonBlock && state.getValue(MechanicalPistonBlock.STATE) != PistonState.MOVING) - return true; - if (block instanceof MechanicalBearingBlock) { - BlockEntity be = world.getBlockEntity(pos); - if (be instanceof MechanicalBearingBlockEntity) - return !((MechanicalBearingBlockEntity) be).isRunning(); - } - if (block instanceof ClockworkBearingBlock) { - BlockEntity be = world.getBlockEntity(pos); - if (be instanceof ClockworkBearingBlockEntity) - return !((ClockworkBearingBlockEntity) be).isRunning(); - } - if (block instanceof PulleyBlock) { - BlockEntity be = world.getBlockEntity(pos); - if (be instanceof PulleyBlockEntity) - return !((PulleyBlockEntity) be).running; - } - - if (AllBlocks.BELT.has(state)) - return true; - if (state.getBlock() instanceof GrindstoneBlock) - return true; - if (state.getBlock() instanceof ITrackBlock) - return false; - if (state.getBlock() instanceof StationBlock) - return false; - return state.getPistonPushReaction() != PushReaction.BLOCK; - } - - private static boolean isBrittleFallback(BlockState state) { - Block block = state.getBlock(); - if (state.hasProperty(BlockStateProperties.HANGING)) - return true; - - if (block instanceof LadderBlock) - return true; - if (block instanceof TorchBlock) - return true; - if (block instanceof SignBlock) - return true; - if (block instanceof BasePressurePlateBlock) - return true; - if (block instanceof FaceAttachedHorizontalDirectionalBlock && !(block instanceof GrindstoneBlock)) - return true; - if (block instanceof CartAssemblerBlock) - return false; - if (block instanceof BaseRailBlock) - return true; - if (block instanceof DiodeBlock) - return true; - if (block instanceof RedStoneWireBlock) - return true; - if (block instanceof WoolCarpetBlock) - return true; - if (block instanceof WhistleBlock) - return true; - if (block instanceof WhistleExtenderBlock) - return true; - return AllBlockTags.BRITTLE.matches(state); - } - - private static boolean isBlockAttachedTowardsFallback(BlockState state, Level world, BlockPos pos, - Direction direction) { - Block block = state.getBlock(); - if (block instanceof LadderBlock) - return state.getValue(LadderBlock.FACING) == direction.getOpposite(); - if (block instanceof WallTorchBlock) - return state.getValue(WallTorchBlock.FACING) == direction.getOpposite(); - if (block instanceof WallSignBlock) - return state.getValue(WallSignBlock.FACING) == direction.getOpposite(); - if (block instanceof StandingSignBlock) - return direction == Direction.DOWN; - if (block instanceof BasePressurePlateBlock) - return direction == Direction.DOWN; - if (block instanceof DoorBlock) { - if (state.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER && direction == Direction.UP) - return true; - return direction == Direction.DOWN; - } - if (block instanceof BedBlock) { - Direction facing = state.getValue(BedBlock.FACING); - if (state.getValue(BedBlock.PART) == BedPart.HEAD) - facing = facing.getOpposite(); - return direction == facing; - } - if (block instanceof RedstoneLinkBlock) - return direction.getOpposite() == state.getValue(RedstoneLinkBlock.FACING); - if (block instanceof FlowerPotBlock) - return direction == Direction.DOWN; - if (block instanceof DiodeBlock) - return direction == Direction.DOWN; - if (block instanceof RedStoneWireBlock) - return direction == Direction.DOWN; - if (block instanceof WoolCarpetBlock) - return direction == Direction.DOWN; - if (block instanceof RedstoneWallTorchBlock) - return state.getValue(RedstoneWallTorchBlock.FACING) == direction.getOpposite(); - if (block instanceof TorchBlock) - return direction == Direction.DOWN; - if (block instanceof FaceAttachedHorizontalDirectionalBlock) { - AttachFace attachFace = state.getValue(FaceAttachedHorizontalDirectionalBlock.FACE); - if (attachFace == AttachFace.CEILING) - return direction == Direction.UP; - if (attachFace == AttachFace.FLOOR) - return direction == Direction.DOWN; - if (attachFace == AttachFace.WALL) - return direction.getOpposite() == state.getValue(FaceAttachedHorizontalDirectionalBlock.FACING); - } - if (state.hasProperty(BlockStateProperties.HANGING)) - return direction == (state.getValue(BlockStateProperties.HANGING) ? Direction.UP : Direction.DOWN); - if (block instanceof BaseRailBlock) - return direction == Direction.DOWN; - if (block instanceof AttachedActorBlock) - return direction == state.getValue(HarvesterBlock.FACING) - .getOpposite(); - if (block instanceof HandCrankBlock) - return direction == state.getValue(HandCrankBlock.FACING) - .getOpposite(); - if (block instanceof NozzleBlock) - return direction == state.getValue(NozzleBlock.FACING) - .getOpposite(); - if (block instanceof BellBlock) { - BellAttachType attachment = state.getValue(BlockStateProperties.BELL_ATTACHMENT); - if (attachment == BellAttachType.FLOOR) - return direction == Direction.DOWN; - if (attachment == BellAttachType.CEILING) - return direction == Direction.UP; - return direction == state.getValue(HorizontalDirectionalBlock.FACING); - } - if (state.getBlock() instanceof SailBlock) - return direction.getAxis() != state.getValue(SailBlock.FACING) - .getAxis(); - if (state.getBlock() instanceof FluidTankBlock) - return ConnectivityHandler.isConnected(world, pos, pos.relative(direction)); - if (state.getBlock() instanceof ItemVaultBlock) - return ConnectivityHandler.isConnected(world, pos, pos.relative(direction)); - if (AllBlocks.STICKER.has(state) && state.getValue(StickerBlock.EXTENDED)) { - return direction == state.getValue(StickerBlock.FACING) - && !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite()); - } - if (block instanceof AbstractBogeyBlock bogey) - return bogey.getStickySurfaces(world, pos, state) - .contains(direction); - if (block instanceof WhistleBlock) - return direction == (state.getValue(WhistleBlock.WALL) ? state.getValue(WhistleBlock.FACING) - : Direction.DOWN); - if (block instanceof WhistleExtenderBlock) - return direction == Direction.DOWN; - return false; - } - - private static boolean isNotSupportiveFallback(BlockState state, Direction facing) { - if (AllBlocks.MECHANICAL_DRILL.has(state)) - return state.getValue(BlockStateProperties.FACING) == facing; - if (AllBlocks.MECHANICAL_BEARING.has(state)) - return state.getValue(BlockStateProperties.FACING) == facing; - - if (AllBlocks.CART_ASSEMBLER.has(state)) - return Direction.DOWN == facing; - if (AllBlocks.MECHANICAL_SAW.has(state)) - return state.getValue(BlockStateProperties.FACING) == facing; - if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state)) - return state.getValue(PortableStorageInterfaceBlock.FACING) == facing; - if (state.getBlock() instanceof AttachedActorBlock && !AllBlocks.MECHANICAL_ROLLER.has(state)) - return state.getValue(BlockStateProperties.HORIZONTAL_FACING) == facing; - if (AllBlocks.ROPE_PULLEY.has(state)) - return facing == Direction.DOWN; - if (state.getBlock() instanceof WoolCarpetBlock) - return facing == Direction.UP; - if (state.getBlock() instanceof SailBlock) - return facing.getAxis() == state.getValue(SailBlock.FACING) - .getAxis(); - if (AllBlocks.PISTON_EXTENSION_POLE.has(state)) - return facing.getAxis() != state.getValue(BlockStateProperties.FACING) - .getAxis(); - if (AllBlocks.MECHANICAL_PISTON_HEAD.has(state)) - return facing.getAxis() != state.getValue(BlockStateProperties.FACING) - .getAxis(); - if (AllBlocks.STICKER.has(state) && !state.getValue(StickerBlock.EXTENDED)) - return facing == state.getValue(StickerBlock.FACING); - if (state.getBlock() instanceof SlidingDoorBlock) - return false; - return isBrittle(state); - } - - // Check classes - - public static interface MovementNecessaryCheck { - public CheckResult isMovementNecessary(BlockState state, Level world, BlockPos pos); - } - - public static interface MovementAllowedCheck { - public CheckResult isMovementAllowed(BlockState state, Level world, BlockPos pos); - } - - public static interface BrittleCheck { - /** - * Brittle blocks will be collected first, as they may break when other blocks - * are removed before them - */ - public CheckResult isBrittle(BlockState state); - } - - public static interface AttachedCheck { - /** - * Attached blocks will move if blocks they are attached to are moved - */ - public CheckResult isBlockAttachedTowards(BlockState state, Level world, BlockPos pos, Direction direction); - } - - public static interface NotSupportiveCheck { - /** - * Non-Supportive blocks will not continue a chain of blocks picked up by e.g. a - * piston - */ - public CheckResult isNotSupportive(BlockState state, Direction direction); - } - - public static interface AllChecks - extends MovementNecessaryCheck, MovementAllowedCheck, BrittleCheck, AttachedCheck, NotSupportiveCheck { - } - - public static enum CheckResult { - SUCCESS, FAIL, PASS; - - public Boolean toBoolean() { - return this == PASS ? null : (this == SUCCESS ? true : false); - } - - public static CheckResult of(boolean b) { - return b ? SUCCESS : FAIL; - } - - public static CheckResult of(Boolean b) { - return b == null ? PASS : (b ? SUCCESS : FAIL); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java index 8d9b8c3340..8e5c1df2f4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -29,8 +29,11 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllInteractionBehaviours; -import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.AllTags.AllContraptionTypeTags; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; +import com.simibubi.create.api.contraption.BlockMovementChecks; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement; import com.simibubi.create.content.contraptions.actors.harvester.HarvesterMovementBehaviour; import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; @@ -40,9 +43,7 @@ import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlock; import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlock; import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlockEntity; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.content.contraptions.chassis.ChassisBlockEntity; import com.simibubi.create.content.contraptions.chassis.StickerBlock; @@ -61,34 +62,37 @@ import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity; import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; import com.simibubi.create.content.kinetics.steamEngine.PoweredShaftBlockEntity; import com.simibubi.create.content.logistics.crate.CreativeCrateBlockEntity; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlockEntity; import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.BBHelper; -import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.ICoordinate; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.NBTProcessors; -import com.simibubi.create.foundation.utility.UniqueLinkedList; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.UniqueLinkedList; +import net.createmod.catnip.math.BBHelper; +import net.createmod.catnip.math.BlockFace; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.nbt.NBTProcessors; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.HolderGetter; +import net.minecraft.core.Vec3i; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; import net.minecraft.network.protocol.game.DebugPackets; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.village.poi.PoiTypes; @@ -100,6 +104,7 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.ButtonBlock; import net.minecraft.world.level.block.ChestBlock; import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.PressurePlateBlock; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.SimpleWaterloggedBlock; @@ -120,11 +125,8 @@ import net.minecraft.world.phys.shapes.BooleanOp; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.client.model.data.ModelData; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; import net.minecraftforge.registries.GameData; public abstract class Contraption { @@ -139,6 +141,7 @@ public abstract class Contraption { public boolean disassembled; protected Map blocks; + protected Map updateTags; protected List> actors; protected Map interactors; protected List disabledActors; @@ -166,6 +169,7 @@ public abstract class Contraption { public Contraption() { blocks = new HashMap<>(); + updateTags = new HashMap<>(); seats = new ArrayList<>(); actors = new ArrayList<>(); disabledActors = new ArrayList<>(); @@ -205,7 +209,7 @@ public abstract class Contraption { } protected boolean addToInitialFrontier(Level world, BlockPos pos, Direction forcedDirection, - Queue frontier) throws AssemblyException { + Queue frontier) throws AssemblyException { return true; } @@ -264,7 +268,7 @@ public abstract class Contraption { stabilizedSubContraptions.put(movedContraption.getUUID(), new BlockFace(toLocalPos(pos), face)); } - storage.createHandlers(); + storage.initialize(); gatherBBsOffThread(); } @@ -296,9 +300,11 @@ public abstract class Contraption { } } - /** move the first block in frontier queue */ + /** + * move the first block in frontier queue + */ protected boolean moveBlock(Level world, @Nullable Direction forcedDirection, Queue frontier, - Set visited) throws AssemblyException { + Set visited) throws AssemblyException { BlockPos pos = frontier.poll(); if (pos == null) return false; @@ -322,7 +328,7 @@ public abstract class Contraption { if (AllBlocks.BELT.has(state)) moveBelt(pos, frontier, visited, state); - if (AllBlocks.WINDMILL_BEARING.has(state) && world.getBlockEntity(pos)instanceof WindmillBearingBlockEntity wbbe) + if (AllBlocks.WINDMILL_BEARING.has(state) && world.getBlockEntity(pos) instanceof WindmillBearingBlockEntity wbbe) wbbe.disassembleForMovement(); if (AllBlocks.GANTRY_CARRIAGE.has(state)) @@ -339,6 +345,9 @@ public abstract class Contraption { frontier.add(attached); } + if (world.getBlockEntity(pos) instanceof ChainConveyorBlockEntity ccbe) + ccbe.notifyConnectedToValidate(); + // Double Chest halves stick together if (state.hasProperty(ChestBlock.TYPE) && state.hasProperty(ChestBlock.FACING) && state.getValue(ChestBlock.TYPE) != ChestType.SINGLE) { @@ -349,7 +358,7 @@ public abstract class Contraption { } // Bogeys tend to have sticky sides - if (state.getBlock()instanceof AbstractBogeyBlock bogey) + if (state.getBlock() instanceof AbstractBogeyBlock bogey) for (Direction d : bogey.getStickySurfaces(world, pos, state)) if (!visited.contains(pos.relative(d))) frontier.add(pos.relative(d)); @@ -421,7 +430,7 @@ public abstract class Contraption { frontier.add(offsetPos); } - addBlock(pos, capture(world, pos)); + addBlock(world, pos, capture(world, pos)); if (blocks.size() <= AllConfigs.server().kinetics.maxBlocksMoved.get()) return true; else @@ -429,7 +438,7 @@ public abstract class Contraption { } protected void movePistonHead(Level world, BlockPos pos, Queue frontier, Set visited, - BlockState state) { + BlockState state) { Direction direction = state.getValue(MechanicalPistonHeadBlock.FACING); BlockPos offset = pos.relative(direction.getOpposite()); if (!visited.contains(offset)) { @@ -452,7 +461,7 @@ public abstract class Contraption { } protected void movePistonPole(Level world, BlockPos pos, Queue frontier, Set visited, - BlockState state) { + BlockState state) { for (Direction d : Iterate.directionsInAxis(state.getValue(PistonExtensionPoleBlock.FACING) .getAxis())) { BlockPos offset = pos.relative(d); @@ -475,7 +484,7 @@ public abstract class Contraption { } protected void moveGantryPinion(Level world, BlockPos pos, Queue frontier, Set visited, - BlockState state) { + BlockState state) { BlockPos offset = pos.relative(state.getValue(GantryCarriageBlock.FACING)); if (!visited.contains(offset)) frontier.add(offset); @@ -491,7 +500,7 @@ public abstract class Contraption { } protected void moveGantryShaft(Level world, BlockPos pos, Queue frontier, Set visited, - BlockState state) { + BlockState state) { for (Direction d : Iterate.directions) { BlockPos offset = pos.relative(d); if (!visited.contains(offset)) { @@ -560,12 +569,12 @@ public abstract class Contraption { frontier.add(ropePos); break; } - addBlock(ropePos, capture(world, ropePos)); + addBlock(world, ropePos, capture(world, ropePos)); } } private boolean moveMechanicalPiston(Level world, BlockPos pos, Queue frontier, Set visited, - BlockState state) throws AssemblyException { + BlockState state) throws AssemblyException { Direction direction = state.getValue(MechanicalPistonBlock.FACING); PistonState pistonState = state.getValue(MechanicalPistonBlock.STATE); if (pistonState == PistonState.MOVING) @@ -589,11 +598,10 @@ public abstract class Contraption { } private boolean moveChassis(Level world, BlockPos pos, Direction movementDirection, Queue frontier, - Set visited) { + Set visited) { BlockEntity be = world.getBlockEntity(pos); - if (!(be instanceof ChassisBlockEntity)) + if (!(be instanceof ChassisBlockEntity chassis)) return false; - ChassisBlockEntity chassis = (ChassisBlockEntity) be; chassis.addAttachedChasses(frontier, visited); List includedBlockPositions = chassis.getIncludedBlockPositions(movementDirection, false); if (includedBlockPositions == null) @@ -610,7 +618,7 @@ public abstract class Contraption { blockstate = blockstate.setValue(RedstoneContactBlock.POWERED, true); if (AllBlocks.POWERED_SHAFT.has(blockstate)) blockstate = BlockHelper.copyProperties(blockstate, AllBlocks.SHAFT.getDefaultState()); - if (blockstate.getBlock() instanceof ControlsBlock && getType() == ContraptionType.CARRIAGE) + if (blockstate.getBlock() instanceof ControlsBlock && AllContraptionTypeTags.OPENS_CONTROLS.matches(this.getType())) blockstate = blockstate.setValue(ControlsBlock.OPEN, true); if (blockstate.hasProperty(SlidingDoorBlock.VISIBLE)) blockstate = blockstate.setValue(SlidingDoorBlock.VISIBLE, false); @@ -626,34 +634,46 @@ public abstract class Contraption { BlockEntity blockEntity = world.getBlockEntity(pos); if (blockEntity instanceof PoweredShaftBlockEntity) blockEntity = AllBlockEntityTypes.BRACKETED_KINETIC.create(pos, blockstate); + if (blockEntity instanceof FactoryPanelBlockEntity fpbe) + fpbe.writeSafe(compoundnbt); + return Pair.of(new StructureBlockInfo(pos, blockstate, compoundnbt), blockEntity); } - protected void addBlock(BlockPos pos, Pair pair) { + protected void addBlock(Level level, BlockPos pos, Pair pair) { StructureBlockInfo captured = pair.getKey(); BlockPos localPos = pos.subtract(anchor); - StructureBlockInfo structureBlockInfo = new StructureBlockInfo(localPos, captured.state(), captured.nbt()); + BlockState state = captured.state(); + StructureBlockInfo structureBlockInfo = new StructureBlockInfo(localPos, state, captured.nbt()); if (blocks.put(localPos, structureBlockInfo) != null) return; bounds = bounds.minmax(new AABB(localPos)); BlockEntity be = pair.getValue(); - storage.addBlock(localPos, be); + + if (be != null) { + CompoundTag updateTag = be.getUpdateTag(); + // empty tags are intentionally kept, see writeBlocksCompound + // for testing, this line can be commented to emulate legacy behavior + updateTags.put(localPos, updateTag); + } + + storage.addBlock(level, state, pos, localPos, be); captureMultiblock(localPos, structureBlockInfo, be); - if (AllMovementBehaviours.getBehaviour(captured.state()) != null) + if (MovementBehaviour.REGISTRY.get(state) != null) actors.add(MutablePair.of(structureBlockInfo, null)); - MovingInteractionBehaviour interactionBehaviour = AllInteractionBehaviours.getBehaviour(captured.state()); + MovingInteractionBehaviour interactionBehaviour = MovingInteractionBehaviour.REGISTRY.get(state); if (interactionBehaviour != null) interactors.put(localPos, interactionBehaviour); if (be instanceof CreativeCrateBlockEntity && ((CreativeCrateBlockEntity) be).getBehaviour(FilteringBehaviour.TYPE) - .getFilter() - .isEmpty()) + .getFilter() + .isEmpty()) hasUniversalCreativeCrate = true; } @@ -663,10 +683,13 @@ public abstract class Contraption { CompoundTag nbt = structureBlockInfo.nbt(); BlockPos controllerPos = nbt.contains("Controller") ? - toLocalPos(NbtUtils.readBlockPos(nbt.getCompound("Controller"))) : - localPos; + toLocalPos(NbtUtils.readBlockPos(nbt.getCompound("Controller"))) : + localPos; nbt.put("Controller", NbtUtils.writeBlockPos(controllerPos)); + if (updateTags.containsKey(localPos)) + updateTags.get(localPos).put("Controller", NbtUtils.writeBlockPos(controllerPos)); + if (multiBlockBE.isController() && multiBlockBE.getHeight() <= 1 && multiBlockBE.getWidth() <= 1) { nbt.put("LastKnownPos", NbtUtils.writeBlockPos(BlockPos.ZERO.below(Integer.MAX_VALUE - 1))); return; @@ -714,17 +737,19 @@ public abstract class Contraption { capturedMultiblocks.clear(); nbt.getList("CapturedMultiblocks", Tag.TAG_COMPOUND).forEach(c -> { - CompoundTag tag = (CompoundTag) c; - if (!tag.contains("Controller", Tag.TAG_COMPOUND) && !tag.contains("Parts", Tag.TAG_LIST)) - return; + CompoundTag tag = (CompoundTag) c; + if (!tag.contains("Controller", Tag.TAG_COMPOUND) && !tag.contains("Parts", Tag.TAG_LIST)) + return; - BlockPos controllerPos = NbtUtils.readBlockPos(tag.getCompound("Controller")); - tag.getList("Parts", Tag.TAG_COMPOUND).forEach(part -> { - BlockPos partPos = NbtUtils.readBlockPos((CompoundTag) part); - StructureBlockInfo partInfo = this.blocks.get(partPos); - capturedMultiblocks.put(controllerPos, partInfo); - }); + BlockPos controllerPos = NbtUtils.readBlockPos(tag.getCompound("Controller")); + tag.getList("Parts", Tag.TAG_COMPOUND).forEach(part -> { + BlockPos partPos = NbtUtils.readBlockPos((CompoundTag) part); + StructureBlockInfo partInfo = this.blocks.get(partPos); + capturedMultiblocks.put(controllerPos, partInfo); }); + }); + + storage.read(nbt, spawnData, this); actors.clear(); nbt.getList("Actors", Tag.TAG_COMPOUND) @@ -762,13 +787,11 @@ public abstract class Contraption { StructureBlockInfo structureBlockInfo = getBlocks().get(pos); if (structureBlockInfo == null) return; - MovingInteractionBehaviour behaviour = AllInteractionBehaviours.getBehaviour(structureBlockInfo.state()); + MovingInteractionBehaviour behaviour = MovingInteractionBehaviour.REGISTRY.get(structureBlockInfo.state()); if (behaviour != null) interactors.put(pos, behaviour); }); - storage.read(nbt, presentBlockEntities, spawnData); - if (nbt.contains("BoundsFront")) bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", Tag.TAG_FLOAT)); @@ -779,9 +802,10 @@ public abstract class Contraption { public CompoundTag writeNBT(boolean spawnPacket) { CompoundTag nbt = new CompoundTag(); - nbt.putString("Type", getType().id); + ResourceLocation typeId = this.getType().holder.key().location(); + nbt.putString("Type", typeId.toString()); - CompoundTag blocksNBT = writeBlocksCompound(); + CompoundTag blocksNBT = writeBlocksCompound(spawnPacket); ListTag multiblocksNBT = new ListTag(); capturedMultiblocks.keySet().forEach(controllerPos -> { @@ -798,7 +822,7 @@ public abstract class Contraption { ListTag actorsNBT = new ListTag(); for (MutablePair actor : getActors()) { - MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(actor.left.state()); + MovementBehaviour behaviour = MovementBehaviour.REGISTRY.get(actor.left.state()); if (behaviour == null) continue; CompoundTag compound = new CompoundTag(); @@ -819,7 +843,7 @@ public abstract class Contraption { } } - (spawnPacket ? getStorageForSpawnPacket() : storage).write(nbt, spawnPacket); + writeStorage(nbt, spawnPacket); ListTag interactorNBT = new ListTag(); for (BlockPos pos : interactors.keySet()) { @@ -862,11 +886,11 @@ public abstract class Contraption { return nbt; } - protected MountedStorageManager getStorageForSpawnPacket() { - return storage; + public void writeStorage(CompoundTag nbt, boolean spawnPacket) { + storage.write(nbt, spawnPacket); } - private CompoundTag writeBlocksCompound() { + private CompoundTag writeBlocksCompound(boolean spawnPacket) { CompoundTag compound = new CompoundTag(); HashMapPalette palette = new HashMapPalette<>(GameData.getBlockStateIDMap(), 16, (i, s) -> { throw new IllegalStateException("Palette Map index exceeded maximum"); @@ -875,11 +899,32 @@ public abstract class Contraption { for (StructureBlockInfo block : this.blocks.values()) { int id = palette.idFor(block.state()); + BlockPos pos = block.pos(); CompoundTag c = new CompoundTag(); - c.putLong("Pos", block.pos().asLong()); + c.putLong("Pos", pos.asLong()); c.putInt("State", id); - if (block.nbt() != null) - c.put("Data", block.nbt()); + + CompoundTag updateTag = updateTags.get(pos); + if (spawnPacket) { + // for client sync, treat the updateTag as the data + if (updateTag != null) { + c.put("Data", updateTag); + } else if (block.nbt() != null) { + // an updateTag is saved for all BlockEntities, even when empty. + // this case means that the contraption was assembled pre-updateTags. + // in this case, we need to use the full BlockEntity data. + c.put("Data", block.nbt()); + NBTHelper.putMarker(c, "Legacy"); + } + } else { + // otherwise, write actual data as the data, save updateTag on its own + if (block.nbt() != null) { + c.put("Data", block.nbt()); + } + if (updateTag != null) { + c.put("UpdateTag", updateTag); + } + } blockList.add(c); } @@ -922,37 +967,73 @@ public abstract class Contraption { this.blocks.put(info.pos(), info); + if (c.contains("UpdateTag", Tag.TAG_COMPOUND)) { + CompoundTag updateTag = c.getCompound("UpdateTag"); + // it's very important that empty tags are read here. see writeBlocksCompound + this.updateTags.put(info.pos(), updateTag); + } + if (!world.isClientSide) return; - CompoundTag tag = info.nbt(); - if (tag == null) - return; - - tag.putInt("x", info.pos().getX()); - tag.putInt("y", info.pos().getY()); - tag.putInt("z", info.pos().getZ()); - - BlockEntity be = BlockEntity.loadStatic(info.pos(), info.state(), tag); + // create the BlockEntity client-side for rendering + BlockEntity be = readBlockEntity(world, info, c); if (be == null) return; - be.setLevel(world); - if (be instanceof KineticBlockEntity kbe) - kbe.setSpeed(0); - be.getBlockState(); presentBlockEntities.put(info.pos(), be); modelData.put(info.pos(), be.getModelData()); - MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(info.state()); + MovementBehaviour movementBehaviour = MovementBehaviour.REGISTRY.get(info.state()); if (movementBehaviour == null || !movementBehaviour.disableBlockEntityRendering()) { renderedBlockEntities.add(be); } }); } + @Nullable + private static BlockEntity readBlockEntity(Level level, StructureBlockInfo info, CompoundTag tag) { + BlockState state = info.state(); + BlockPos pos = info.pos(); + CompoundTag nbt = info.nbt(); + + if (tag.contains("Legacy")) { + // for contraptions that were assembled pre-updateTags, we need to use the old strategy. + if (nbt == null) + return null; + + nbt.putInt("x", pos.getX()); + nbt.putInt("y", pos.getY()); + nbt.putInt("z", pos.getZ()); + + BlockEntity be = BlockEntity.loadStatic(pos, state, nbt); + postprocessReadBlockEntity(level, be); + return be; + } + + if (!state.hasBlockEntity() || !(state.getBlock() instanceof EntityBlock entityBlock)) + return null; + + BlockEntity be = entityBlock.newBlockEntity(pos, state); + postprocessReadBlockEntity(level, be); + if (be != null && nbt != null) { + be.handleUpdateTag(nbt); + } + + return be; + } + + private static void postprocessReadBlockEntity(Level level, @Nullable BlockEntity be) { + if (be != null) { + be.setLevel(level); + if (be instanceof KineticBlockEntity kbe) { + kbe.setSpeed(0); + } + } + } + private static StructureBlockInfo readStructureBlockInfo(CompoundTag blockListEntry, - HashMapPalette palette) { + HashMapPalette palette) { return new StructureBlockInfo(BlockPos.of(blockListEntry.getLong("Pos")), Objects.requireNonNull(palette.valueFor(blockListEntry.getInt("State"))), blockListEntry.contains("Data") ? blockListEntry.getCompound("Data") : null); @@ -965,8 +1046,6 @@ public abstract class Contraption { } public void removeBlocksFromWorld(Level world, BlockPos offset) { - storage.removeStorageFromWorld(); - glueToRemove.forEach(glue -> { superglue.add(glue.getBoundingBox() .move(Vec3.atLowerCornerOf(offset.offset(anchor)) @@ -980,7 +1059,7 @@ public abstract class Contraption { for (boolean brittles : Iterate.trueAndFalse) { for (Iterator iterator = blocks.values() - .iterator(); iterator.hasNext();) { + .iterator(); iterator.hasNext(); ) { StructureBlockInfo block = iterator.next(); if (brittles != BlockMovementChecks.isBrittle(block.state())) continue; @@ -1085,7 +1164,7 @@ public abstract class Contraption { if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) .isEmpty() && !blockState.getCollisionShape(world, targetPos) - .isEmpty())) { + .isEmpty())) { if (targetPos.getY() == world.getMinBuildHeight()) targetPos = targetPos.above(); world.levelEvent(2001, targetPos, Block.getId(state)); @@ -1106,7 +1185,7 @@ public abstract class Contraption { state = state.setValue(SlidingDoorBlock.VISIBLE, !state.getValue(SlidingDoorBlock.OPEN)) .setValue(SlidingDoorBlock.POWERED, false); // Stop Sculk shriekers from getting "stuck" if moved mid-shriek. - if(state.is(Blocks.SCULK_SHRIEKER)){ + if (state.is(Blocks.SCULK_SHRIEKER)) { state = Blocks.SCULK_SHRIEKER.defaultBlockState(); } @@ -1125,7 +1204,7 @@ public abstract class Contraption { CompoundTag tag = block.nbt(); // Temporary fix: Calling load(CompoundTag tag) on a Sculk sensor causes it to not react to vibrations. - if(state.is(Blocks.SCULK_SENSOR) || state.is(Blocks.SCULK_SHRIEKER)) + if (state.is(Blocks.SCULK_SENSOR) || state.is(Blocks.SCULK_SHRIEKER)) tag = null; if (blockEntity != null) @@ -1148,10 +1227,13 @@ public abstract class Contraption { } blockEntity.load(tag); - storage.addStorageToWorld(block, blockEntity); } - transform.apply(blockEntity); + storage.unmount(world, block, targetPos, blockEntity); + + if (blockEntity != null) { + transform.apply(blockEntity); + } } } @@ -1169,8 +1251,6 @@ public abstract class Contraption { if (!world.isClientSide) world.addFreshEntity(new SuperGlueEntity(world, box)); } - - storage.clear(); } protected void translateMultiblockControllers(StructureTransform transform) { @@ -1189,12 +1269,11 @@ public abstract class Contraption { BoundingBox boundingBox = optionalBoundingBox.get(); BlockPos newControllerPos = new BlockPos(boundingBox.minX(), boundingBox.minY(), boundingBox.minZ()); - BlockPos newLocalPos = toLocalPos(newControllerPos); BlockPos otherPos = transform.unapply(newControllerPos); multiblockParts.forEach(info -> info.nbt().put("Controller", NbtUtils.writeBlockPos(newControllerPos))); - if (controllerPos.equals(newLocalPos)) + if (controllerPos.equals(otherPos)) return; // swap nbt data to the new controller position @@ -1231,7 +1310,7 @@ public abstract class Contraption { for (MutablePair pair : actors) { MovementContext context = new MovementContext(world, pair.left, this); - MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.left.state()); + MovementBehaviour behaviour = MovementBehaviour.REGISTRY.get(pair.left.state()); if (behaviour != null) behaviour.startMoving(context); pair.setRight(context); @@ -1261,7 +1340,7 @@ public abstract class Contraption { public void setActorsActive(ItemStack referenceStack, boolean enable) { for (MutablePair pair : actors) { - MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.left.state()); + MovementBehaviour behaviour = MovementBehaviour.REGISTRY.get(pair.left.state()); if (behaviour == null) continue; ItemStack behaviourStack = behaviour.canBeDisabledVia(pair.right); @@ -1291,7 +1370,7 @@ public abstract class Contraption { public void forEachActor(Level world, BiConsumer callBack) { for (MutablePair pair : actors) { - MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.getLeft().state()); + MovementBehaviour behaviour = MovementBehaviour.REGISTRY.get(pair.getLeft().state()); if (behaviour == null) continue; callBack.accept(behaviour, pair.getRight()); @@ -1310,7 +1389,7 @@ public abstract class Contraption { public void expandBoundsAroundAxis(Axis axis) { Set blocks = getBlocks().keySet(); - int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis)))); + int radius = (int) (Math.ceil(getRadius(blocks, axis))); int maxX = radius + 2; int maxY = radius + 2; @@ -1319,13 +1398,13 @@ public abstract class Contraption { int minY = -radius - 1; int minZ = -radius - 1; - if (axis == Direction.Axis.X) { + if (axis == Axis.X) { maxX = (int) bounds.maxX; minX = (int) bounds.minX; - } else if (axis == Direction.Axis.Y) { + } else if (axis == Axis.Y) { maxY = (int) bounds.maxY; minY = (int) bounds.minY; - } else if (axis == Direction.Axis.Z) { + } else if (axis == Axis.Z) { maxZ = (int) bounds.maxZ; minZ = (int) bounds.minZ; } @@ -1392,62 +1471,60 @@ public abstract class Contraption { simplifiedEntityColliderProvider.cancel(false); } simplifiedEntityColliderProvider = CompletableFuture.supplyAsync(() -> { - VoxelShape combinedShape = Shapes.empty(); - for (Entry entry : blocks.entrySet()) { - StructureBlockInfo info = entry.getValue(); - BlockPos localPos = entry.getKey(); - VoxelShape collisionShape = info.state().getCollisionShape(world, localPos, CollisionContext.empty()); - if (collisionShape.isEmpty()) - continue; - combinedShape = Shapes.joinUnoptimized(combinedShape, - collisionShape.move(localPos.getX(), localPos.getY(), localPos.getZ()), BooleanOp.OR); - } - return combinedShape.optimize() - .toAabbs(); - }) + VoxelShape combinedShape = Shapes.empty(); + for (Entry entry : blocks.entrySet()) { + StructureBlockInfo info = entry.getValue(); + BlockPos localPos = entry.getKey(); + VoxelShape collisionShape = info.state().getCollisionShape(world, localPos, CollisionContext.empty()); + if (collisionShape.isEmpty()) + continue; + combinedShape = Shapes.joinUnoptimized(combinedShape, + collisionShape.move(localPos.getX(), localPos.getY(), localPos.getZ()), BooleanOp.OR); + } + return combinedShape.optimize() + .toAabbs(); + }) .thenAccept(r -> { simplifiedEntityColliders = Optional.of(r); }); } - public static float getRadius(Set blocks, Direction.Axis axis) { + public static double getRadius(Iterable blocks, Axis axis) { + Axis axisA; + Axis axisB; + switch (axis) { - case X: - return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ); - case Y: - return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ); - case Z: - return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY); + case X -> { + axisA = Axis.Y; + axisB = Axis.Z; + } + case Y -> { + axisA = Axis.X; + axisB = Axis.Z; + } + case Z -> { + axisA = Axis.X; + axisB = Axis.Y; + } + default -> throw new IllegalStateException("Unexpected value: " + axis); } - throw new IllegalStateException("Impossible axis"); - } + int maxDistSq = 0; + for (Vec3i vec : blocks) { + int a = vec.get(axisA); + int b = vec.get(axisB); - public static float getMaxDistSqr(Set blocks, ICoordinate one, ICoordinate other) { - float maxDistSq = -1; - for (BlockPos pos : blocks) { - float a = one.get(pos); - float b = other.get(pos); - - float distSq = a * a + b * b; + int distSq = a * a + b * b; if (distSq > maxDistSq) maxDistSq = distSq; } - return maxDistSq; + return Math.sqrt(maxDistSq); } - public IItemHandlerModifiable getSharedInventory() { - return storage.getItems(); - } - - public IItemHandlerModifiable getSharedFuelInventory() { - return storage.getFuelItems(); - } - - public IFluidHandler getSharedFluidTanks() { - return storage.getFluids(); + public MountedStorageManager getStorage() { + return this.storage; } public RenderedBlocks getRenderedBlocks() { @@ -1472,37 +1549,13 @@ public abstract class Contraption { return simplifiedEntityColliders; } - public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) { - storage.updateContainedFluid(localPos, containedFluid); - } - - public static class ContraptionInvWrapper extends CombinedInvWrapper { - protected final boolean isExternal; - - public ContraptionInvWrapper(boolean isExternal, IItemHandlerModifiable... itemHandler) { - super(itemHandler); - this.isExternal = isExternal; - } - - public ContraptionInvWrapper(IItemHandlerModifiable... itemHandler) { - this(false, itemHandler); - } - - public boolean isSlotExternal(int slot) { - if (isExternal) - return true; - IItemHandlerModifiable handler = getHandlerFromIndex(getIndexForSlot(slot)); - return handler instanceof ContraptionInvWrapper && ((ContraptionInvWrapper) handler).isSlotExternal(slot); - } - } - public void tickStorage(AbstractContraptionEntity entity) { - storage.entityTick(entity); + getStorage().tick(entity); } public boolean containsBlockBreakers() { for (MutablePair pair : actors) { - MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.getLeft().state()); + MovementBehaviour behaviour = MovementBehaviour.REGISTRY.get(pair.getLeft().state()); if (behaviour instanceof BlockBreakingMovementBehaviour || behaviour instanceof HarvesterMovementBehaviour) return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionBlockChangedPacket.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionBlockChangedPacket.java index b28ccfd4e2..313ad17ba8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionBlockChangedPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionBlockChangedPacket.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.contraptions; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.NbtUtils; diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionCollider.java index 3c542c490c..e5825c278b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionCollider.java @@ -15,13 +15,12 @@ import org.apache.commons.lang3.mutable.MutableObject; import org.apache.commons.lang3.tuple.MutablePair; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllPackets; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity.ContraptionRotationState; import com.simibubi.create.content.contraptions.ContraptionColliderLockPacket.ContraptionColliderLockPacketRequest; import com.simibubi.create.content.contraptions.actors.harvester.HarvesterMovementBehaviour; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; -import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.sync.ClientMotionPacket; import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; @@ -31,10 +30,10 @@ import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.collision.OrientedBB; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; @@ -63,6 +62,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -141,6 +141,10 @@ public class ContraptionCollider { float yawOffset = rotation.getYawOffset(); Vec3 position = getWorldToLocalTranslation(entity, anchorVec, rotationMatrix, yawOffset); + // Make player 'shorter' to make it less likely to become stuck + if (playerType == PlayerType.CLIENT && entityBounds.getYsize() > 1) + entityBounds = entityBounds.contract(0, 2 / 16f, 0); + motion = motion.subtract(contraptionMotion); motion = rotationMatrix.transform(motion); @@ -765,17 +769,14 @@ public class ContraptionCollider { if (collidedState.getBlock() instanceof CocoaBlock) continue; - MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(blockInfo.state()); + MovementBehaviour movementBehaviour = MovementBehaviour.REGISTRY.get(blockInfo.state()); if (movementBehaviour != null) { - if (movementBehaviour instanceof BlockBreakingMovementBehaviour) { - BlockBreakingMovementBehaviour behaviour = (BlockBreakingMovementBehaviour) movementBehaviour; + if (movementBehaviour instanceof BlockBreakingMovementBehaviour behaviour) { if (!behaviour.canBreak(world, colliderPos, collidedState) && !emptyCollider) return true; continue; } - if (movementBehaviour instanceof HarvesterMovementBehaviour) { - HarvesterMovementBehaviour harvesterMovementBehaviour = - (HarvesterMovementBehaviour) movementBehaviour; + if (movementBehaviour instanceof HarvesterMovementBehaviour harvesterMovementBehaviour) { if (!harvesterMovementBehaviour.isValidCrop(world, colliderPos, collidedState) && !harvesterMovementBehaviour.isValidOther(world, colliderPos, collidedState) && !emptyCollider) diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionData.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionData.java deleted file mode 100644 index 158d306a76..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionData.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import com.simibubi.create.compat.Mods; -import com.simibubi.create.foundation.mixin.accessor.NbtAccounterAccessor; -import com.simibubi.create.infrastructure.config.AllConfigs; - -import io.netty.buffer.Unpooled; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; - -public class ContraptionData { - /** - * A sane, default maximum for contraption data size. - */ - public static final int DEFAULT_LIMIT = 2_000_000; - /** - * Connectivity expands the NBT packet limit to 2 GB. - */ - public static final int CONNECTIVITY_LIMIT = Integer.MAX_VALUE; - /** - * Packet Fixer expands the NBT packet limit to 200 MB. - */ - public static final int PACKET_FIXER_LIMIT = 209_715_200; - /** - * XL Packets expands the NBT packet limit to 2 GB. - */ - public static final int XL_PACKETS_LIMIT = 2_000_000_000; - /** - * Minecart item sizes are limited by the vanilla slot change packet ({@link ClientboundContainerSetSlotPacket}). - * {@link #DEFAULT_LIMIT} is used as the default. - * Connectivity, PacketFixer, and XL Packets expand the size limit. - * If one of these mods is loaded, we take advantage of it and use the higher limit. - */ - public static final int PICKUP_LIMIT; - - static { - int limit = DEFAULT_LIMIT; - - // Check from largest to smallest to use the smallest limit if multiple mods are loaded. - // It is necessary to use the smallest limit because even if multiple mods are loaded, - // not all of their mixins may be applied. Therefore, it is safest to only assume that - // the mod with the smallest limit is actually active. - if (Mods.CONNECTIVITY.isLoaded()) { - limit = CONNECTIVITY_LIMIT; - } - if (Mods.XLPACKETS.isLoaded()) { - limit = XL_PACKETS_LIMIT; - } - if (Mods.PACKETFIXER.isLoaded()) { - limit = PACKET_FIXER_LIMIT; - } - - PICKUP_LIMIT = limit; - } - - /** - * @return true if the given NBT is too large for a contraption to be synced to clients. - */ - public static boolean isTooLargeForSync(CompoundTag data) { - int max = AllConfigs.server().kinetics.maxDataSize.get(); - return max != 0 && packetSize(data) > max; - } - - /** - * @return true if the given NBT is too large for a contraption to be picked up with a wrench. - */ - public static boolean isTooLargeForPickup(CompoundTag data) { - return packetSize(data) > PICKUP_LIMIT; - } - - /** - * @return the size of the given NBT when put through a packet, in bytes. - */ - public static long packetSize(CompoundTag data) { - FriendlyByteBuf test = new FriendlyByteBuf(Unpooled.buffer()); - test.writeNbt(data); - NbtAccounter sizeTracker = new NbtAccounter(Long.MAX_VALUE); - test.readNbt(sizeTracker); - long size = ((NbtAccounterAccessor) sizeTracker).create$getUsage(); - test.release(); - return size; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandler.java index a55884112f..b909708607 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandler.java @@ -7,11 +7,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.WorldAttached; - import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectLists; +import net.createmod.catnip.data.WorldAttached; +import net.createmod.catnip.math.VecHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.world.entity.Entity; @@ -51,7 +50,7 @@ public class ContraptionHandler { contraptionEntity.staleTicks--; continue; } - + ContraptionCollider.collideEntities(contraptionEntity); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandlerClient.java index 654412af1d..ec5bb7cabe 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandlerClient.java @@ -12,12 +12,12 @@ import com.simibubi.create.AllPackets; import com.simibubi.create.content.contraptions.sync.ContraptionInteractionPacket; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.TrainRelocator; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.RemotePlayer; @@ -32,6 +32,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.InputEvent; @@ -48,9 +49,8 @@ public class ContraptionHandlerClient { public static void preventRemotePlayersWalkingAnimations(PlayerTickEvent event) { if (event.phase == Phase.START) return; - if (!(event.player instanceof RemotePlayer)) + if (!(event.player instanceof RemotePlayer remotePlayer)) return; - RemotePlayer remotePlayer = (RemotePlayer) event.player; CompoundTag data = remotePlayer.getPersistentData(); if (!data.contains("LastOverrideLimbSwingUpdate")) return; @@ -91,7 +91,11 @@ public class ContraptionHandlerClient { Collection> contraptions = ContraptionHandler.loadedContraptions.get(mc.level) .values(); - + + double bestDistance = Double.MAX_VALUE; + BlockHitResult bestResult = null; + AbstractContraptionEntity bestEntity = null; + for (WeakReference ref : contraptions) { AbstractContraptionEntity contraptionEntity = ref.get(); if (contraptionEntity == null) @@ -104,23 +108,34 @@ public class ContraptionHandlerClient { if (rayTraceResult == null) continue; - InteractionHand hand = event.getHand(); - Direction face = rayTraceResult.getDirection(); - BlockPos pos = rayTraceResult.getBlockPos(); - - if (contraptionEntity.handlePlayerInteraction(player, pos, face, hand)) { - AllPackets.getChannel().sendToServer(new ContraptionInteractionPacket(contraptionEntity, hand, pos, face)); - } else if (handleSpecialInteractions(contraptionEntity, player, pos, face, hand)) { - } else + double distance = contraptionEntity.toGlobalVector(rayTraceResult.getLocation(), 1).distanceTo(origin); + if (distance > bestDistance) continue; - event.setCanceled(true); - event.setSwingHand(false); + bestResult = rayTraceResult; + bestDistance = distance; + bestEntity = contraptionEntity; } + + if (bestResult == null) + return; + + InteractionHand hand = event.getHand(); + Direction face = bestResult.getDirection(); + BlockPos pos = bestResult.getBlockPos(); + + if (bestEntity.handlePlayerInteraction(player, pos, face, hand)) { + AllPackets.getChannel() + .sendToServer(new ContraptionInteractionPacket(bestEntity, hand, pos, face)); + } else + handleSpecialInteractions(bestEntity, player, pos, face, hand); + + event.setCanceled(true); + event.setSwingHand(false); } private static boolean handleSpecialInteractions(AbstractContraptionEntity contraptionEntity, Player player, - BlockPos localPos, Direction side, InteractionHand interactionHand) { + BlockPos localPos, Direction side, InteractionHand interactionHand) { if (AllItems.WRENCH.isIn(player.getItemInHand(interactionHand)) && contraptionEntity instanceof CarriageContraptionEntity car) return TrainRelocator.carriageWrenched(car.toGlobalVector(VecHelper.getCenterOf(localPos), 1), car); @@ -141,7 +156,7 @@ public class ContraptionHandlerClient { @Nullable public static BlockHitResult rayTraceContraption(Vec3 origin, Vec3 target, - AbstractContraptionEntity contraptionEntity) { + AbstractContraptionEntity contraptionEntity) { Vec3 localOrigin = contraptionEntity.toLocalVector(origin, 1); Vec3 localTarget = contraptionEntity.toLocalVector(target, 1); Contraption contraption = contraptionEntity.getContraption(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java deleted file mode 100644 index 4d49f8ffb9..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.Collection; -import java.util.function.Supplier; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.utility.AttachedRegistry; -import com.simibubi.create.infrastructure.config.AllConfigs; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraftforge.common.extensions.IForgeBlock; -import net.minecraftforge.registries.ForgeRegistries; - -public enum ContraptionMovementSetting { - MOVABLE, NO_PICKUP, UNMOVABLE; - - private static final AttachedRegistry> SETTING_SUPPLIERS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - - public static void register(ResourceLocation block, Supplier settingSupplier) { - SETTING_SUPPLIERS.register(block, settingSupplier); - } - - public static void register(Block block, Supplier settingSupplier) { - SETTING_SUPPLIERS.register(block, settingSupplier); - } - - @Nullable - public static ContraptionMovementSetting get(Block block) { - if (block instanceof IMovementSettingProvider provider) - return provider.getContraptionMovementSetting(); - Supplier supplier = SETTING_SUPPLIERS.get(block); - if (supplier == null) - return null; - return supplier.get(); - } - - public static boolean allAre(Collection blocks, ContraptionMovementSetting are) { - return blocks.stream().anyMatch(b -> get(b.state().getBlock()) == are); - } - - public static boolean isNoPickup(Collection blocks) { - return allAre(blocks, ContraptionMovementSetting.NO_PICKUP); - } - - public static void registerDefaults() { - register(Blocks.SPAWNER, () -> AllConfigs.server().kinetics.spawnerMovement.get()); - register(Blocks.BUDDING_AMETHYST, () -> AllConfigs.server().kinetics.amethystMovement.get()); - register(Blocks.OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); - register(Blocks.CRYING_OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); - register(Blocks.RESPAWN_ANCHOR, () -> AllConfigs.server().kinetics.obsidianMovement.get()); - register(Blocks.REINFORCED_DEEPSLATE, () -> AllConfigs.server().kinetics.reinforcedDeepslateMovement.get()); - } - - public interface IMovementSettingProvider extends IForgeBlock { - ContraptionMovementSetting getContraptionMovementSetting(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionType.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionType.java deleted file mode 100644 index 1b85efc417..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionType.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Supplier; - -import com.simibubi.create.content.contraptions.bearing.BearingContraption; -import com.simibubi.create.content.contraptions.bearing.ClockworkContraption; -import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; -import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; -import com.simibubi.create.content.contraptions.gantry.GantryContraption; -import com.simibubi.create.content.contraptions.mounted.MountedContraption; -import com.simibubi.create.content.contraptions.piston.PistonContraption; -import com.simibubi.create.content.contraptions.pulley.PulleyContraption; -import com.simibubi.create.content.trains.entity.CarriageContraption; - -public class ContraptionType { - - public static final Map ENTRIES = new HashMap<>(); - public static final ContraptionType - PISTON = register("piston", PistonContraption::new), - BEARING = register("bearing", BearingContraption::new), - PULLEY = register("pulley", PulleyContraption::new), - CLOCKWORK = register("clockwork", ClockworkContraption::new), - MOUNTED = register("mounted", MountedContraption::new), - STABILIZED = register("stabilized", StabilizedContraption::new), - GANTRY = register("gantry", GantryContraption::new), - CARRIAGE = register("carriage", CarriageContraption::new), - ELEVATOR = register("elevator", ElevatorContraption::new); - - Supplier factory; - String id; - - public static ContraptionType register(String id, Supplier factory) { - ContraptionType value = new ContraptionType(id, factory); - ENTRIES.put(id, value); - return value; - } - - private ContraptionType(String id, Supplier factory) { - this.factory = factory; - this.id = id; - } - - public static Contraption fromType(String type) { - for (Entry allContraptionTypes : ENTRIES.entrySet()) - if (type.equals(allContraptionTypes.getKey())) - return allContraptionTypes.getValue().factory.get(); - return null; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionWorld.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionWorld.java index a5b7790f25..dcd6157a15 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/ContraptionWorld.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionWorld.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.contraptions; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; - +import net.createmod.catnip.levelWrappers.WrappedLevel; import net.minecraft.core.BlockPos; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; @@ -11,7 +10,7 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -public class ContraptionWorld extends WrappedWorld { +public class ContraptionWorld extends WrappedLevel { final Contraption contraption; private final int minY; private final int height; @@ -44,7 +43,7 @@ public class ContraptionWorld extends WrappedWorld { @Override public void playLocalSound(double x, double y, double z, SoundEvent sound, SoundSource category, float volume, float pitch, boolean distanceDelay) { - world.playLocalSound(x, y, z, sound, category, volume, pitch, distanceDelay); + level.playLocalSound(x, y, z, sound, category, volume, pitch, distanceDelay); } // Ensure that we provide accurate information about ContraptionWorld height to mods (such as Starlight) which diff --git a/src/main/java/com/simibubi/create/content/contraptions/ControlledContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/ControlledContraptionEntity.java index 79f0b07497..efb15980cd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/ControlledContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ControlledContraptionEntity.java @@ -1,16 +1,15 @@ package com.simibubi.create.content.contraptions; -import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp; - import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.bearing.BearingContraption; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -22,6 +21,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -44,7 +44,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { } public static ControlledContraptionEntity create(Level world, IControlContraption controller, - Contraption contraption) { + Contraption contraption) { ControlledContraptionEntity entity = new ControlledContraptionEntity(AllEntityTypes.CONTROLLED_CONTRAPTION.get(), world); entity.controllerPos = controller.getBlockPosition(); @@ -132,7 +132,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { } public float getAngle(float partialTicks) { - return partialTicks == 1.0F ? angle : angleLerp(partialTicks, prevAngle, angle); + return partialTicks == 1.0F ? angle : AngleHelper.angleLerp(partialTicks, prevAngle, angle); } public void setRotationAxis(Axis rotationAxis) { @@ -144,11 +144,13 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { } @Override - public void teleportTo(double p_70634_1_, double p_70634_3_, double p_70634_5_) {} + public void teleportTo(double p_70634_1_, double p_70634_3_, double p_70634_5_) { + } @Override @OnlyIn(Dist.CLIENT) - public void lerpTo(double x, double y, double z, float yw, float pt, int inc, boolean t) {} + public void lerpTo(double x, double y, double z, float yw, float pt, int inc, boolean t) { + } protected void tickContraption() { angleDelta = angle - prevAngle; @@ -173,14 +175,13 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { @Override protected boolean shouldActorTrigger(MovementContext context, StructureBlockInfo blockInfo, MovementBehaviour actor, - Vec3 actorPosition, BlockPos gridPosition) { + Vec3 actorPosition, BlockPos gridPosition) { if (super.shouldActorTrigger(context, blockInfo, actor, actorPosition, gridPosition)) return true; // Special activation timer for actors in the center of a bearing contraption - if (!(contraption instanceof BearingContraption)) + if (!(contraption instanceof BearingContraption bc)) return false; - BearingContraption bc = (BearingContraption) contraption; Direction facing = bc.getFacing(); Vec3 activeAreaOffset = actor.getActiveAreaOffset(context); if (!activeAreaOffset.multiply(VecHelper.axisAlingedPlaneOf(Vec3.atLowerCornerOf(facing.getNormal()))) @@ -248,10 +249,10 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { if (axis != null) { TransformStack.of(matrixStack) - .nudge(getId()) - .center() - .rotateDegrees(angle, axis) - .uncenter(); + .nudge(getId()) + .center() + .rotateDegrees(angle, axis) + .uncenter(); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/DirectionalExtenderScrollOptionSlot.java b/src/main/java/com/simibubi/create/content/contraptions/DirectionalExtenderScrollOptionSlot.java index 5b19e632ad..60d815a0b3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/DirectionalExtenderScrollOptionSlot.java +++ b/src/main/java/com/simibubi/create/content/contraptions/DirectionalExtenderScrollOptionSlot.java @@ -4,10 +4,12 @@ import java.util.function.BiPredicate; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.Vec3; @@ -19,16 +21,16 @@ public class DirectionalExtenderScrollOptionSlot extends CenteredSideValueBoxTra } @Override - public Vec3 getLocalOffset(BlockState state) { - return super.getLocalOffset(state) + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { + return super.getLocalOffset(level, pos, state) .add(Vec3.atLowerCornerOf(state.getValue(BlockStateProperties.FACING).getNormal()).scale(-2 / 16f)); } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { if (!getSide().getAxis().isHorizontal()) TransformStack.of(ms) .rotateYDegrees(AngleHelper.horizontalAngle(state.getValue(BlockStateProperties.FACING)) + 180); - super.rotate(state, ms); + super.rotate(level, pos, state, ms); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/IControlContraption.java b/src/main/java/com/simibubi/create/content/contraptions/IControlContraption.java index 9453fea9f2..2493c5b11c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/IControlContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/IControlContraption.java @@ -2,20 +2,20 @@ package com.simibubi.create.content.contraptions; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; public interface IControlContraption { public boolean isAttachedTo(AbstractContraptionEntity contraption); - + public void attach(ControlledContraptionEntity contraption); public void onStall(); public boolean isValid(); - + public BlockPos getBlockPosition(); static enum MovementMode implements INamedIconOptions { diff --git a/src/main/java/com/simibubi/create/content/contraptions/IDisplayAssemblyExceptions.java b/src/main/java/com/simibubi/create/content/contraptions/IDisplayAssemblyExceptions.java index c157ed1924..87f0e2ddbb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/IDisplayAssemblyExceptions.java +++ b/src/main/java/com/simibubi/create/content/contraptions/IDisplayAssemblyExceptions.java @@ -4,11 +4,11 @@ import java.util.Arrays; import java.util.List; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.FontHelper.Palette; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; public interface IDisplayAssemblyExceptions { @@ -19,15 +19,15 @@ public interface IDisplayAssemblyExceptions { return false; if (!tooltip.isEmpty()) - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); - Lang.translate("gui.assembly.exception").style(ChatFormatting.GOLD) + CreateLang.translate("gui.assembly.exception").style(ChatFormatting.GOLD) .forGoggles(tooltip); String text = e.component.getString(); Arrays.stream(text.split("\n")) .forEach(l -> TooltipHelper.cutStringTextComponent(l, Palette.GRAY_AND_WHITE) - .forEach(c -> Lang.builder().add(c).forGoggles(tooltip))); + .forEach(c -> CreateLang.builder().add(c).forGoggles(tooltip))); return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlock.java b/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlock.java deleted file mode 100644 index 61c4cb0aa7..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlock.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import net.minecraft.world.level.block.state.BlockState; - -public interface ITransformableBlock { - BlockState transform(BlockState state, StructureTransform transform); -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlockEntity.java deleted file mode 100644 index cadd35946a..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlockEntity.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.content.contraptions; - -public interface ITransformableBlockEntity { - - void transform(StructureTransform transform); - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java b/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java deleted file mode 100644 index b395535e1c..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import com.simibubi.create.AllPackets; -import com.simibubi.create.content.contraptions.sync.ContraptionFluidPacket; -import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; -import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity.CreativeSmartFluidTank; -import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; -import com.simibubi.create.foundation.fluid.SmartFluidTank; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.network.PacketDistributor; - -public class MountedFluidStorage { - - SmartFluidTank tank; - private boolean valid; - private BlockEntity blockEntity; - - private int packetCooldown = 0; - private boolean sendPacket = false; - - public static boolean canUseAsStorage(BlockEntity be) { - if (be instanceof FluidTankBlockEntity) - return ((FluidTankBlockEntity) be).isController(); - return false; - } - - public MountedFluidStorage(BlockEntity be) { - assignBlockEntity(be); - } - - public void assignBlockEntity(BlockEntity be) { - this.blockEntity = be; - tank = createMountedTank(be); - } - - private SmartFluidTank createMountedTank(BlockEntity be) { - if (be instanceof CreativeFluidTankBlockEntity) - return new CreativeSmartFluidTank( - ((FluidTankBlockEntity) be).getTotalTankSize() * FluidTankBlockEntity.getCapacityMultiplier(), $ -> { - }); - if (be instanceof FluidTankBlockEntity) - return new SmartFluidTank( - ((FluidTankBlockEntity) be).getTotalTankSize() * FluidTankBlockEntity.getCapacityMultiplier(), - this::onFluidStackChanged); - return null; - } - - public void tick(Entity entity, BlockPos pos, boolean isRemote) { - if (!isRemote) { - if (packetCooldown > 0) - packetCooldown--; - else if (sendPacket) { - sendPacket = false; - AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), - new ContraptionFluidPacket(entity.getId(), pos, tank.getFluid())); - packetCooldown = 8; - } - return; - } - - if (!(blockEntity instanceof FluidTankBlockEntity)) - return; - FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; - tank.getFluidLevel() - .tickChaser(); - } - - public void updateFluid(FluidStack fluid) { - tank.setFluid(fluid); - if (!(blockEntity instanceof FluidTankBlockEntity)) - return; - float fillState = tank.getFluidAmount() / (float) tank.getCapacity(); - FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; - if (tank.getFluidLevel() == null) - tank.setFluidLevel(LerpedFloat.linear() - .startWithValue(fillState)); - tank.getFluidLevel() - .chase(fillState, 0.5, Chaser.EXP); - IFluidTank tankInventory = tank.getTankInventory(); - if (tankInventory instanceof SmartFluidTank) - ((SmartFluidTank) tankInventory).setFluid(fluid); - } - - public void removeStorageFromWorld() { - valid = false; - if (blockEntity == null) - return; - - IFluidHandler teHandler = blockEntity.getCapability(ForgeCapabilities.FLUID_HANDLER) - .orElse(null); - if (!(teHandler instanceof SmartFluidTank)) - return; - SmartFluidTank smartTank = (SmartFluidTank) teHandler; - tank.setFluid(smartTank.getFluid()); - sendPacket = false; - valid = true; - } - - private void onFluidStackChanged(FluidStack fs) { - sendPacket = true; - } - - public void addStorageToWorld(BlockEntity be) { - if (tank instanceof CreativeSmartFluidTank) - return; - - LazyOptional capability = be.getCapability(ForgeCapabilities.FLUID_HANDLER); - IFluidHandler teHandler = capability.orElse(null); - if (!(teHandler instanceof SmartFluidTank)) - return; - - SmartFluidTank inv = (SmartFluidTank) teHandler; - inv.setFluid(tank.getFluid() - .copy()); - } - - public IFluidHandler getFluidHandler() { - return tank; - } - - public CompoundTag serialize() { - if (!valid) - return null; - CompoundTag tag = tank.writeToNBT(new CompoundTag()); - tag.putInt("Capacity", tank.getCapacity()); - - if (tank instanceof CreativeSmartFluidTank) { - NBTHelper.putMarker(tag, "Bottomless"); - tag.put("ProvidedStack", tank.getFluid() - .writeToNBT(new CompoundTag())); - } - return tag; - } - - public static MountedFluidStorage deserialize(CompoundTag nbt) { - MountedFluidStorage storage = new MountedFluidStorage(null); - if (nbt == null) - return storage; - - int capacity = nbt.getInt("Capacity"); - storage.tank = new SmartFluidTank(capacity, storage::onFluidStackChanged); - storage.valid = true; - - if (nbt.contains("Bottomless")) { - FluidStack providedStack = FluidStack.loadFluidStackFromNBT(nbt.getCompound("ProvidedStack")); - CreativeSmartFluidTank creativeSmartFluidTank = new CreativeSmartFluidTank(capacity, $ -> { - }); - creativeSmartFluidTank.setContainedFluid(providedStack); - storage.tank = creativeSmartFluidTank; - return storage; - } - - storage.tank.readFromNBT(nbt); - return storage; - } - - public boolean isValid() { - return valid; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java deleted file mode 100644 index 09fd87072e..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import com.simibubi.create.AllBlockEntityTypes; -import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.equipment.toolbox.ToolboxInventory; -import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity; -import com.simibubi.create.content.logistics.crate.BottomlessItemHandler; -import com.simibubi.create.content.logistics.vault.ItemVaultBlockEntity; -import com.simibubi.create.content.processing.recipe.ProcessingInventory; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BarrelBlockEntity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.ChestBlockEntity; -import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.registries.ForgeRegistries; - -public class MountedStorage { - - private static final ItemStackHandler dummyHandler = new ItemStackHandler(); - - ItemStackHandler handler; - boolean noFuel; - boolean valid; - - private BlockEntity blockEntity; - - public static boolean canUseAsStorage(BlockEntity be) { - if (be == null) - return false; - if (be instanceof MechanicalCrafterBlockEntity) - return false; - if (AllBlockEntityTypes.CREATIVE_CRATE.is(be)) - return true; - if (be instanceof ShulkerBoxBlockEntity) - return true; - if (be instanceof ChestBlockEntity) - return true; - if (be instanceof BarrelBlockEntity) - return true; - if (be instanceof ItemVaultBlockEntity) - return true; - - try { - LazyOptional capability = be.getCapability(ForgeCapabilities.ITEM_HANDLER); - IItemHandler handler = capability.orElse(null); - if (handler instanceof ItemStackHandler) - return !(handler instanceof ProcessingInventory); - return canUseModdedInventory(be, handler); - - } catch (Exception e) { - return false; - } - } - - public static boolean canUseModdedInventory(BlockEntity be, IItemHandler handler) { - if (!(handler instanceof IItemHandlerModifiable validItemHandler)) - return false; - BlockState blockState = be.getBlockState(); - if (AllBlockTags.CONTRAPTION_INVENTORY_DENY.matches(blockState)) - return false; - - // There doesn't appear to be much of a standard for tagging chests/barrels - String blockId = ForgeRegistries.BLOCKS.getKey(blockState.getBlock()) - .getPath(); - if (blockId.contains("ender")) - return false; - return blockId.endsWith("_chest") || blockId.endsWith("_barrel"); - } - - public MountedStorage(BlockEntity be) { - this.blockEntity = be; - handler = dummyHandler; - noFuel = be instanceof ItemVaultBlockEntity; - } - - public void removeStorageFromWorld() { - valid = false; - if (blockEntity == null) - return; - - if (blockEntity instanceof ChestBlockEntity) { - CompoundTag tag = blockEntity.saveWithFullMetadata(); - if (tag.contains("LootTable", 8)) - return; - - handler = new ItemStackHandler(((ChestBlockEntity) blockEntity).getContainerSize()); - NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); - ContainerHelper.loadAllItems(tag, items); - for (int i = 0; i < items.size(); i++) - handler.setStackInSlot(i, items.get(i)); - valid = true; - return; - } - - IItemHandler beHandler = blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER) - .orElse(dummyHandler); - if (beHandler == dummyHandler) - return; - - // multiblock vaults need to provide individual invs - if (blockEntity instanceof ItemVaultBlockEntity) { - handler = ((ItemVaultBlockEntity) blockEntity).getInventoryOfBlock(); - valid = true; - return; - } - - // be uses ItemStackHandler - if (beHandler instanceof ItemStackHandler) { - handler = (ItemStackHandler) beHandler; - valid = true; - return; - } - - // serialization not accessible -> fill into a serializable handler - if (beHandler instanceof IItemHandlerModifiable) { - IItemHandlerModifiable inv = (IItemHandlerModifiable) beHandler; - handler = new ItemStackHandler(beHandler.getSlots()); - for (int slot = 0; slot < handler.getSlots(); slot++) { - handler.setStackInSlot(slot, inv.getStackInSlot(slot)); - inv.setStackInSlot(slot, ItemStack.EMPTY); - } - valid = true; - return; - } - - } - - public void addStorageToWorld(BlockEntity be) { - // FIXME: More dynamic mounted storage in .4 - if (handler instanceof BottomlessItemHandler) - return; - - if (be instanceof ChestBlockEntity) { - CompoundTag tag = be.saveWithFullMetadata(); - tag.remove("Items"); - NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); - for (int i = 0; i < items.size(); i++) - items.set(i, handler.getStackInSlot(i)); - ContainerHelper.saveAllItems(tag, items); - be.load(tag); - return; - } - - if (be instanceof ItemVaultBlockEntity) { - ((ItemVaultBlockEntity) be).applyInventoryToBlock(handler); - return; - } - - LazyOptional capability = be.getCapability(ForgeCapabilities.ITEM_HANDLER); - IItemHandler teHandler = capability.orElse(null); - if (!(teHandler instanceof IItemHandlerModifiable)) - return; - - IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler; - for (int slot = 0; slot < Math.min(inv.getSlots(), handler.getSlots()); slot++) - inv.setStackInSlot(slot, handler.getStackInSlot(slot)); - } - - public IItemHandlerModifiable getItemHandler() { - return handler; - } - - public CompoundTag serialize() { - if (!valid) - return null; - - CompoundTag tag = handler.serializeNBT(); - if (noFuel) - NBTHelper.putMarker(tag, "NoFuel"); - if (handler instanceof ToolboxInventory) - NBTHelper.putMarker(tag, "Toolbox"); - if (!(handler instanceof BottomlessItemHandler)) - return tag; - - NBTHelper.putMarker(tag, "Bottomless"); - tag.put("ProvidedStack", handler.getStackInSlot(0) - .serializeNBT()); - return tag; - } - - public static MountedStorage deserialize(CompoundTag nbt) { - MountedStorage storage = new MountedStorage(null); - storage.handler = new ItemStackHandler(); - if (nbt == null) - return storage; - if (nbt.contains("Toolbox")) - storage.handler = new ToolboxInventory(null); - - storage.valid = true; - storage.noFuel = nbt.contains("NoFuel"); - - if (nbt.contains("Bottomless")) { - ItemStack providedStack = ItemStack.of(nbt.getCompound("ProvidedStack")); - storage.handler = new BottomlessItemHandler(() -> providedStack); - return storage; - } - - storage.handler.deserializeNBT(nbt); - return storage; - } - - public boolean isValid() { - return valid; - } - - public boolean canUseForFuel() { - return !noFuel; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java deleted file mode 100644 index da84498db7..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.List; -import java.util.function.Supplier; - -import com.google.common.collect.ImmutableList; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.MenuType; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class MountedStorageInteraction { - - public static final List> menus = ImmutableList.of(MenuType.GENERIC_9x1, MenuType.GENERIC_9x2, - MenuType.GENERIC_9x3, MenuType.GENERIC_9x4, MenuType.GENERIC_9x5, MenuType.GENERIC_9x6); - - public static MenuProvider createMenuProvider(Component displayName, IItemHandlerModifiable handler, - int slotCount, Supplier stillValid) { - int rows = Mth.clamp(slotCount / 9, 1, 6); - MenuType menuType = menus.get(rows - 1); - Component menuName = Lang.translateDirect("contraptions.moving_container", displayName); - - return new MenuProvider() { - - @Override - public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { - return new ChestMenu(menuType, pContainerId, pPlayerInventory, new StorageInteractionContainer(handler, stillValid), - rows); - } - - @Override - public Component getDisplayName() { - return menuName; - } - - }; - } - - public static class StorageInteractionContainer extends RecipeWrapper { - - private Supplier stillValid; - - public StorageInteractionContainer(IItemHandlerModifiable inv, Supplier stillValid) { - super(inv); - this.stillValid = stillValid; - } - - @Override - public boolean stillValid(Player player) { - return stillValid.get(); - } - - @Override - public int getMaxStackSize() { - return 64; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java index 78a4742a8d..1ce9554475 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java @@ -1,262 +1,480 @@ package com.simibubi.create.content.contraptions; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; -import java.util.function.Supplier; -import java.util.stream.Collectors; +import java.util.Set; +import java.util.function.Predicate; -import com.simibubi.create.content.contraptions.Contraption.ContraptionInvWrapper; -import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; -import com.simibubi.create.foundation.fluid.CombinedTankWrapper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.NBTHelper; +import org.jetbrains.annotations.Nullable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTags.AllMountedItemStorageTypeTags; +import com.simibubi.create.Create; +import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageWrapper; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageWrapper; +import com.simibubi.create.content.equipment.toolbox.ToolboxMountedStorage; +import com.simibubi.create.content.fluids.tank.storage.FluidTankMountedStorage; +import com.simibubi.create.content.fluids.tank.storage.creative.CreativeFluidTankMountedStorage; +import com.simibubi.create.content.logistics.crate.CreativeCrateMountedStorage; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorage; +import com.simibubi.create.content.logistics.vault.ItemVaultMountedStorage; +import com.simibubi.create.impl.contraption.storage.FallbackMountedStorage; + +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.properties.ChestType; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.fluids.capability.templates.FluidTank; + import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.CombinedInvWrapper; +import net.minecraftforge.network.PacketDistributor; public class MountedStorageManager { + // builders used during assembly, null afterward + // ImmutableMap.Builder is not used because it will throw with duplicate keys, not override them + private Map itemsBuilder; + private Map fluidsBuilder; + private Map syncedItemsBuilder; + private Map syncedFluidsBuilder; - protected ContraptionInvWrapper inventory; - protected ContraptionInvWrapper fuelInventory; - protected CombinedTankWrapper fluidInventory; - protected Map storage; - protected Map fluidStorage; + // built data structures after assembly, null before + private ImmutableMap allItemStorages; + // different from allItemStorages, does not contain internal ones + protected MountedItemStorageWrapper items; + @Nullable + protected MountedItemStorageWrapper fuelItems; + protected MountedFluidStorageWrapper fluids; + + private ImmutableMap syncedItems; + private ImmutableMap syncedFluids; + + private List externalHandlers; + private CombinedInvWrapper allItems; + + // ticks until storage can sync again + private int syncCooldown; + + // client-side: not all storages are synced, this determines which interactions are valid + private Set interactablePositions; public MountedStorageManager() { - storage = new TreeMap<>(); - fluidStorage = new TreeMap<>(); + this.reset(); } - public void entityTick(AbstractContraptionEntity entity) { - fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, entity.level().isClientSide)); - } - - public void createHandlers() { - Collection itemHandlers = storage.values(); - - inventory = wrapItems(itemHandlers.stream() - .map(MountedStorage::getItemHandler) - .toList(), false); - - fuelInventory = wrapItems(itemHandlers.stream() - .filter(MountedStorage::canUseForFuel) - .map(MountedStorage::getItemHandler) - .toList(), true); - - fluidInventory = wrapFluids(fluidStorage.values() - .stream() - .map(MountedFluidStorage::getFluidHandler) - .collect(Collectors.toList())); - } - - protected ContraptionInvWrapper wrapItems(Collection list, boolean fuel) { - return new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); - } - - protected CombinedTankWrapper wrapFluids(Collection list) { - return new CombinedTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class)); - } - - public void addBlock(BlockPos localPos, BlockEntity be) { - if (be != null && MountedStorage.canUseAsStorage(be)) - storage.put(localPos, new MountedStorage(be)); - if (be != null && MountedFluidStorage.canUseAsStorage(be)) - fluidStorage.put(localPos, new MountedFluidStorage(be)); - } - - public void read(CompoundTag nbt, Map presentBlockEntities, boolean clientPacket) { - storage.clear(); - NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), c -> storage - .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data")))); - - fluidStorage.clear(); - NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), c -> fluidStorage - .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data")))); - - if (clientPacket && presentBlockEntities != null) - bindTanks(presentBlockEntities); - - List handlers = new ArrayList<>(); - List fuelHandlers = new ArrayList<>(); - for (MountedStorage mountedStorage : storage.values()) { - IItemHandlerModifiable itemHandler = mountedStorage.getItemHandler(); - handlers.add(itemHandler); - if (mountedStorage.canUseForFuel()) - fuelHandlers.add(itemHandler); + public void initialize() { + if (this.isInitialized()) { + // originally this threw an exception to try to catch mistakes. + // however, in the case where a Contraption is deserialized before its Entity, that would also throw, + // since both the deserialization and the onEntityCreated callback initialize the storage. + // this case occurs when placing a picked up minecart contraption. + // the reverse case is fine since deserialization also resets the manager first. + return; } - inventory = wrapItems(handlers, false); - fuelInventory = wrapItems(fuelHandlers, true); - fluidInventory = wrapFluids(fluidStorage.values() - .stream() - .map(MountedFluidStorage::getFluidHandler) - .toList()); + this.allItemStorages = ImmutableMap.copyOf(this.itemsBuilder); + + this.items = new MountedItemStorageWrapper(subMap(this.allItemStorages, this::isExposed)); + + this.allItems = this.items; + this.itemsBuilder = null; + + ImmutableMap fuelMap = subMap(this.allItemStorages, this::canUseForFuel); + this.fuelItems = fuelMap.isEmpty() ? null : new MountedItemStorageWrapper(fuelMap); + + ImmutableMap fluids = ImmutableMap.copyOf(this.fluidsBuilder); + this.fluids = new MountedFluidStorageWrapper(fluids); + this.fluidsBuilder = null; + + this.syncedItems = ImmutableMap.copyOf(this.syncedItemsBuilder); + this.syncedItemsBuilder = null; + this.syncedFluids = ImmutableMap.copyOf(this.syncedFluidsBuilder); + this.syncedFluidsBuilder = null; } - public void bindTanks(Map presentBlockEntities) { - fluidStorage.forEach((pos, mfs) -> { - BlockEntity blockEntity = presentBlockEntities.get(pos); - if (!(blockEntity instanceof FluidTankBlockEntity)) - return; - FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; - IFluidTank tankInventory = tank.getTankInventory(); - if (tankInventory instanceof FluidTank) - ((FluidTank) tankInventory).setFluid(mfs.tank.getFluid()); - tank.getFluidLevel() - .startWithValue(tank.getFillState()); - mfs.assignBlockEntity(tank); + private boolean isExposed(MountedItemStorage storage) { + return !AllMountedItemStorageTypeTags.INTERNAL.matches(storage); + } + + private boolean canUseForFuel(MountedItemStorage storage) { + return this.isExposed(storage) && !AllMountedItemStorageTypeTags.FUEL_BLACKLIST.matches(storage); + } + + private boolean isInitialized() { + return this.itemsBuilder == null; + } + + private void assertInitialized() { + if (!this.isInitialized()) { + throw new IllegalStateException("MountedStorageManager is uninitialized"); + } + } + + protected void reset() { + this.allItemStorages = null; + this.items = null; + this.fuelItems = null; + this.fluids = null; + this.externalHandlers = new ArrayList<>(); + this.allItems = null; + this.itemsBuilder = new HashMap<>(); + this.fluidsBuilder = new HashMap<>(); + this.syncedItemsBuilder = new HashMap<>(); + this.syncedFluidsBuilder = new HashMap<>(); + // interactablePositions intentionally not reset + } + + public void addBlock(Level level, BlockState state, BlockPos globalPos, BlockPos localPos, @Nullable BlockEntity be) { + MountedItemStorageType itemType = MountedItemStorageType.REGISTRY.get(state.getBlock()); + if (itemType != null) { + MountedItemStorage storage = itemType.mount(level, state, globalPos, be); + if (storage != null) { + this.addStorage(storage, localPos); + } + } + + MountedFluidStorageType fluidType = MountedFluidStorageType.REGISTRY.get(state.getBlock()); + if (fluidType != null) { + MountedFluidStorage storage = fluidType.mount(level, state, globalPos, be); + if (storage != null) { + this.addStorage(storage, localPos); + } + } + } + + public void unmount(Level level, StructureBlockInfo info, BlockPos globalPos, @Nullable BlockEntity be) { + BlockPos localPos = info.pos(); + BlockState state = info.state(); + + MountedItemStorage itemStorage = this.getAllItemStorages().get(localPos); + if (itemStorage != null) { + MountedItemStorageType expectedType = MountedItemStorageType.REGISTRY.get(state.getBlock()); + if (itemStorage.type == expectedType) { + itemStorage.unmount(level, state, globalPos, be); + } + } + + MountedFluidStorage fluidStorage = this.getFluids().storages.get(localPos); + if (fluidStorage != null) { + MountedFluidStorageType expectedType = MountedFluidStorageType.REGISTRY.get(state.getBlock()); + if (fluidStorage.type == expectedType) { + fluidStorage.unmount(level, state, globalPos, be); + } + } + } + + public void tick(AbstractContraptionEntity entity) { + if (this.syncCooldown > 0) { + this.syncCooldown--; + return; + } + + Map items = new HashMap<>(); + Map fluids = new HashMap<>(); + this.syncedItems.forEach((pos, storage) -> { + if (storage.isDirty()) { + items.put(pos, (MountedItemStorage) storage); + storage.markClean(); + } + }); + this.syncedFluids.forEach((pos, storage) -> { + if (storage.isDirty()) { + fluids.put(pos, (MountedFluidStorage) storage); + storage.markClean(); + } + }); + + if (!items.isEmpty() || !fluids.isEmpty()) { + MountedStorageSyncPacket packet = new MountedStorageSyncPacket(entity.getId(), items, fluids); + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), packet); + this.syncCooldown = 8; + } + } + + public void handleSync(MountedStorageSyncPacket packet, AbstractContraptionEntity entity) { + // packet only contains changed storages, grab existing ones before resetting + ImmutableMap items = this.getAllItemStorages(); + MountedFluidStorageWrapper fluids = this.getFluids(); + this.reset(); + + // track freshly synced storages + Map syncedStorages = new IdentityHashMap<>(); + + try { + // re-add existing ones + this.itemsBuilder.putAll(items); + this.fluidsBuilder.putAll(fluids.storages); + // add newly synced ones, overriding existing ones if present + packet.items.forEach((pos, storage) -> { + this.itemsBuilder.put(pos, storage); + syncedStorages.put((SyncedMountedStorage) storage, pos); + }); + packet.fluids.forEach((pos, storage) -> { + this.fluidsBuilder.put(pos, storage); + syncedStorages.put((SyncedMountedStorage) storage, pos); + }); + } catch (Throwable t) { + // an exception will leave the manager in an invalid state + Create.LOGGER.error("An error occurred while syncing a MountedStorageManager", t); + } + + this.initialize(); + + // call all afterSync methods + Contraption contraption = entity.getContraption(); + syncedStorages.forEach((storage, pos) -> storage.afterSync(contraption, pos)); + } + + // contraption is provided on the client for initial afterSync storage callbacks + public void read(CompoundTag nbt, boolean clientPacket, @Nullable Contraption contraption) { + this.reset(); + + try { + NBTHelper.iterateCompoundList(nbt.getList("items", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("pos")); + CompoundTag data = tag.getCompound("storage"); + MountedItemStorage.CODEC.decode(NbtOps.INSTANCE, data) + .result() + .map(Pair::getFirst) + .ifPresent(storage -> this.addStorage(storage, pos)); + }); + + NBTHelper.iterateCompoundList(nbt.getList("fluids", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("pos")); + CompoundTag data = tag.getCompound("storage"); + MountedFluidStorage.CODEC.decode(NbtOps.INSTANCE, data) + .result() + .map(Pair::getFirst) + .ifPresent(storage -> this.addStorage(storage, pos)); + }); + + this.readLegacy(nbt); + + if (nbt.contains("interactable_positions")) { + this.interactablePositions = new HashSet<>(); + NBTHelper.iterateCompoundList(nbt.getList("interactable_positions", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag); + this.interactablePositions.add(pos); + }); + } + } catch (Throwable t) { + Create.LOGGER.error("Error deserializing mounted storage", t); + // an exception will leave the manager in an invalid state, initialize must be called + } + + this.initialize(); + + // for client sync, run initial afterSync callbacks + if (!clientPacket || contraption == null) + return; + + this.getAllItemStorages().forEach((pos, storage) -> { + if (storage instanceof SyncedMountedStorage synced) { + synced.afterSync(contraption, pos); + } + }); + this.getFluids().storages.forEach((pos, storage) -> { + if (storage instanceof SyncedMountedStorage synced) { + synced.afterSync(contraption, pos); + } }); } public void write(CompoundTag nbt, boolean clientPacket) { - ListTag storageNBT = new ListTag(); - if (!clientPacket) - for (BlockPos pos : storage.keySet()) { - CompoundTag c = new CompoundTag(); - MountedStorage mountedStorage = storage.get(pos); - if (!mountedStorage.isValid()) - continue; - c.put("Pos", NbtUtils.writeBlockPos(pos)); - c.put("Data", mountedStorage.serialize()); - storageNBT.add(c); + ListTag items = new ListTag(); + this.getAllItemStorages().forEach((pos, storage) -> { + if (!clientPacket || storage instanceof SyncedMountedStorage) { + MountedItemStorage.CODEC.encodeStart(NbtOps.INSTANCE, storage).result().ifPresent(encoded -> { + CompoundTag tag = new CompoundTag(); + tag.put("pos", NbtUtils.writeBlockPos(pos)); + tag.put("storage", encoded); + items.add(tag); + }); + } } - - ListTag fluidStorageNBT = new ListTag(); - for (BlockPos pos : fluidStorage.keySet()) { - CompoundTag c = new CompoundTag(); - MountedFluidStorage mountedStorage = fluidStorage.get(pos); - if (!mountedStorage.isValid()) - continue; - c.put("Pos", NbtUtils.writeBlockPos(pos)); - c.put("Data", mountedStorage.serialize()); - fluidStorageNBT.add(c); + ); + if (!items.isEmpty()) { + nbt.put("items", items); } - nbt.put("Storage", storageNBT); - nbt.put("FluidStorage", fluidStorageNBT); - } - - public void removeStorageFromWorld() { - storage.values() - .forEach(MountedStorage::removeStorageFromWorld); - fluidStorage.values() - .forEach(MountedFluidStorage::removeStorageFromWorld); - } - - public void addStorageToWorld(StructureBlockInfo block, BlockEntity blockEntity) { - if (storage.containsKey(block.pos())) { - MountedStorage mountedStorage = storage.get(block.pos()); - if (mountedStorage.isValid()) - mountedStorage.addStorageToWorld(blockEntity); + ListTag fluids = new ListTag(); + this.getFluids().storages.forEach((pos, storage) -> { + if (!clientPacket || storage instanceof SyncedMountedStorage) { + MountedFluidStorage.CODEC.encodeStart(NbtOps.INSTANCE, storage).result().ifPresent(encoded -> { + CompoundTag tag = new CompoundTag(); + tag.put("pos", NbtUtils.writeBlockPos(pos)); + tag.put("storage", encoded); + fluids.add(tag); + }); + } + } + ); + if (!fluids.isEmpty()) { + nbt.put("fluids", fluids); } - if (fluidStorage.containsKey(block.pos())) { - MountedFluidStorage mountedStorage = fluidStorage.get(block.pos()); - if (mountedStorage.isValid()) - mountedStorage.addStorageToWorld(blockEntity); + if (clientPacket) { + // let the client know of all non-synced ones too + SetView positions = Sets.union(this.getAllItemStorages().keySet(), this.getFluids().storages.keySet()); + ListTag list = new ListTag(); + for (BlockPos pos : positions) { + list.add(NbtUtils.writeBlockPos(pos)); + } + nbt.put("interactable_positions", list); } } - public void clear() { - for (int i = 0; i < inventory.getSlots(); i++) - if (!inventory.isSlotExternal(i)) - inventory.setStackInSlot(i, ItemStack.EMPTY); - for (int i = 0; i < fluidInventory.getTanks(); i++) - fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE); - } - - public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) { - MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos); - if (mountedFluidStorage != null) - mountedFluidStorage.updateFluid(containedFluid); - } - public void attachExternal(IItemHandlerModifiable externalStorage) { - inventory = new ContraptionInvWrapper(externalStorage, inventory); - fuelInventory = new ContraptionInvWrapper(externalStorage, fuelInventory); + this.externalHandlers.add(externalStorage); + IItemHandlerModifiable[] all = new IItemHandlerModifiable[this.externalHandlers.size() + 1]; + all[0] = this.items; + for (int i = 0; i < this.externalHandlers.size(); i++) { + all[i + 1] = this.externalHandlers.get(i); + } + + this.allItems = new CombinedInvWrapper(all); } - public IItemHandlerModifiable getItems() { - return inventory; + /** + * The primary way to access a contraption's inventory. Includes all + * non-internal mounted storages as well as all external storage. + */ + public CombinedInvWrapper getAllItems() { + this.assertInitialized(); + return this.allItems; } - public IItemHandlerModifiable getFuelItems() { - return fuelInventory; + /** + * Gets a map of all MountedItemStorages in the contraption, irrelevant of them being internal or providing fuel. + */ + public ImmutableMap getAllItemStorages() { + this.assertInitialized(); + return this.allItemStorages; } - public IFluidHandler getFluids() { - return fluidInventory; + /** + * Gets an item handler wrapping all non-internal mounted storages. This is not + * the whole contraption inventory as it does not include external storages. + * Most often, you want {@link #getAllItems()}, which does. + */ + public MountedItemStorageWrapper getMountedItems() { + this.assertInitialized(); + return this.items; + } + + /** + * Gets an item handler wrapping all non-internal mounted storages that provide fuel. + * May be null if none are present. + */ + @Nullable + public MountedItemStorageWrapper getFuelItems() { + this.assertInitialized(); + return this.fuelItems; + } + + /** + * Gets a fluid handler wrapping all mounted fluid storages. + */ + public MountedFluidStorageWrapper getFluids() { + this.assertInitialized(); + return this.fluids; } public boolean handlePlayerStorageInteraction(Contraption contraption, Player player, BlockPos localPos) { - if (player.level().isClientSide()) { - BlockEntity localBE = contraption.presentBlockEntities.get(localPos); - return MountedStorage.canUseAsStorage(localBE); + if (!(player instanceof ServerPlayer serverPlayer)) { + return this.interactablePositions != null && this.interactablePositions.contains(localPos); } - MountedStorageManager storageManager = contraption.getStorageForSpawnPacket(); - MountedStorage storage = storageManager.storage.get(localPos); - if (storage == null || storage.getItemHandler() == null) + StructureBlockInfo info = contraption.getBlocks().get(localPos); + if (info == null) return false; - IItemHandlerModifiable handler = storage.getItemHandler(); - StructureBlockInfo info = contraption.getBlocks() - .get(localPos); - if (info != null && info.state().hasProperty(ChestBlock.TYPE)) { - ChestType chestType = info.state().getValue(ChestBlock.TYPE); - Direction facing = info.state().getOptionalValue(ChestBlock.FACING) - .orElse(Direction.SOUTH); - Direction connectedDirection = - chestType == ChestType.LEFT ? facing.getClockWise() : facing.getCounterClockWise(); + MountedStorageManager storageManager = contraption.getStorage(); + MountedItemStorage storage = storageManager.getAllItemStorages().get(localPos); - if (chestType != ChestType.SINGLE) { - MountedStorage storage2 = storageManager.storage.get(localPos.relative(connectedDirection)); - if (storage2 != null && storage2.getItemHandler() != null) - handler = chestType == ChestType.RIGHT ? new CombinedInvWrapper(handler, storage2.getItemHandler()) - : new CombinedInvWrapper(storage2.getItemHandler(), handler); - } + if (storage != null) { + return storage.handleInteraction(serverPlayer, contraption, info); + } else { + return false; } - - int slotCount = handler.getSlots(); - if (slotCount == 0) - return false; - if (slotCount % 9 != 0) - return false; - - Supplier stillValid = () -> contraption.entity.isAlive() - && player.distanceToSqr(contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0)) < 64; - Component name = info != null ? info.state().getBlock() - .getName() : Components.literal("Container"); - player.openMenu(MountedStorageInteraction.createMenuProvider(name, handler, slotCount, stillValid)); - - Vec3 soundPos = contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0); - player.level().playSound(null, BlockPos.containing(soundPos), SoundEvents.BARREL_OPEN, SoundSource.BLOCKS, 0.75f, 1f); - return true; } + private void readLegacy(CompoundTag nbt) { + NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("Pos")); + CompoundTag data = tag.getCompound("Data"); + + if (data.contains("Toolbox")) { + this.addStorage(ToolboxMountedStorage.fromLegacy(data), pos); + } else if (data.contains("NoFuel")) { + this.addStorage(ItemVaultMountedStorage.fromLegacy(data), pos); + } else if (data.contains("Bottomless")) { + ItemStack supplied = ItemStack.of(data.getCompound("ProvidedStack")); + this.addStorage(new CreativeCrateMountedStorage(supplied), pos); + } else if (data.contains("Synced")) { + this.addStorage(DepotMountedStorage.fromLegacy(data), pos); + } else { + // we can create a fallback storage safely, it will be validated before unmounting + ItemStackHandler handler = new ItemStackHandler(); + handler.deserializeNBT(data); + this.addStorage(new FallbackMountedStorage(handler), pos); + } + }); + + NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("Pos")); + CompoundTag data = tag.getCompound("Data"); + + if (data.contains("Bottomless")) { + this.addStorage(CreativeFluidTankMountedStorage.fromLegacy(data), pos); + } else { + this.addStorage(FluidTankMountedStorage.fromLegacy(data), pos); + } + }); + } + + private void addStorage(MountedItemStorage storage, BlockPos pos) { + this.itemsBuilder.put(pos, storage); + if (storage instanceof SyncedMountedStorage synced) + this.syncedItemsBuilder.put(pos, synced); + } + + private void addStorage(MountedFluidStorage storage, BlockPos pos) { + this.fluidsBuilder.put(pos, storage); + if (storage instanceof SyncedMountedStorage synced) + this.syncedFluidsBuilder.put(pos, synced); + } + + private static ImmutableMap subMap(Map map, Predicate predicate) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + map.forEach((key, value) -> { + if (predicate.test(value)) { + builder.put(key, value); + } + }); + return builder.build(); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageSyncPacket.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageSyncPacket.java new file mode 100644 index 0000000000..751990c21a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageSyncPacket.java @@ -0,0 +1,63 @@ +package com.simibubi.create.content.contraptions; + +import java.util.Map; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; + +import net.minecraftforge.network.NetworkEvent.Context; + +public class MountedStorageSyncPacket extends SimplePacketBase { + public final int contraptionId; + public final Map items; + public final Map fluids; + + public MountedStorageSyncPacket(int contraptionId, Map items, Map fluids) { + this.contraptionId = contraptionId; + this.items = items; + this.fluids = fluids; + } + + public MountedStorageSyncPacket(FriendlyByteBuf buf) { + this.contraptionId = buf.readVarInt(); + this.items = read(buf, MountedItemStorage.CODEC); + this.fluids = read(buf, MountedFluidStorage.CODEC); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(this.contraptionId); + write(buffer, this.items, MountedItemStorage.CODEC); + write(buffer, this.fluids, MountedFluidStorage.CODEC); + } + + @SuppressWarnings("deprecation") + private static void write(FriendlyByteBuf buf, Map map, Codec codec) { + buf.writeMap(map, FriendlyByteBuf::writeBlockPos, (b, t) -> b.writeWithCodec(NbtOps.INSTANCE, codec, t)); + } + + @SuppressWarnings("deprecation") + private static Map read(FriendlyByteBuf buf, Codec codec) { + return buf.readMap(FriendlyByteBuf::readBlockPos, (b) -> b.readWithCodec(NbtOps.INSTANCE, codec)); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Entity entity = Minecraft.getInstance().level.getEntity(this.contraptionId); + if (!(entity instanceof AbstractContraptionEntity contraption)) + return; + + contraption.getContraption().getStorage().handleSync(this, contraption); + }); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java index 736f5e1863..e98f98ea49 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.contraptions; -import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp; -import static com.simibubi.create.foundation.utility.AngleHelper.wrapAngle180; +import static net.createmod.catnip.math.AngleHelper.angleLerp; import java.util.Optional; import java.util.UUID; @@ -10,6 +9,7 @@ import javax.annotation.Nullable; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageWrapper; import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; import com.simibubi.create.content.contraptions.minecart.MinecartSim2020; import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; @@ -17,12 +17,12 @@ import com.simibubi.create.content.contraptions.minecart.capability.MinecartCont import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity.CartMovementMode; import com.simibubi.create.content.contraptions.mounted.MountedContraption; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -46,6 +46,7 @@ import net.minecraft.world.level.block.BaseRailBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.LazyOptional; @@ -97,7 +98,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } public static OrientedContraptionEntity createAtYaw(Level world, Contraption contraption, - Direction initialOrientation, float initialYaw) { + Direction initialOrientation, float initialYaw) { OrientedContraptionEntity entity = create(world, contraption, initialOrientation); entity.startAtYaw(initialYaw); entity.manuallyPlaced = true; @@ -257,8 +258,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { boolean rotationLock = false; boolean pauseWhileRotating = false; boolean wasStalled = isStalled(); - if (contraption instanceof MountedContraption) { - MountedContraption mountedContraption = (MountedContraption) contraption; + if (contraption instanceof MountedContraption mountedContraption) { rotationLock = mountedContraption.rotationMode == CartMovementMode.ROTATION_LOCKED; pauseWhileRotating = mountedContraption.rotationMode == CartMovementMode.ROTATE_PAUSED; } @@ -344,17 +344,15 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { return false; } - if (contraption instanceof StabilizedContraption) { - if (!(riding instanceof OrientedContraptionEntity)) + if (contraption instanceof StabilizedContraption stabilized) { + if (!(riding instanceof OrientedContraptionEntity parent)) return false; - StabilizedContraption stabilized = (StabilizedContraption) contraption; Direction facing = stabilized.getFacing(); if (facing.getAxis() .isVertical()) return false; - OrientedContraptionEntity parent = (OrientedContraptionEntity) riding; prevYaw = yaw; - yaw = wrapAngle180(getInitialYaw() - parent.getInitialYaw()) - parent.getViewYRot(1); + yaw = AngleHelper.wrapAngle180(getInitialYaw() - parent.getInitialYaw()) - parent.getViewYRot(1); return false; } @@ -371,12 +369,10 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { Vec3 motion = movementVector.normalize(); if (!rotationLock) { - if (riding instanceof AbstractMinecart) { - AbstractMinecart minecartEntity = (AbstractMinecart) riding; + if (riding instanceof AbstractMinecart minecartEntity) { BlockPos railPosition = minecartEntity.getCurrentRailPosition(); BlockState blockState = level().getBlockState(railPosition); - if (blockState.getBlock() instanceof BaseRailBlock) { - BaseRailBlock abstractRailBlock = (BaseRailBlock) blockState.getBlock(); + if (blockState.getBlock() instanceof BaseRailBlock abstractRailBlock) { RailShape railDirection = abstractRailBlock.getRailDirection(blockState, level(), railPosition, minecartEntity); motion = VecHelper.project(motion, MinecartSim2020.getRailVec(railDirection)); @@ -406,9 +402,8 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } protected void powerFurnaceCartWithFuelFromStorage(Entity riding) { - if (!(riding instanceof MinecartFurnace)) + if (!(riding instanceof MinecartFurnace furnaceCart)) return; - MinecartFurnace furnaceCart = (MinecartFurnace) riding; // Notify to not trigger serialization side-effects isSerializingFurnaceCart = true; @@ -435,9 +430,12 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { .normalize() .scale(1)); if (fuel < 5 && contraption != null) { - ItemStack coal = ItemHelper.extract(contraption.getSharedInventory(), FUEL_ITEMS, 1, false); - if (!coal.isEmpty()) - fuel += 3600; + MountedItemStorageWrapper fuelItems = contraption.getStorage().getFuelItems(); + if (fuelItems != null) { + ItemStack coal = ItemHelper.extract(fuelItems, FUEL_ITEMS, 1, false); + if (!coal.isEmpty()) + fuel += 3600; + } } if (fuel != fuelBefore || pushX != 0 || pushZ != 0) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java b/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java index f781e0b8d4..72f0b5e673 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java +++ b/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java @@ -4,8 +4,13 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.api.contraption.transformable.MovedBlockTransformerRegistries; +import com.simibubi.create.api.contraption.transformable.MovedBlockTransformerRegistries.BlockEntityTransformer; +import com.simibubi.create.api.contraption.transformable.MovedBlockTransformerRegistries.BlockTransformer; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -129,8 +134,12 @@ public class StructureTransform { } public void apply(BlockEntity be) { - if (be instanceof ITransformableBlockEntity) - ((ITransformableBlockEntity) be).transform(this); + BlockEntityTransformer transformer = MovedBlockTransformerRegistries.BLOCK_ENTITY_TRANSFORMERS.get(be.getType()); + if (transformer != null) { + transformer.transform(be, this); + } else if (be instanceof TransformableBlockEntity itbe) { + itbe.transform(be, this); + } } /** @@ -140,8 +149,12 @@ public class StructureTransform { */ public BlockState apply(BlockState state) { Block block = state.getBlock(); - if (block instanceof ITransformableBlock transformable) + BlockTransformer transformer = MovedBlockTransformerRegistries.BLOCK_TRANSFORMERS.get(block); + if (transformer != null) { + return transformer.transform(state, this); + } else if (block instanceof TransformableBlock transformable) { return transformable.transform(state, this); + } if (mirror != null) state = state.mirror(mirror); diff --git a/src/main/java/com/simibubi/create/content/contraptions/TrainCollisionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/TrainCollisionPacket.java index 3da40de44b..63317132ba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/TrainCollisionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/TrainCollisionPacket.java @@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvents; diff --git a/src/main/java/com/simibubi/create/content/contraptions/TranslatingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/TranslatingContraption.java index 0c902d7206..62950dea65 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/TranslatingContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/TranslatingContraption.java @@ -55,5 +55,5 @@ public abstract class TranslatingContraption extends Contraption { public boolean canBeStabilized(Direction facing, BlockPos localPos) { return AllConfigs.server().kinetics.stabiliseStableContraptions.get(); } - + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlock.java index 9898d1549a..fc0115820d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlock.java @@ -51,6 +51,12 @@ public class ContraptionControlsBlock extends ControlsBlock implements IBE getBlockEntityClass() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlockEntity.java index 3aa4dfa3c4..1d4e3a24f6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlockEntity.java @@ -9,14 +9,14 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.DyeHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -25,6 +25,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -50,7 +51,7 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity { @Override public void addBehaviours(List behaviours) { behaviours.add(filtering = new FilteringBehaviour(this, new ControlsSlot())); - filtering.setLabel(Lang.translateDirect("contraptions.contoller.target")); + filtering.setLabel(CreateLang.translateDirect("contraptions.contoller.target")); filtering.withPredicate(AllItemTags.CONTRAPTION_CONTROLLED::matches); } @@ -106,18 +107,18 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity { } public static void sendStatus(Player player, ItemStack filter, boolean enabled) { - MutableComponent state = Lang.translate("contraption.controls.actor_toggle." + (enabled ? "on" : "off")) + MutableComponent state = CreateLang.translate("contraption.controls.actor_toggle." + (enabled ? "on" : "off")) .color(DyeHelper.getDyeColors(enabled ? DyeColor.LIME : DyeColor.ORANGE) .getFirst()) .component(); if (filter.isEmpty()) { - Lang.translate("contraption.controls.all_actor_toggle", state) + CreateLang.translate("contraption.controls.all_actor_toggle", state) .sendStatus(player); return; } - Lang.translate("contraption.controls.specific_actor_toggle", filter.getHoverName() + CreateLang.translate("contraption.controls.specific_actor_toggle", filter.getHoverName() .getString(), state) .sendStatus(player); } @@ -125,14 +126,14 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity { public static class ControlsSlot extends ValueBoxTransform.Sided { @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Direction facing = state.getValue(ControlsBlock.FACING); float yRot = AngleHelper.horizontalAngle(facing); - return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12f, 5.5f), yRot, Axis.Y); + return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 14f, 5.5f), yRot, Axis.Y); } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { Direction facing = state.getValue(ControlsBlock.FACING); float yRot = AngleHelper.horizontalAngle(facing); TransformStack.of(ms) diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovement.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovement.java index e0bf94a583..8407e50bf2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovement.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovement.java @@ -1,21 +1,22 @@ package com.simibubi.create.content.contraptions.actors.contraptionControls; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.ItemHandlerHelper; @@ -134,7 +135,7 @@ public class ContraptionControlsMovement implements MovementBehaviour { efs.targetYEqualsSelection = efs.currentTargetY == ec.clientYTarget; if (ec.isTargetUnreachable(efs.currentTargetY)) - efs.currentLongName = Lang.translate("contraption.controls.floor_unreachable") + efs.currentLongName = CreateLang.translate("contraption.controls.floor_unreachable") .string(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovingInteraction.java index 1eb3de3367..8c5700c37f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovingInteraction.java @@ -5,15 +5,14 @@ import java.util.List; import org.apache.commons.lang3.tuple.MutablePair; -import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement.ElevatorFloorSelection; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; import com.simibubi.create.content.contraptions.elevator.ElevatorTargetFloorPacket; @@ -24,6 +23,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.network.PacketDistributor; public class ContraptionControlsMovingInteraction extends MovingInteractionBehaviour { @@ -71,7 +71,7 @@ public class ContraptionControlsMovingInteraction extends MovingInteractionBehav if (invert) { for (MutablePair pair : contraption.getActors()) { - MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.left.state()); + MovementBehaviour behaviour = MovementBehaviour.REGISTRY.get(pair.left.state()); if (behaviour == null) continue; ItemStack behaviourStack = behaviour.canBeDisabledVia(pair.right); diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsRenderer.java index 5dfb49ffac..44e9bded98 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsRenderer.java @@ -11,16 +11,16 @@ import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.redstone.nixieTube.NixieTubeRenderer; import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.DyeHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; @@ -57,14 +57,14 @@ public class ContraptionControlsRenderer extends SmartBlockEntityRenderer property : state.getProperties()) { - if (!(property instanceof IntegerProperty)) + if (!(property instanceof IntegerProperty ageProperty)) continue; - IntegerProperty ageProperty = (IntegerProperty) property; if (!property.getName() .equals(BlockStateProperties.AGE_1.getName())) continue; @@ -167,14 +169,13 @@ public class HarvesterMovementBehaviour implements MovementBehaviour { } Block block = state.getBlock(); - if (block instanceof CropBlock) { - CropBlock crop = (CropBlock) block; + if (block instanceof CropBlock crop) { return crop.getStateForAge(0); } if (block == Blocks.SWEET_BERRY_BUSH) { return state.setValue(BlockStateProperties.AGE_3, Integer.valueOf(1)); } - if (state.is(AllTags.AllBlockTags.SUGAR_CANE_VARIANTS.tag) || block instanceof GrowingPlantBlock) { + if (AllBlockTags.SUGAR_CANE_VARIANTS.matches(block) || block instanceof GrowingPlantBlock) { if (state.getFluidState() .isEmpty()) return Blocks.AIR.defaultBlockState(); @@ -207,15 +208,15 @@ public class HarvesterMovementBehaviour implements MovementBehaviour { @Override public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffers) { - if (!VisualizationManager.supportsVisualization(context.world)) + ContraptionMatrices matrices, MultiBufferSource buffers) { + if (!VisualizationManager.supportsVisualization(context.world)) HarvesterRenderer.renderInContraption(context, renderWorld, matrices, buffers); } @Nullable @Override public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld, - MovementContext movementContext) { + MovementContext movementContext) { return new HarvesterActorVisual(visualizationContext, simulationWorld, movementContext); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterRenderer.java index 0aa9b7102c..f1a865b9df 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterRenderer.java @@ -7,13 +7,13 @@ import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -33,7 +33,7 @@ public class HarvesterRenderer extends SafeBlockEntityRenderer dropItem(context, s)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PIInstance.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PIInstance.java index 4f7e371cfa..6fcb9af8cd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PIInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PIInstance.java @@ -2,13 +2,12 @@ package com.simibubi.create.content.contraptions.actors.psi; import java.util.function.Consumer; -import com.simibubi.create.foundation.utility.AngleHelper; - import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstancerProvider; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; @@ -24,17 +23,15 @@ public class PIInstance { TransformedInstance middle; TransformedInstance top; - public PIInstance(InstancerProvider instancerProvider, BlockState blockState, BlockPos instancePos) { + public PIInstance(InstancerProvider instancerProvider, BlockState blockState, BlockPos instancePos, boolean lit) { this.instancerProvider = instancerProvider; this.blockState = blockState; this.instancePos = instancePos; Direction facing = blockState.getValue(PortableStorageInterfaceBlock.FACING); angleX = facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90; angleY = AngleHelper.horizontalAngle(facing); - } - - public void init(boolean lit) { this.lit = lit; + middle = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(PortableStorageInterfaceRenderer.getMiddleForState(blockState, lit))) .createInstance(); top = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(PortableStorageInterfaceRenderer.getTopForState(blockState))) diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIActorVisual.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIActorVisual.java index 130d8dc82a..0b9ecc1747 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIActorVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIActorVisual.java @@ -2,11 +2,11 @@ package com.simibubi.create.content.contraptions.actors.psi; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ActorVisual; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.animation.LerpedFloat; public class PSIActorVisual extends ActorVisual { @@ -15,9 +15,8 @@ public class PSIActorVisual extends ActorVisual { public PSIActorVisual(VisualizationContext context, VirtualRenderWorld world, MovementContext movementContext) { super(context, world, movementContext); - instance = new PIInstance(context.instancerProvider(), movementContext.state, movementContext.localPos); + instance = new PIInstance(context.instancerProvider(), movementContext.state, movementContext.localPos, false); - instance.init(false); instance.middle.light(localBlockLight(), 0); instance.top.light(localBlockLight(), 0); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIVisual.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIVisual.java index e92d39b744..557c9a6372 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIVisual.java @@ -17,9 +17,8 @@ public class PSIVisual extends AbstractBlockEntityVisual oldcap = capability; - capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.getSharedFluidTanks())); + capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.getStorage().getFluids())); oldcap.invalidate(); super.startTransferringTo(contraption, distance); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java index fd72d56279..df3e2439ce 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java @@ -25,7 +25,7 @@ public class PortableItemInterfaceBlockEntity extends PortableStorageInterfaceBl @Override public void startTransferringTo(Contraption contraption, float distance) { LazyOptional oldCap = capability; - capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.getSharedInventory())); + capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.getStorage().getAllItems())); oldCap.invalidate(); super.startTransferringTo(contraption, distance); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlockEntity.java index 18d13c84b6..182343445d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlockEntity.java @@ -7,9 +7,9 @@ import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.LerpedFloat; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement.java index e72ad5c8a7..48be250c0e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement.java @@ -4,18 +4,18 @@ import java.util.Optional; import org.jetbrains.annotations.Nullable; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ActorVisual; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.trains.entity.CarriageContraption; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -24,6 +24,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceRenderer.java index 99e1ecfb21..61b2900cfc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceRenderer.java @@ -9,15 +9,15 @@ import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -62,8 +62,8 @@ public class PortableStorageInterfaceRenderer extends SafeBlockEntityRenderer drawCallback) { - SuperByteBuffer middle = CachedBufferer.partial(getMiddleForState(blockState, lit), blockState); - SuperByteBuffer top = CachedBufferer.partial(getTopForState(blockState), blockState); + SuperByteBuffer middle = CachedBuffers.partial(getMiddleForState(blockState, lit), blockState); + SuperByteBuffer top = CachedBuffers.partial(getTopForState(blockState), blockState); if (local != null) { middle.transform(local); diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/PaveTask.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/PaveTask.java index abefe49a64..686eec71fe 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/PaveTask.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/PaveTask.java @@ -4,31 +4,30 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import com.simibubi.create.foundation.utility.Couple; - +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; public class PaveTask { - + private Couple horizontalInterval; private Map, Float> heightValues = new HashMap<>(); - + public PaveTask(double h1, double h2) { horizontalInterval = Couple.create(h1, h2); } - + public Couple getHorizontalInterval() { return horizontalInterval; } - + public void put(int x, int z, float y) { heightValues.put(Couple.create(x, z), y); } - + public float get(Couple coords) { return heightValues.get(coords); } - + public Set> keys() { return heightValues.keySet(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlock.java index 4e191d0c99..7085fe91df 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlock.java @@ -6,10 +6,10 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.actors.AttachedActorBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; import com.simibubi.create.foundation.placement.PoleHelper; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockEntity.java index d525bef7b1..0493ef5702 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockEntity.java @@ -10,16 +10,18 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.StairBlock; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -47,10 +49,10 @@ public class RollerBlockEntity extends SmartBlockEntity { @Override public void addBehaviours(List behaviours) { behaviours.add(filtering = new FilteringBehaviour(this, new RollerValueBox(3))); - behaviours.add(mode = new ScrollOptionBehaviour(RollingMode.class, - Lang.translateDirect("contraptions.roller_mode"), this, new RollerValueBox(-3))); + behaviours.add(mode = new ScrollOptionBehaviour<>(RollingMode.class, + CreateLang.translateDirect("contraptions.roller_mode"), this, new RollerValueBox(-3))); - filtering.setLabel(Lang.translateDirect("contraptions.mechanical_roller.pave_material")); + filtering.setLabel(CreateLang.translateDirect("contraptions.mechanical_roller.pave_material")); filtering.withCallback(this::onFilterChanged); filtering.withPredicate(this::isValidMaterial); mode.withCallback(this::onModeChanged); @@ -179,7 +181,7 @@ public class RollerBlockEntity extends SmartBlockEntity { } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { Direction facing = state.getValue(RollerBlock.FACING); float yRot = AngleHelper.horizontalAngle(facing) + 180; TransformStack.of(ms) @@ -188,15 +190,15 @@ public class RollerBlockEntity extends SmartBlockEntity { } @Override - public boolean testHit(BlockState state, Vec3 localHit) { - Vec3 offset = getLocalOffset(state); + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(level, pos, state); if (offset == null) return false; return localHit.distanceTo(offset) < scale / 3; } @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Direction facing = state.getValue(RollerBlock.FACING); float stateAngle = AngleHelper.horizontalAngle(facing) + 180; return VecHelper.rotateCentered(VecHelper.voxelSpace(8 + hOffset, 15.5f, 11), stateAngle, Axis.Y); diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java index f640dbd269..fe17bfd1aa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java @@ -10,7 +10,6 @@ import java.util.function.BiConsumer; import javax.annotation.Nullable; import com.simibubi.create.AllTags; -import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.actors.roller.RollerBlockEntity.RollingMode; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.pulley.PulleyContraption; @@ -31,15 +30,15 @@ import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import com.simibubi.create.infrastructure.config.AllConfigs; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -60,6 +59,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.registries.ForgeRegistries; public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour { @@ -197,7 +197,7 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour { if (!getStateToPaveWith(context).isAir()) { FilterItemStack filter = context.getFilterFromBE(); if (!ItemHelper - .extract(context.contraption.getSharedInventory(), + .extract(context.contraption.getStorage().getAllItems(), stack -> filter.test(context.world, stack), 1, true) .isEmpty()) startingY = 0; @@ -476,7 +476,7 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour { return PaveResult.FAIL; FilterItemStack filter = context.getFilterFromBE(); - ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(), + ItemStack held = ItemHelper.extract(context.contraption.getStorage().getAllItems(), stack -> filter.test(context.world, stack), 1, false); if (held.isEmpty()) return PaveResult.FAIL; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerRenderer.java index 06064e32b3..9bb7eb6b55 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerRenderer.java @@ -9,12 +9,12 @@ import com.simibubi.create.content.contraptions.actors.harvester.HarvesterRender import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -39,7 +39,7 @@ public class RollerRenderer extends SmartBlockEntityRenderer ms.pushPose(); ms.translate(0, -0.25, 0); - SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.ROLLER_WHEEL, blockState); + SuperByteBuffer superBuffer = CachedBuffers.partial(AllPartialModels.ROLLER_WHEEL, blockState); Direction facing = blockState.getValue(RollerBlock.FACING); superBuffer.translate(Vec3.atLowerCornerOf(facing.getNormal()) .scale(17 / 16f)); @@ -50,7 +50,7 @@ public class RollerRenderer extends SmartBlockEntityRenderer .renderInto(ms, vc); ms.popPose(); - CachedBufferer.partial(AllPartialModels.ROLLER_FRAME, blockState) + CachedBuffers.partial(AllPartialModels.ROLLER_FRAME, blockState) .rotateCentered(AngleHelper.rad(AngleHelper.horizontalAngle(facing) + 180), Direction.UP) .light(light) .renderInto(ms, vc); @@ -61,7 +61,7 @@ public class RollerRenderer extends SmartBlockEntityRenderer BlockState blockState = context.state; Direction facing = blockState.getValue(HORIZONTAL_FACING); VertexConsumer vc = buffers.getBuffer(RenderType.cutoutMipped()); - SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.ROLLER_WHEEL, blockState); + SuperByteBuffer superBuffer = CachedBuffers.partial(AllPartialModels.ROLLER_WHEEL, blockState); float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()) ? context.getAnimationSpeed() : -context.getAnimationSpeed()); @@ -84,7 +84,7 @@ public class RollerRenderer extends SmartBlockEntityRenderer .renderInto(viewProjection, vc); viewProjection.popPose(); - CachedBufferer.partial(AllPartialModels.ROLLER_FRAME, blockState) + CachedBuffers.partial(AllPartialModels.ROLLER_FRAME, blockState) .transform(matrices.getModel()) .rotateCentered(AngleHelper.rad(AngleHelper.horizontalAngle(facing) + 180), Direction.UP) .light(contraptionWorldLight) diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/TrackPaverV2.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/TrackPaverV2.java index e7b4fc6280..69dcd32465 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/TrackPaverV2.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/TrackPaverV2.java @@ -9,10 +9,10 @@ import java.util.Set; import com.simibubi.create.content.trains.graph.TrackEdge; import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.content.trains.track.BezierConnection; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; import net.minecraft.world.phys.AABB; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/ContraptionPlayerPassengerRotation.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/ContraptionPlayerPassengerRotation.java index d5c81643cc..54bf206ae8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/ContraptionPlayerPassengerRotation.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/ContraptionPlayerPassengerRotation.java @@ -3,10 +3,10 @@ package com.simibubi.create.content.contraptions.actors.seat; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.AbstractContraptionEntity.ContraptionRotationState; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatBlock.java index 2e2e85cf64..11c6c964af 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatBlock.java @@ -42,6 +42,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.common.util.FakePlayer; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @@ -128,7 +129,7 @@ public class SeatBlock extends Block implements ProperWaterloggedBlock { @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult p_225533_6_) { - if (player.isShiftKeyDown()) + if (player.isShiftKeyDown() || player instanceof FakePlayer) return InteractionResult.PASS; ItemStack heldItem = player.getItemInHand(hand); diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatEntity.java index b95b5733a3..fb9a258fa9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatEntity.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.actors.seat; import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.content.logistics.box.PackageEntity; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.entity.EntityRenderer; @@ -77,6 +78,8 @@ public class SeatEntity extends Entity implements IEntityAdditionalSpawnData { return 1 / 16f; if (entity instanceof Frog) return 1 / 8f + 1 / 64f; + if (entity instanceof PackageEntity) + return 1 / 4f; return 0; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatInteractionBehaviour.java index 522d0a9b26..81e1cb10a0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatInteractionBehaviour.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.contraptions.actors.seat; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatMovementBehaviour.java index f1a26404b7..d6540999f1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatMovementBehaviour.java @@ -3,11 +3,11 @@ package com.simibubi.create.content.contraptions.actors.seat; import java.util.Map; import java.util.UUID; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.SlabBlock; @@ -28,7 +28,7 @@ public class SeatMovementBehaviour implements MovementBehaviour { @Override public void visitNewPosition(MovementContext context, BlockPos pos) { MovementBehaviour.super.visitNewPosition(context, pos); - + AbstractContraptionEntity contraptionEntity = context.contraption.entity; if (contraptionEntity == null) return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsBlock.java index c9d13fb8d5..b784afb168 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsBlock.java @@ -67,4 +67,10 @@ public class ControlsBlock extends HorizontalDirectionalBlock implements IWrench return AllShapes.CONTROLS.get(pState.getValue(FACING)); } + @Override + public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, + CollisionContext pContext) { + return AllShapes.CONTROLS_COLLISION.get(pState.getValue(FACING)); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsHandler.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsHandler.java index d3a1b19192..d445205627 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsHandler.java @@ -12,7 +12,7 @@ import com.mojang.blaze3d.platform.InputConstants; import com.simibubi.create.AllPackets; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.utility.ControlsUtil; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; @@ -37,11 +37,11 @@ public class ControlsHandler { } public static void startControlling(AbstractContraptionEntity entity, BlockPos controllerLocalPos) { - entityRef = new WeakReference(entity); + entityRef = new WeakReference<>(entity); controlsPos = controllerLocalPos; Minecraft.getInstance().player.displayClientMessage( - Lang.translateDirect("contraption.controls.start_controlling", entity.getContraptionName()), true); + CreateLang.translateDirect("contraption.controls.start_controlling", entity.getContraptionName()), true); } public static void stopControlling() { @@ -58,7 +58,7 @@ public class ControlsHandler { controlsPos = null; currentlyPressed.clear(); - Minecraft.getInstance().player.displayClientMessage(Lang.translateDirect("contraption.controls.stop_controlling"), + Minecraft.getInstance().player.displayClientMessage(CreateLang.translateDirect("contraption.controls.stop_controlling"), true); } @@ -108,9 +108,9 @@ public class ControlsHandler { // Keepalive Pressed Keys if (packetCooldown == 0) { // if (!pressedKeys.isEmpty()) { - AllPackets.getChannel() - .sendToServer(new ControlsInputPacket(pressedKeys, true, entity.getId(), controlsPos, false)); - packetCooldown = PACKET_RATE; + AllPackets.getChannel() + .sendToServer(new ControlsInputPacket(pressedKeys, true, entity.getId(), controlsPos, false)); + packetCooldown = PACKET_RATE; // } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInteractionBehaviour.java index c513097a59..0d3b27dfa1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInteractionBehaviour.java @@ -4,12 +4,13 @@ import java.util.UUID; import com.google.common.base.Objects; import com.simibubi.create.AllItems; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsMovementBehaviour.java index 45f840136a..bba75321af 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsMovementBehaviour.java @@ -2,20 +2,21 @@ package com.simibubi.create.content.contraptions.actors.trainControls; import java.util.Collection; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.Direction; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsRenderer.java index 265542dbb3..c6e885f875 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsRenderer.java @@ -4,13 +4,13 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -25,7 +25,7 @@ public class ControlsRenderer { BlockState state = context.state; Direction facing = state.getValue(ControlsBlock.FACING); - SuperByteBuffer cover = CachedBufferer.partial(AllPartialModels.TRAIN_CONTROLS_COVER, state); + SuperByteBuffer cover = CachedBuffers.partial(AllPartialModels.TRAIN_CONTROLS_COVER, state); float hAngle = 180 + AngleHelper.horizontalAngle(facing); PoseStack ms = matrices.getModel(); cover.transform(ms) @@ -40,17 +40,17 @@ public class ControlsRenderer { for (boolean first : Iterate.trueAndFalse) { float vAngle = Mth.clamp(first ? firstLever * 70 - 25 : secondLever * 15, -45, 45); - SuperByteBuffer lever = CachedBufferer.partial(AllPartialModels.TRAIN_CONTROLS_LEVER, state); + SuperByteBuffer lever = CachedBuffers.partial(AllPartialModels.TRAIN_CONTROLS_LEVER, state); ms.pushPose(); TransformStack.of(ms) .center() .rotateYDegrees(hAngle) - .translate(0, 0, 4 / 16f) + .translate(0, 4 / 16f, 4 / 16f) .rotateXDegrees(vAngle - 45) .translate(0, yOffset, 0) .rotateXDegrees(45) .uncenter() - .translate(0, -2 / 16f, -3 / 16f) + .translate(0, -6 / 16f, -3 / 16f) .translate(first ? 0 : 6 / 16f, 0, 0); lever.transform(ms) .light(LevelRenderer.getLightColor(renderWorld, context.localPos)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsServerHandler.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsServerHandler.java index f3ef536d56..580ad57dbb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsServerHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsServerHandler.java @@ -9,9 +9,9 @@ import java.util.Map.Entry; import java.util.UUID; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.WorldAttached; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.data.WorldAttached; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.LevelAccessor; @@ -24,7 +24,7 @@ public class ControlsServerHandler { public static void tick(LevelAccessor world) { Map map = receivedInputs.get(world); for (Iterator> iterator = map.entrySet() - .iterator(); iterator.hasNext();) { + .iterator(); iterator.hasNext(); ) { Entry entry = iterator.next(); ControlsContext ctx = entry.getValue(); @@ -35,7 +35,7 @@ public class ControlsServerHandler { continue; } - for (Iterator entryIterator = list.iterator(); entryIterator.hasNext();) { + for (Iterator entryIterator = list.iterator(); entryIterator.hasNext(); ) { ManuallyPressedKey pressedKey = entryIterator.next(); pressedKey.decrement(); if (!pressedKey.isAlive()) @@ -61,7 +61,7 @@ public class ControlsServerHandler { } public static void receivePressed(LevelAccessor world, AbstractContraptionEntity entity, BlockPos controlsPos, - UUID uniqueID, Collection collect, boolean pressed) { + UUID uniqueID, Collection collect, boolean pressed) { Map map = receivedInputs.get(world); if (map.containsKey(uniqueID) && map.get(uniqueID).entity != entity) @@ -70,9 +70,9 @@ public class ControlsServerHandler { ControlsContext ctx = map.computeIfAbsent(uniqueID, $ -> new ControlsContext(entity, controlsPos)); Collection list = ctx.keys; - WithNext: for (Integer activated : collect) { - for (Iterator iterator = list.iterator(); iterator.hasNext();) { - ManuallyPressedKey entry = iterator.next(); + WithNext: + for (Integer activated : collect) { + for (ManuallyPressedKey entry : list) { Integer inputType = entry.getSecond(); if (inputType.equals(activated)) { if (!pressed) diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java index ce4f40be7b..40a3dd1d93 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java @@ -3,10 +3,11 @@ package com.simibubi.create.content.contraptions.bearing; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllContraptionTypes; import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AssemblyException; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.ContraptionType; import com.simibubi.create.content.decoration.copycat.CopycatBlockEntity; import com.simibubi.create.infrastructure.config.AllConfigs; @@ -48,7 +49,7 @@ public class BearingContraption extends Contraption { @Override public ContraptionType getType() { - return ContraptionType.BEARING; + return AllContraptionTypes.BEARING.get(); } @Override @@ -57,11 +58,11 @@ public class BearingContraption extends Contraption { } @Override - public void addBlock(BlockPos pos, Pair capture) { + public void addBlock(Level level, BlockPos pos, Pair capture) { BlockPos localPos = pos.subtract(anchor); if (!getBlocks().containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(getSailBlock(capture))) sailBlocks++; - super.addBlock(pos, capture); + super.addBlock(level, pos, capture); } private BlockState getSailBlock(Pair capture) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingRenderer.java index e77b0500b8..a565e53ad9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingRenderer.java @@ -4,12 +4,12 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -35,7 +35,7 @@ public class BearingRenderer .getValue(BlockStateProperties.FACING); PartialModel top = be.isWoodenTop() ? AllPartialModels.BEARING_TOP_WOODEN : AllPartialModels.BEARING_TOP; - SuperByteBuffer superBuffer = CachedBufferer.partial(top, be.getBlockState()); + SuperByteBuffer superBuffer = CachedBuffers.partial(top, be.getBlockState()); float interpolatedAngle = be.getInterpolatedAngle(partialTicks - 1); kineticRotationTransform(superBuffer, be, facing.getAxis(), (float) (interpolatedAngle / 180 * Math.PI), light); @@ -50,7 +50,7 @@ public class BearingRenderer @Override protected SuperByteBuffer getRotatedModel(KineticBlockEntity be, BlockState state) { - return CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, state, state + return CachedBuffers.partialFacing(AllPartialModels.SHAFT_HALF, state, state .getValue(BearingBlock.FACING) .getOpposite()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingVisual.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingVisual.java index e244c49cff..a246afcab8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingVisual.java @@ -6,9 +6,8 @@ import org.joml.Quaternionf; import com.mojang.math.Axis; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.base.BackHalfShaftVisual; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; -import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.content.kinetics.base.OrientedRotatingVisual; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.visual.DynamicVisual; @@ -18,20 +17,21 @@ import dev.engine_room.flywheel.lib.instance.OrientedInstance; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -public class BearingVisual extends BackHalfShaftVisual implements SimpleDynamicVisual { +public class BearingVisual extends OrientedRotatingVisual implements SimpleDynamicVisual { final OrientedInstance topInstance; final Axis rotationAxis; final Quaternionf blockOrientation; public BearingVisual(VisualizationContext context, B blockEntity, float partialTick) { - super(context, blockEntity, partialTick); + super(context, blockEntity, partialTick, Direction.SOUTH, blockEntity.getBlockState().getValue(BlockStateProperties.FACING).getOpposite(), Models.partial(AllPartialModels.SHAFT_HALF)); Direction facing = blockState.getValue(BlockStateProperties.FACING); - rotationAxis = Axis.of(Direction.get(Direction.AxisDirection.POSITIVE, axis).step()); + rotationAxis = Axis.of(Direction.get(Direction.AxisDirection.POSITIVE, rotationAxis()).step()); blockOrientation = getBlockStateOrientation(facing); diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlockEntity.java index 9a4786793a..30250093e4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlockEntity.java @@ -15,10 +15,11 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -54,7 +55,7 @@ public class ClockworkBearingBlockEntity extends KineticBlockEntity public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); operationMode = new ScrollOptionBehaviour<>(ClockHands.class, - Lang.translateDirect("contraptions.clockwork.clock_hands"), this, getMovementModeSlot()); + CreateLang.translateDirect("contraptions.clockwork.clock_hands"), this, getMovementModeSlot()); behaviours.add(operationMode); registerAwardables(behaviours, AllAdvancements.CLOCKWORK_BEARING); } @@ -240,7 +241,7 @@ public class ClockworkBearingBlockEntity extends KineticBlockEntity hourHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); hourHand.setRotationAxis(direction.getAxis()); level.addFreshEntity(hourHand); - + if (contraption.getLeft() .containsBlockBreakers()) award(AllAdvancements.CONTRAPTION_ACTORS); @@ -253,12 +254,12 @@ public class ClockworkBearingBlockEntity extends KineticBlockEntity minuteHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); minuteHand.setRotationAxis(direction.getAxis()); level.addFreshEntity(minuteHand); - + if (contraption.getRight() .containsBlockBreakers()) award(AllAdvancements.CONTRAPTION_ACTORS); } - + award(AllAdvancements.CLOCKWORK_BEARING); // Run @@ -290,10 +291,9 @@ public class ClockworkBearingBlockEntity extends KineticBlockEntity @Override public void attach(ControlledContraptionEntity contraption) { - if (!(contraption.getContraption() instanceof ClockworkContraption)) + if (!(contraption.getContraption() instanceof ClockworkContraption cc)) return; - ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); setChanged(); Direction facing = getBlockState().getValue(BlockStateProperties.FACING); BlockPos anchor = worldPosition.relative(facing, cc.offset + 1); @@ -379,9 +379,8 @@ public class ClockworkBearingBlockEntity extends KineticBlockEntity @Override public boolean isAttachedTo(AbstractContraptionEntity contraption) { - if (!(contraption.getContraption() instanceof ClockworkContraption)) + if (!(contraption.getContraption() instanceof ClockworkContraption cc)) return false; - ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); if (cc.handType == HandType.HOUR) return this.hourHand == contraption; else diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkContraption.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkContraption.java index 8ceca23c08..ff5572f501 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkContraption.java @@ -6,11 +6,12 @@ import java.util.Set; import org.apache.commons.lang3.tuple.Pair; +import com.simibubi.create.AllContraptionTypes; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AssemblyException; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.ContraptionType; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -25,7 +26,7 @@ public class ClockworkContraption extends Contraption { @Override public ContraptionType getType() { - return ContraptionType.CLOCKWORK; + return AllContraptionTypes.CLOCKWORK.get(); } private void ignoreBlocks(Set blocks, BlockPos anchor) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlockEntity.java index d0b8ef8a4d..e581e3acbb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlockEntity.java @@ -13,10 +13,10 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -60,7 +60,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); movementMode = new ScrollOptionBehaviour<>(RotationMode.class, - Lang.translateDirect("contraptions.movement_mode"), this, getMovementModeSlot()); + CreateLang.translateDirect("contraptions.movement_mode"), this, getMovementModeSlot()); behaviours.add(movementMode); registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/SailBlock.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/SailBlock.java index a7096b4a2d..e6886903ba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/SailBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/SailBlock.java @@ -11,12 +11,12 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingMovementBehaviour.java index 310add5939..eb1949ac32 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingMovementBehaviour.java @@ -6,27 +6,28 @@ import org.joml.Quaternionf; import com.mojang.math.Axis; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ActorVisual; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -45,13 +46,13 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour { @Override @OnlyIn(Dist.CLIENT) public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffer) { - if (!VisualizationManager.supportsVisualization(context.world)) + ContraptionMatrices matrices, MultiBufferSource buffer) { + if (VisualizationManager.supportsVisualization(context.world)) return; Direction facing = context.state.getValue(BlockStateProperties.FACING); PartialModel top = AllPartialModels.BEARING_TOP; - SuperByteBuffer superBuffer = CachedBufferer.partial(top, context.state); + SuperByteBuffer superBuffer = CachedBuffers.partial(top, context.state); float renderPartialTicks = AnimationTickHolder.getPartialTicks(); // rotate to match blockstate @@ -80,7 +81,7 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour { @Nullable @Override public ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld, - MovementContext movementContext) { + MovementContext movementContext) { return new StabilizedBearingVisual(visualizationContext, simulationWorld, movementContext); } @@ -92,13 +93,11 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour { Direction.Axis axis = facing.getAxis(); AbstractContraptionEntity entity = context.contraption.entity; - if (entity instanceof ControlledContraptionEntity) { - ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity; + if (entity instanceof ControlledContraptionEntity controlledCE) { if (context.contraption.canBeStabilized(facing, context.localPos)) offset = -controlledCE.getAngle(renderPartialTicks); - } else if (entity instanceof OrientedContraptionEntity) { - OrientedContraptionEntity orientedCE = (OrientedContraptionEntity) entity; + } else if (entity instanceof OrientedContraptionEntity orientedCE) { if (axis.isVertical()) offset = -orientedCE.getViewYRot(renderPartialTicks); else { diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingVisual.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingVisual.java index 81e11bfc65..3f1592a145 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingVisual.java @@ -6,15 +6,16 @@ import com.mojang.math.Axis; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ActorVisual; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; import com.simibubi.create.content.kinetics.base.RotatingInstance; import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.OrientedInstance; import dev.engine_room.flywheel.lib.model.Models; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; @@ -44,14 +45,20 @@ public class StabilizedBearingVisual extends ActorVisual { int blockLight = localBlockLight(); topInstance.position(movementContext.localPos) .rotation(blockOrientation) - .light(blockLight, 0); + .light(blockLight, 0) + .setChanged(); - shaft = instancerProvider.instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT_HALF, blockState.getValue(BlockStateProperties.FACING).getOpposite())) + shaft = instancerProvider.instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT_HALF)) .createInstance(); - // not rotating so no need to set speed, axis, etc. - shaft.setPosition(movementContext.localPos) - .light(blockLight, 0); + // not rotating so no need to set speed. + var axis = KineticBlockEntityVisual.rotationAxis(blockState); + shaft.setRotationAxis(axis) + .setRotationOffset(KineticBlockEntityVisual.rotationOffset(blockState, axis, movementContext.localPos)) + .setPosition(movementContext.localPos) + .rotateToFace(Direction.SOUTH, blockState.getValue(BlockStateProperties.FACING).getOpposite()) + .light(blockLight, 0) + .setChanged(); } @Override @@ -62,7 +69,8 @@ public class StabilizedBearingVisual extends ActorVisual { rotation.mul(blockOrientation); - topInstance.rotation(rotation); + topInstance.rotation(rotation) + .setChanged(); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedContraption.java index 67c9946244..7ec9b44c7b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedContraption.java @@ -1,8 +1,9 @@ package com.simibubi.create.content.contraptions.bearing; +import com.simibubi.create.AllContraptionTypes; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AssemblyException; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.ContraptionType; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -37,7 +38,7 @@ public class StabilizedContraption extends Contraption { @Override public ContraptionType getType() { - return ContraptionType.STABILIZED; + return AllContraptionTypes.STABILIZED.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlock.java index 29416b9826..11bd891e30 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlock.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.bearing; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Couple; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; @@ -46,14 +45,9 @@ public class WindmillBearingBlock extends BearingBlock implements IBE getBlockEntityClass() { return WindmillBearingBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.WINDMILL_BEARING.get(); } - - public static Couple getSpeedRange() { - return Couple.create(1, 16); - } - } diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlockEntity.java index d78dc52512..c1f0486855 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlockEntity.java @@ -7,9 +7,10 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; @@ -52,7 +53,7 @@ public class WindmillBearingBlockEntity extends MechanicalBearingBlockEntity { if (!running) assembleNextTick = true; } - + public void disassembleForMovement() { if (!running) return; @@ -101,7 +102,7 @@ public class WindmillBearingBlockEntity extends MechanicalBearingBlockEntity { super.addBehaviours(behaviours); behaviours.remove(movementMode); movementDirection = new ScrollOptionBehaviour<>(RotationDirection.class, - Lang.translateDirect("contraptions.windmill.rotation_direction"), this, getMovementModeSlot()); + CreateLang.translateDirect("contraptions.windmill.rotation_direction"), this, getMovementModeSlot()); movementDirection.withCallback($ -> onDirectionChanged()); behaviours.add(movementDirection); registerAwardables(behaviours, AllAdvancements.WINDMILL, AllAdvancements.WINDMILL_MAXED); diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/BellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/BellMovementBehaviour.java index 7796239796..116aa4167c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/BellMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/BellMovementBehaviour.java @@ -1,6 +1,11 @@ package com.simibubi.create.content.contraptions.behaviour; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; import com.simibubi.create.content.equipment.bell.AbstractBellBlock; +import com.simibubi.create.content.redstone.deskBell.DeskBellBlock; import com.simibubi.create.content.trains.entity.CarriageContraption; import net.minecraft.core.BlockPos; @@ -11,15 +16,31 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.phys.Vec3; public class BellMovementBehaviour implements MovementBehaviour { + @Override public boolean isActive(MovementContext context) { return MovementBehaviour.super.isActive(context) && !(context.contraption instanceof CarriageContraption); } @Override - public void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) { - double dotProduct = oldMotion.dot(motion); + public void tick(MovementContext context) { + boolean moved = context.temporaryData instanceof Boolean b && b.booleanValue(); + Contraption contraption = context.contraption; + if (contraption instanceof ElevatorContraption ec && !ec.arrived) + context.temporaryData = Boolean.valueOf(true); + else if (moved) { + playSound(context); + context.temporaryData = null; + } + } + + @Override + public void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) { + if (context.contraption instanceof ElevatorContraption) + return; + + double dotProduct = oldMotion.dot(motion); if (dotProduct <= 0 && (context.relativeMotion.length() != 0) || context.firstMovement) playSound(context); } @@ -35,12 +56,14 @@ public class BellMovementBehaviour implements MovementBehaviour { BlockPos pos = BlockPos.containing(context.position); Block block = context.state.getBlock(); - if (block instanceof AbstractBellBlock) { + if (AllBlocks.DESK_BELL.has(context.state)) { + ((DeskBellBlock) block).playSound(null, world, pos); + } else if (block instanceof AbstractBellBlock) { ((AbstractBellBlock) block).playSound(world, pos); } else { // Vanilla bell sound - world.playSound(null, pos, SoundEvents.BELL_BLOCK, - SoundSource.BLOCKS, 2f, 1f); + world.playSound(null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2f, 1f); } } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/CampfireMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/CampfireMovementBehaviour.java index 05315b3138..fb86887260 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/CampfireMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/CampfireMovementBehaviour.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.behaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; + import net.minecraft.core.particles.ParticleTypes; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.CampfireBlock; diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/DoorMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/DoorMovingInteraction.java index c4132ba4ba..b7762b9100 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/DoorMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/DoorMovingInteraction.java @@ -29,13 +29,13 @@ public class DoorMovingInteraction extends SimpleBlockMovingInteraction { BlockPos otherPos = currentState.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? pos.above() : pos.below(); StructureBlockInfo info = contraption.getBlocks() .get(otherPos); - if (info.state().hasProperty(DoorBlock.OPEN)) { + if (info != null && info.state().hasProperty(DoorBlock.OPEN)) { BlockState newState = info.state().cycle(DoorBlock.OPEN); setContraptionBlockData(contraption.entity, otherPos, new StructureBlockInfo(info.pos(), newState, info.nbt())); } currentState = currentState.cycle(DoorBlock.OPEN); - + if (player != null) { if (trainDoor) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java index 82fdb13c75..d25d20103a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java @@ -1,11 +1,17 @@ package com.simibubi.create.content.contraptions.behaviour; +import java.util.function.Supplier; import java.util.function.UnaryOperator; +import org.jetbrains.annotations.Nullable; + +import com.google.common.base.Suppliers; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.logistics.filter.FilterItemStack; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -32,9 +38,12 @@ public class MovementContext { public CompoundTag data; public Contraption contraption; public Object temporaryData; - + private FilterItemStack filter; + private final Supplier itemStorage; + private final Supplier fluidStorage; + public MovementContext(Level world, StructureBlockInfo info, Contraption contraption) { this.world = world; this.state = info.state(); @@ -51,6 +60,8 @@ public class MovementContext { data = new CompoundTag(); stall = false; filter = null; + this.itemStorage = Suppliers.memoize(() -> contraption.getStorage().getAllItemStorages().get(this.localPos)); + this.fluidStorage = Suppliers.memoize(() -> contraption.getStorage().getFluids().storages.get(this.localPos)); } public float getAnimationSpeed() { @@ -87,11 +98,20 @@ public class MovementContext { nbt.put("Data", data.copy()); return nbt; } - + public FilterItemStack getFilterFromBE() { if (filter != null) return filter; return filter = FilterItemStack.of(blockEntityData.getCompound("Filter")); } -} \ No newline at end of file + @Nullable + public MountedItemStorage getItemStorage() { + return this.itemStorage.get(); + } + + @Nullable + public MountedFluidStorage getFluidStorage() { + return this.fluidStorage.get(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovingInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovingInteractionBehaviour.java deleted file mode 100644 index 1d0cd6ddbd..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovingInteractionBehaviour.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour; - -import org.apache.commons.lang3.tuple.MutablePair; - -import com.simibubi.create.content.contraptions.AbstractContraptionEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; - -public abstract class MovingInteractionBehaviour { - - protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, - StructureBlockInfo info, MovementContext ctx) { - contraptionEntity.getContraption().getActors().remove(index); - contraptionEntity.getContraption().getActors().add(index, MutablePair.of(info, ctx)); - if (contraptionEntity.level().isClientSide) - contraptionEntity.getContraption().deferInvalidate = true; - } - - protected void setContraptionBlockData(AbstractContraptionEntity contraptionEntity, BlockPos pos, - StructureBlockInfo info) { - if (contraptionEntity.level().isClientSide()) - return; - contraptionEntity.setBlock(pos, info); - } - - public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, - AbstractContraptionEntity contraptionEntity) { - return true; - } - - public void handleEntityCollision(Entity entity, BlockPos localPos, AbstractContraptionEntity contraptionEntity) {} - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/SimpleBlockMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/SimpleBlockMovingInteraction.java index d3a579e1d8..06c66f9d21 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/SimpleBlockMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/SimpleBlockMovingInteraction.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.behaviour; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.Contraption; diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java deleted file mode 100644 index c9134e0b3f..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -public class DispenseItemLocation { - private final boolean internal; - private final int slot; - - public static final DispenseItemLocation NONE = new DispenseItemLocation(false, -1); - - public DispenseItemLocation(boolean internal, int slot) { - this.internal = internal; - this.slot = slot; - } - - public boolean isInternal() { - return internal; - } - - public int getSlot() { - return slot; - } - - public boolean isEmpty() { - return slot < 0; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java index 1018e98875..86468d4cd5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java @@ -1,89 +1,16 @@ package com.simibubi.create.content.contraptions.behaviour.dispenser; -import java.util.HashMap; - +import com.simibubi.create.api.contraption.dispenser.DefaultMountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedDispenseBehavior; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.foundation.mixin.accessor.DispenserBlockAccessor; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; -import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; -import net.minecraft.core.dispenser.DispenseItemBehavior; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.DispenserBlock; -import net.minecraft.world.phys.Vec3; public class DispenserMovementBehaviour extends DropperMovementBehaviour { - private static final HashMap MOVED_DISPENSE_ITEM_BEHAVIOURS = new HashMap<>(); - private static final HashMap MOVED_PROJECTILE_DISPENSE_BEHAVIOURS = new HashMap<>(); - private static boolean spawnEggsRegistered = false; - - public static void gatherMovedDispenseItemBehaviours() { - IMovedDispenseItemBehaviour.init(); - } - - public static void registerMovedDispenseItemBehaviour(Item item, - IMovedDispenseItemBehaviour movedDispenseItemBehaviour) { - MOVED_DISPENSE_ITEM_BEHAVIOURS.put(item, movedDispenseItemBehaviour); - } - - public static DispenseItemBehavior getDispenseMethod(ItemStack itemstack) { - return ((DispenserBlockAccessor) Blocks.DISPENSER).create$callGetDispenseMethod(itemstack); - } - @Override - protected void activate(MovementContext context, BlockPos pos) { - if (!spawnEggsRegistered) { - spawnEggsRegistered = true; - IMovedDispenseItemBehaviour.initSpawnEggs(); - } - - DispenseItemLocation location = getDispenseLocation(context); - if (location.isEmpty()) { - context.world.levelEvent(1001, pos, 0); - } else { - ItemStack itemStack = getItemStackAt(location, context); - // Special dispense item behaviour for moving contraptions - if (MOVED_DISPENSE_ITEM_BEHAVIOURS.containsKey(itemStack.getItem())) { - setItemStackAt(location, MOVED_DISPENSE_ITEM_BEHAVIOURS.get(itemStack.getItem()).dispense(itemStack, context, pos), context); - return; - } - - ItemStack backup = itemStack.copy(); - // If none is there, try vanilla registry - try { - if (MOVED_PROJECTILE_DISPENSE_BEHAVIOURS.containsKey(itemStack.getItem())) { - setItemStackAt(location, MOVED_PROJECTILE_DISPENSE_BEHAVIOURS.get(itemStack.getItem()).dispense(itemStack, context, pos), context); - return; - } - - DispenseItemBehavior behavior = getDispenseMethod(itemStack); - if (behavior instanceof AbstractProjectileDispenseBehavior) { // Projectile behaviours can be converted most of the time - IMovedDispenseItemBehaviour movedBehaviour = MovedProjectileDispenserBehaviour.of((AbstractProjectileDispenseBehavior) behavior); - setItemStackAt(location, movedBehaviour.dispense(itemStack, context, pos), context); - MOVED_PROJECTILE_DISPENSE_BEHAVIOURS.put(itemStack.getItem(), movedBehaviour); // buffer conversion if successful - return; - } - - Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING).getNormal()); - facingVec = context.rotation.apply(facingVec); - facingVec.normalize(); - Direction clostestFacing = Direction.getNearest(facingVec.x, facingVec.y, facingVec.z); - ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing); - - if (behavior.getClass() != DefaultDispenseItemBehavior.class) { // There is a dispense item behaviour registered for the vanilla dispenser - setItemStackAt(location, behavior.dispense(blockSource, itemStack), context); - return; - } - } catch (NullPointerException ignored) { - itemStack = backup; // Something went wrong with the BE being null in ContraptionBlockSource, reset the stack - } - - setItemStackAt(location, DEFAULT_BEHAVIOUR.dispense(itemStack, context, pos), context); // the default: launch the item - } + protected MountedDispenseBehavior getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { + MountedDispenseBehavior behavior = MountedDispenseBehavior.REGISTRY.get(stack.getItem()); + return behavior != null ? behavior : DefaultMountedDispenseBehavior.INSTANCE; } - } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java index 65f73bbe26..312faf1388 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java @@ -1,132 +1,91 @@ package com.simibubi.create.content.contraptions.behaviour.dispenser; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; +import java.util.function.Predicate; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; +import com.simibubi.create.api.contraption.dispenser.DefaultMountedDispenseBehavior; +import com.simibubi.create.api.contraption.dispenser.MountedDispenseBehavior; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.item.ItemHelper; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.Util; import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; -import net.minecraft.world.ContainerHelper; +import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.LevelEvent; + +import net.minecraftforge.items.IItemHandler; public class DropperMovementBehaviour implements MovementBehaviour { - protected static final MovedDefaultDispenseItemBehaviour DEFAULT_BEHAVIOUR = - new MovedDefaultDispenseItemBehaviour(); - private static final Random RNG = new Random(); - - protected void activate(MovementContext context, BlockPos pos) { - DispenseItemLocation location = getDispenseLocation(context); - if (location.isEmpty()) { - context.world.levelEvent(1001, pos, 0); - } else { - setItemStackAt(location, DEFAULT_BEHAVIOUR.dispense(getItemStackAt(location, context), context, pos), - context); - } - } - @Override public void visitNewPosition(MovementContext context, BlockPos pos) { if (context.world.isClientSide) return; - collectItems(context); - activate(context, pos); - } - private void collectItems(MovementContext context) { - getStacks(context).stream() - .filter(itemStack -> !itemStack.isEmpty() && itemStack.getItem() != Items.AIR - && itemStack.getMaxStackSize() > itemStack.getCount()) - .forEach(itemStack -> itemStack.grow(ItemHelper - .extract(context.contraption.getSharedInventory(), (otherItemStack) -> ItemStack.isSameItemSameTags(itemStack, otherItemStack), - ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false) - .getCount())); - } - - private void updateTemporaryData(MovementContext context) { - if (!(context.temporaryData instanceof NonNullList) && context.world != null) { - NonNullList stacks = NonNullList.withSize(getInvSize(), ItemStack.EMPTY); - ContainerHelper.loadAllItems(context.blockEntityData, stacks); - context.temporaryData = stacks; - } - } - - @SuppressWarnings("unchecked") - private NonNullList getStacks(MovementContext context) { - updateTemporaryData(context); - return (NonNullList) context.temporaryData; - } - - private ArrayList getUseableLocations(MovementContext context) { - ArrayList useable = new ArrayList<>(); - for (int slot = 0; slot < getInvSize(); slot++) { - DispenseItemLocation location = new DispenseItemLocation(true, slot); - ItemStack testStack = getItemStackAt(location, context); - if (testStack == null || testStack.isEmpty()) - continue; - if (testStack.getMaxStackSize() == 1) { - location = new DispenseItemLocation(false, ItemHelper.findFirstMatchingSlotIndex( - context.contraption.getSharedInventory(), ItemHelper.sameItemPredicate(testStack))); - if (!getItemStackAt(location, context).isEmpty()) - useable.add(location); - } else if (testStack.getCount() >= 2) - useable.add(location); - } - return useable; - } - - @Override - public void writeExtraData(MovementContext context) { - NonNullList stacks = getStacks(context); - if (stacks == null) + MountedItemStorage storage = context.getItemStorage(); + if (storage == null) return; - ContainerHelper.saveAllItems(context.blockEntityData, stacks); + + int slot = getSlot(storage, context.world.random, context.contraption.getStorage().getAllItems()); + if (slot == -1) { + // all slots empty + failDispense(context, pos); + return; + } + + // copy because dispense behaviors will modify it directly + ItemStack stack = storage.getStackInSlot(slot).copy(); + MountedDispenseBehavior behavior = getDispenseBehavior(context, pos, stack); + ItemStack remainder = behavior.dispense(stack, context, pos); + storage.setStackInSlot(slot, remainder); } - @Override - public void stopMoving(MovementContext context) { - MovementBehaviour.super.stopMoving(context); - writeExtraData(context); + protected MountedDispenseBehavior getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { + return DefaultMountedDispenseBehavior.INSTANCE; } - protected DispenseItemLocation getDispenseLocation(MovementContext context) { - int i = -1; - int j = 1; - List useableLocations = getUseableLocations(context); - for (int k = 0; k < useableLocations.size(); ++k) { - if (RNG.nextInt(j++) == 0) { - i = k; + /** + * Finds a dispensable slot. Empty slots are skipped and nearly-empty slots are topped off. + */ + private static int getSlot(MountedItemStorage storage, RandomSource random, IItemHandler contraptionInventory) { + IntList filledSlots = new IntArrayList(); + for (int i = 0; i < storage.getSlots(); i++) { + ItemStack stack = storage.getStackInSlot(i); + if (stack.isEmpty()) + continue; + + if (stack.getCount() == 1 && stack.getMaxStackSize() != 1) { + stack = tryTopOff(stack, contraptionInventory); + if (stack != null) { + storage.setStackInSlot(i, stack); + } } + + filledSlots.add(i); } - if (i < 0) - return DispenseItemLocation.NONE; - else - return useableLocations.get(i); + + return switch (filledSlots.size()) { + case 0 -> -1; + case 1 -> filledSlots.getInt(0); + default -> Util.getRandom(filledSlots, random); + }; } - protected ItemStack getItemStackAt(DispenseItemLocation location, MovementContext context) { - if (location.isInternal()) { - return getStacks(context).get(location.getSlot()); - } else { - return context.contraption.getSharedInventory() - .getStackInSlot(location.getSlot()); - } + @Nullable + private static ItemStack tryTopOff(ItemStack stack, IItemHandler from) { + Predicate test = otherStack -> ItemStack.isSameItemSameTags(stack, otherStack); + int needed = stack.getMaxStackSize() - stack.getCount(); + + ItemStack extracted = ItemHelper.extract(from, test, ItemHelper.ExtractionCountMode.UPTO, needed, false); + return extracted.isEmpty() ? null : stack.copyWithCount(stack.getCount() + extracted.getCount()); } - protected void setItemStackAt(DispenseItemLocation location, ItemStack stack, MovementContext context) { - if (location.isInternal()) { - getStacks(context).set(location.getSlot(), stack); - } else { - context.contraption.getSharedInventory() - .setStackInSlot(location.getSlot(), stack); - } - } - - private static int getInvSize() { - return 9; + private static void failDispense(MovementContext ctx, BlockPos pos) { + ctx.world.levelEvent(LevelEvent.SOUND_DISPENSER_FAIL, pos, 0); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java deleted file mode 100644 index f1deec3e8c..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import com.simibubi.create.content.contraptions.behaviour.MovementContext; - -import net.minecraft.Util; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.BlockTags; -import net.minecraft.tags.FluidTags; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.item.PrimedTnt; -import net.minecraft.world.entity.projectile.FireworkRocketEntity; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.entity.projectile.SmallFireball; -import net.minecraft.world.entity.projectile.ThrownPotion; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.SpawnEggItem; -import net.minecraft.world.item.alchemy.PotionUtils; -import net.minecraft.world.item.alchemy.Potions; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.BeehiveBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.BucketPickup; -import net.minecraft.world.level.block.entity.BeehiveBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public interface IMovedDispenseItemBehaviour { - - static void initSpawnEggs() { - final IMovedDispenseItemBehaviour spawnEggDispenseBehaviour = new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3 facing) { - if (!(itemStack.getItem() instanceof SpawnEggItem)) - return super.dispenseStack(itemStack, context, pos, facing); - if (context.world instanceof ServerLevel) { - EntityType entityType = ((SpawnEggItem) itemStack.getItem()).getType(itemStack.getTag()); - Entity spawnedEntity = entityType.spawn((ServerLevel) context.world, itemStack, null, - pos.offset(BlockPos.containing(facing.x + .7, facing.y + .7, facing.z + .7)), MobSpawnType.DISPENSER, facing.y < .5, - false); - if (spawnedEntity != null) - spawnedEntity.setDeltaMovement(context.motion.scale(2)); - } - itemStack.shrink(1); - return itemStack; - } - }; - - for (SpawnEggItem spawneggitem : SpawnEggItem.eggs()) - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(spawneggitem, spawnEggDispenseBehaviour); - } - - static void init() { - MovedProjectileDispenserBehaviour movedPotionDispenseItemBehaviour = new MovedProjectileDispenserBehaviour() { - @Override - protected Projectile getProjectileEntity(Level world, double x, double y, double z, ItemStack itemStack) { - return Util.make(new ThrownPotion(world, x, y, z), (p_218411_1_) -> p_218411_1_.setItem(itemStack)); - } - - protected float getProjectileInaccuracy() { - return super.getProjectileInaccuracy() * 0.5F; - } - - protected float getProjectileVelocity() { - return super.getProjectileVelocity() * .5F; - } - }; - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.SPLASH_POTION, - movedPotionDispenseItemBehaviour); - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.LINGERING_POTION, - movedPotionDispenseItemBehaviour); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.TNT, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - PrimedTnt tntentity = new PrimedTnt(context.world, x, y, z, null); - tntentity.push(context.motion.x, context.motion.y, context.motion.z); - context.world.addFreshEntity(tntentity); - context.world.playSound(null, tntentity.getX(), tntentity.getY(), tntentity.getZ(), - SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); - itemStack.shrink(1); - return itemStack; - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.FIREWORK_ROCKET, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - FireworkRocketEntity fireworkrocketentity = - new FireworkRocketEntity(context.world, itemStack, x, y, z, true); - fireworkrocketentity.shoot(facing.x, facing.y, facing.z, 0.5F, 1.0F); - context.world.addFreshEntity(fireworkrocketentity); - itemStack.shrink(1); - return itemStack; - } - - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1004, pos, 0); - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.FIRE_CHARGE, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1018, pos, 0); - } - - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - RandomSource random = context.world.random; - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - context.world.addFreshEntity(Util.make( - new SmallFireball(context.world, x, y, z, - random.nextGaussian() * 0.05D + facing.x + context.motion.x, - random.nextGaussian() * 0.05D + facing.y + context.motion.y, - random.nextGaussian() * 0.05D + facing.z + context.motion.z), - (p_229425_1_) -> p_229425_1_.setItem(itemStack))); - itemStack.shrink(1); - return itemStack; - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.GLASS_BOTTLE, - new MovedOptionalDispenseBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - this.successful = false; - BlockPos interactAt = pos.relative(getClosestFacingDirection(facing)); - BlockState state = context.world.getBlockState(interactAt); - Block block = state.getBlock(); - - if (state.is(BlockTags.BEEHIVES) && state.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { - ((BeehiveBlock) block).releaseBeesAndResetHoneyLevel(context.world, state, interactAt, null, - BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); - this.successful = true; - return placeItemInInventory(itemStack, new ItemStack(Items.HONEY_BOTTLE), context, pos, facing); - } else if (context.world.getFluidState(interactAt) - .is(FluidTags.WATER)) { - this.successful = true; - return placeItemInInventory(itemStack, - PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER), context, pos, facing); - } else { - return super.dispenseStack(itemStack, context, pos, facing); - } - } - }); - - DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.BUCKET, - new MovedDefaultDispenseItemBehaviour() { - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, - Vec3 facing) { - BlockPos interactAt = pos.relative(getClosestFacingDirection(facing)); - BlockState state = context.world.getBlockState(interactAt); - Block block = state.getBlock(); - if (block instanceof BucketPickup) { - ItemStack bucket = ((BucketPickup) block).pickupBlock(context.world, interactAt, state); - return placeItemInInventory(itemStack, bucket, context, pos, facing); - } - return super.dispenseStack(itemStack, context, pos, facing); - } - }); - } - - ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos); -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java deleted file mode 100644 index 1ad03f1bcf..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import com.simibubi.create.content.contraptions.behaviour.MovementContext; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Container; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.DispenserBlock; -import net.minecraft.world.level.block.entity.HopperBlockEntity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.items.ItemHandlerHelper; - -public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBehaviour { - private static final MovedDefaultDispenseItemBehaviour DEFAULT_INSTANCE = new MovedDefaultDispenseItemBehaviour(); - - public static void doDispense(Level p_82486_0_, ItemStack p_82486_1_, int p_82486_2_, Vec3 facing, - BlockPos p_82486_4_, MovementContext context) { - double d0 = p_82486_4_.getX() + facing.x + .5; - double d1 = p_82486_4_.getY() + facing.y + .5; - double d2 = p_82486_4_.getZ() + facing.z + .5; - if (Direction.getNearest(facing.x, facing.y, facing.z) - .getAxis() == Direction.Axis.Y) { - d1 = d1 - 0.125D; - } else { - d1 = d1 - 0.15625D; - } - - ItemEntity itementity = new ItemEntity(p_82486_0_, d0, d1, d2, p_82486_1_); - double d3 = p_82486_0_.random.nextDouble() * 0.1D + 0.2D; - itementity.setDeltaMovement( - p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.x() * d3 - + context.motion.x, - p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.y() * d3 - + context.motion.y, - p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.z() * d3 - + context.motion.z); - p_82486_0_.addFreshEntity(itementity); - } - - @Override - public ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos) { - Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING) - .getNormal()); - facingVec = context.rotation.apply(facingVec); - facingVec.normalize(); - - Direction closestToFacing = getClosestFacingDirection(facingVec); - Container inventory = HopperBlockEntity.getContainerAt(context.world, pos.relative(closestToFacing)); - if (inventory == null) { - this.playDispenseSound(context.world, pos); - this.spawnDispenseParticles(context.world, pos, closestToFacing); - return this.dispenseStack(itemStack, context, pos, facingVec); - } else { - if (HopperBlockEntity.addItem(null, inventory, itemStack.copy() - .split(1), closestToFacing.getOpposite()) - .isEmpty()) - itemStack.shrink(1); - return itemStack; - } - } - - /** - * Dispense the specified stack, play the dispense sound and spawn particles. - */ - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3 facing) { - ItemStack itemstack = itemStack.split(1); - doDispense(context.world, itemstack, 6, facing, pos, context); - return itemStack; - } - - /** - * Play the dispense sound from the specified block. - */ - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1000, pos, 0); - } - - /** - * Order clients to display dispense particles from the specified block and - * facing. - */ - protected void spawnDispenseParticles(LevelAccessor world, BlockPos pos, Vec3 facing) { - spawnDispenseParticles(world, pos, getClosestFacingDirection(facing)); - } - - protected void spawnDispenseParticles(LevelAccessor world, BlockPos pos, Direction direction) { - world.levelEvent(2000, pos, direction.get3DDataValue()); - } - - protected Direction getClosestFacingDirection(Vec3 exactFacing) { - return Direction.getNearest(exactFacing.x, exactFacing.y, exactFacing.z); - } - - protected ItemStack placeItemInInventory(ItemStack consumedFrom, ItemStack output, MovementContext context, - BlockPos pos, Vec3 facing) { - consumedFrom.shrink(1); - ItemStack remainder = - ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), output.copy(), false); - if (!remainder.isEmpty()) - DEFAULT_INSTANCE.dispenseStack(output, context, pos, facing); - return consumedFrom; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java deleted file mode 100644 index 3e9e77ed13..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelAccessor; - -public class MovedOptionalDispenseBehaviour extends MovedDefaultDispenseItemBehaviour { - protected boolean successful = true; - - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(this.successful ? 1000 : 1001, pos, 0); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java deleted file mode 100644 index 2d99d36172..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import javax.annotation.Nullable; - -import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.foundation.mixin.accessor.AbstractProjectileDispenseBehaviorAccessor; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.phys.Vec3; - -public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDispenseItemBehaviour { - - @Override - protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3 facing) { - double x = pos.getX() + facing.x * .7 + .5; - double y = pos.getY() + facing.y * .7 + .5; - double z = pos.getZ() + facing.z * .7 + .5; - Projectile projectile = this.getProjectileEntity(context.world, x, y, z, itemStack.copy()); - if (projectile == null) - return itemStack; - Vec3 effectiveMovementVec = facing.scale(getProjectileVelocity()).add(context.motion); - projectile.shoot(effectiveMovementVec.x, effectiveMovementVec.y, effectiveMovementVec.z, (float) effectiveMovementVec.length(), this.getProjectileInaccuracy()); - context.world.addFreshEntity(projectile); - itemStack.shrink(1); - return itemStack; - } - - @Override - protected void playDispenseSound(LevelAccessor world, BlockPos pos) { - world.levelEvent(1002, pos, 0); - } - - @Nullable - protected abstract Projectile getProjectileEntity(Level world, double x, double y, double z, ItemStack itemStack); - - protected float getProjectileInaccuracy() { - return 6.0F; - } - - protected float getProjectileVelocity() { - return 1.1F; - } - - public static MovedProjectileDispenserBehaviour of(AbstractProjectileDispenseBehavior vanillaBehaviour) { - AbstractProjectileDispenseBehaviorAccessor accessor = (AbstractProjectileDispenseBehaviorAccessor) vanillaBehaviour; - return new MovedProjectileDispenserBehaviour() { - @Override - protected Projectile getProjectileEntity(Level world, double x, double y, double z, ItemStack itemStack) { - return accessor.create$callGetProjectile(world, new SimplePos(x, y, z), itemStack); - } - - @Override - protected float getProjectileInaccuracy() { - return accessor.create$callGetUncertainty(); - } - - @Override - protected float getProjectileVelocity() { - return accessor.create$callGetPower(); - } - }; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java deleted file mode 100644 index 9b8c22acca..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.content.contraptions.behaviour.dispenser; - -import net.minecraft.core.Position; - -public class SimplePos implements Position { - private final double x; - private final double y; - private final double z; - - public SimplePos(double x, double y, double z) { - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public double x() { - return x; - } - - @Override - public double y() { - return y; - } - - @Override - public double z() { - return z; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java new file mode 100644 index 0000000000..e085b22c47 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.contraptions.behaviour.dispenser.storage; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.menu.MountedStorageMenus; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; + +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +public class DispenserMountedStorage extends SimpleMountedStorage { + public static final Codec CODEC = SimpleMountedStorage.codec(DispenserMountedStorage::new); + + protected DispenserMountedStorage(MountedItemStorageType type, IItemHandler handler) { + super(type, handler); + } + + public DispenserMountedStorage(IItemHandler handler) { + this(AllMountedStorageTypes.DISPENSER.get(), handler); + } + + @Override + @Nullable + protected MenuProvider createMenuProvider(Component name, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + return MountedStorageMenus.createGeneric9x9(name, handler, stillValid, onClose); + } + + @Override + protected void playOpeningSound(ServerLevel level, Vec3 pos) { + // dispensers are silent + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorageType.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorageType.java new file mode 100644 index 0000000000..a5ff233a7a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorageType.java @@ -0,0 +1,17 @@ +package com.simibubi.create.content.contraptions.behaviour.dispenser.storage; + +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorageType; + +import net.minecraftforge.items.IItemHandler; + +public class DispenserMountedStorageType extends SimpleMountedStorageType { + public DispenserMountedStorageType() { + super(DispenserMountedStorage.CODEC); + } + + @Override + protected SimpleMountedStorage createStorage(IItemHandler handler) { + return new DispenserMountedStorage(handler); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/AbstractChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/AbstractChassisBlock.java index 9ef6232542..98233bebec 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/chassis/AbstractChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/AbstractChassisBlock.java @@ -3,12 +3,12 @@ package com.simibubi.create.content.contraptions.chassis; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; @@ -26,9 +26,10 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.Tags; -public abstract class AbstractChassisBlock extends RotatedPillarBlock implements IWrenchable, IBE, ITransformableBlock { +public abstract class AbstractChassisBlock extends RotatedPillarBlock implements IWrenchable, IBE, TransformableBlock { public AbstractChassisBlock(Properties properties) { super(properties); diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisBlockEntity.java index 702f9148a1..94d102a280 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisBlockEntity.java @@ -12,7 +12,7 @@ import java.util.function.Function; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllKeys; -import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.api.contraption.BlockMovementChecks; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; @@ -21,10 +21,10 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.BulkScrollValueBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -37,6 +37,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.BlockHitResult; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -54,7 +55,7 @@ public class ChassisBlockEntity extends SmartBlockEntity { @Override public void addBehaviours(List behaviours) { int max = AllConfigs.server().kinetics.maxChassisRange.get(); - range = new ChassisScrollValueBehaviour(Lang.translateDirect("contraptions.chassis.range"), this, + range = new ChassisScrollValueBehaviour(CreateLang.translateDirect("contraptions.chassis.range"), this, new CenteredSideValueBoxTransform(), be -> ((ChassisBlockEntity) be).collectChassisGroup()); range.requiresWrench(); range.between(1, max); @@ -70,7 +71,7 @@ public class ChassisBlockEntity extends SmartBlockEntity { public void initialize() { super.initialize(); if (getBlockState().getBlock() instanceof RadialChassisBlock) - range.setLabel(Lang.translateDirect("contraptions.chassis.radius")); + range.setLabel(CreateLang.translateDirect("contraptions.chassis.radius")); } @Override @@ -107,8 +108,7 @@ public class ChassisBlockEntity extends SmartBlockEntity { continue; visited.add(current); BlockEntity blockEntity = level.getBlockEntity(current); - if (blockEntity instanceof ChassisBlockEntity) { - ChassisBlockEntity chassis = (ChassisBlockEntity) blockEntity; + if (blockEntity instanceof ChassisBlockEntity chassis) { collected.add(chassis); visited.add(current); chassis.addAttachedChasses(frontier, visited); @@ -125,7 +125,7 @@ public class ChassisBlockEntity extends SmartBlockEntity { if (isRadial()) { // Collect chain of radial chassis - for (int offset : new int[] { -1, 1 }) { + for (int offset : new int[]{-1, 1}) { Direction direction = Direction.get(AxisDirection.POSITIVE, axis); BlockPos currentPos = worldPosition.relative(direction, offset); if (!level.isLoaded(currentPos)) @@ -173,7 +173,7 @@ public class ChassisBlockEntity extends SmartBlockEntity { Direction facing = Direction.get(AxisDirection.POSITIVE, axis); int chassisRange = visualize ? currentlySelectedRange : getRange(); - for (int offset : new int[] { 1, -1 }) { + for (int offset : new int[]{1, -1}) { if (offset == -1) facing = facing.getOpposite(); boolean sticky = state.getValue(block.getGlueableSide(state, facing)); @@ -254,13 +254,13 @@ public class ChassisBlockEntity extends SmartBlockEntity { class ChassisScrollValueBehaviour extends BulkScrollValueBehaviour { public ChassisScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot, - Function> groupGetter) { + Function> groupGetter) { super(label, be, slot, groupGetter); } @Override public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { - ImmutableList rows = ImmutableList.of(Lang.translateDirect("contraptions.chassis.distance")); + ImmutableList rows = ImmutableList.of(CreateLang.translateDirect("contraptions.chassis.distance")); ValueSettingsFormatter formatter = new ValueSettingsFormatter(vs -> new ValueSettings(vs.row(), vs.value() + 1).format()); return new ValueSettingsBoard(label, max - 1, 1, rows, formatter); @@ -290,7 +290,7 @@ public class ChassisBlockEntity extends SmartBlockEntity { ValueSettings vs = super.getValueSettings(); return new ValueSettings(vs.row(), vs.value() - 1); } - + @Override public String getClipboardKey() { return "Chassis"; diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisRangeDisplay.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisRangeDisplay.java index b55a138aa4..d76edfcb61 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisRangeDisplay.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisRangeDisplay.java @@ -13,8 +13,8 @@ import com.mojang.datafixers.util.Pair; import com.simibubi.create.AllItems; import com.simibubi.create.AllKeys; import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.CreateClient; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.player.Player; @@ -35,7 +35,7 @@ public class ChassisRangeDisplay { public Entry(ChassisBlockEntity be) { this.be = be; timer = DISPLAY_TIME; - CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(be)) + Outliner.getInstance().showCluster(getOutlineKey(), createSelection(be)) .colored(0xFFFFFF) .disableLineNormals() .lineWidth(1 / 16f) @@ -92,40 +92,38 @@ public class ChassisRangeDisplay { boolean hasWrench = AllItems.WRENCH.isIn(player.getMainHandItem()); for (Iterator iterator = entries.keySet() - .iterator(); iterator.hasNext();) { + .iterator(); iterator.hasNext(); ) { BlockPos pos = iterator.next(); Entry entry = entries.get(pos); if (tickEntry(entry, hasWrench)) iterator.remove(); - CreateClient.OUTLINER.keep(entry.getOutlineKey()); + Outliner.getInstance().keep(entry.getOutlineKey()); } - for (Iterator iterator = groupEntries.iterator(); iterator.hasNext();) { + for (Iterator iterator = groupEntries.iterator(); iterator.hasNext(); ) { GroupEntry group = iterator.next(); if (tickEntry(group, hasWrench)) { iterator.remove(); if (group == lastHoveredGroup) lastHoveredGroup = null; } - CreateClient.OUTLINER.keep(group.getOutlineKey()); + Outliner.getInstance().keep(group.getOutlineKey()); } if (!hasWrench) return; HitResult over = Minecraft.getInstance().hitResult; - if (!(over instanceof BlockHitResult)) + if (!(over instanceof BlockHitResult ray)) return; - BlockHitResult ray = (BlockHitResult) over; BlockPos pos = ray.getBlockPos(); BlockEntity blockEntity = world.getBlockEntity(pos); if (blockEntity == null || blockEntity.isRemoved()) return; - if (!(blockEntity instanceof ChassisBlockEntity)) + if (!(blockEntity instanceof ChassisBlockEntity chassisBlockEntity)) return; boolean ctrl = AllKeys.ctrlDown(); - ChassisBlockEntity chassisBlockEntity = (ChassisBlockEntity) blockEntity; if (ctrl) { GroupEntry existingGroupForPos = getExistingGroupForPos(pos); @@ -173,9 +171,9 @@ public class ChassisRangeDisplay { GroupEntry hoveredGroup = new GroupEntry(chassis); for (ChassisBlockEntity included : hoveredGroup.includedBEs) - CreateClient.OUTLINER.remove(Pair.of(included.getBlockPos(), 1)); + Outliner.getInstance().remove(Pair.of(included.getBlockPos(), 1)); - groupEntries.forEach(entry -> CreateClient.OUTLINER.remove(entry.getOutlineKey())); + groupEntries.forEach(entry -> Outliner.getInstance().remove(entry.getOutlineKey())); groupEntries.clear(); entries.clear(); groupEntries.add(hoveredGroup); @@ -186,7 +184,7 @@ public class ChassisRangeDisplay { BlockPos pos = chassis.getBlockPos(); GroupEntry entry = getExistingGroupForPos(pos); if (entry != null) - CreateClient.OUTLINER.remove(entry.getOutlineKey()); + Outliner.getInstance().remove(entry.getOutlineKey()); groupEntries.clear(); entries.clear(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlock.java index 8b0d0e9cba..a0dbb1fd1d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlock.java @@ -4,7 +4,6 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; - import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.BlockParticleOption; diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlockEntity.java index 131113c78f..53ca8c9396 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlockEntity.java @@ -8,16 +8,17 @@ import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.glue.SuperGlueItem; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerRenderer.java index 8245657d41..724446f39c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerRenderer.java @@ -3,12 +3,12 @@ package com.simibubi.create.content.contraptions.chassis; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -28,7 +28,7 @@ public class StickerRenderer extends SafeBlockEntityRenderer if (VisualizationManager.supportsVisualization(be.getLevel())) return; BlockState state = be.getBlockState(); - SuperByteBuffer head = CachedBufferer.partial(AllPartialModels.STICKER_HEAD, state); + SuperByteBuffer head = CachedBuffers.partial(AllPartialModels.STICKER_HEAD, state); float offset = be.piston.getValue(AnimationTickHolder.getPartialTicks(be.getLevel())); if (be.getLevel() != Minecraft.getInstance().level && !be.isVirtual()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerVisual.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerVisual.java index e9c84956cb..21899a34c1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerVisual.java @@ -3,7 +3,6 @@ package com.simibubi.create.content.contraptions.chassis; import java.util.function.Consumer; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.visual.DynamicVisual; @@ -13,6 +12,7 @@ import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.Direction; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/contraptions/data/ContraptionPickupLimiting.java b/src/main/java/com/simibubi/create/content/contraptions/data/ContraptionPickupLimiting.java new file mode 100644 index 0000000000..a862e443d4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/data/ContraptionPickupLimiting.java @@ -0,0 +1,55 @@ +package com.simibubi.create.content.contraptions.data; + +import com.simibubi.create.compat.Mods; +import com.simibubi.create.foundation.mixin.accessor.NbtAccounterAccessor; + +import io.netty.buffer.Unpooled; +import net.minecraft.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtAccounter; +import net.minecraft.network.FriendlyByteBuf; + +public class ContraptionPickupLimiting { + /// The default NBT limit, defined by {@link FriendlyByteBuf#readNbt()}. + public static final int NBT_LIMIT = 2_097_152; + + // increased nbt limits provided by other mods. + public static final int PACKET_FIXER_LIMIT = NBT_LIMIT * 100; + public static final int XL_PACKETS_LIMIT = Integer.MAX_VALUE; + + // leave some space for the rest of the packet. + public static final int BUFFER = 20_000; + + // the actual limit to be used + public static final int LIMIT = Util.make(() -> { + // the smallest limit needs to be used, as we can't guarantee that all mixins are applied if multiple are present. + if (Mods.PACKETFIXER.isLoaded()) { + return PACKET_FIXER_LIMIT; + } else if (Mods.XLPACKETS.isLoaded()) { + return XL_PACKETS_LIMIT; + } + + // none are present, use vanilla default + return NBT_LIMIT; + }) - BUFFER; + + /** + * @return true if the given NBT is too large for a contraption to be picked up with a wrench. + */ + public static boolean isTooLargeForPickup(CompoundTag data) { + return nbtSize(data) > LIMIT; + } + + /** + * @return the size of the given NBT when read by the client according to {@link NbtAccounter} + */ + private static long nbtSize(CompoundTag data) { + FriendlyByteBuf test = new FriendlyByteBuf(Unpooled.buffer()); + test.writeNbt(data); + NbtAccounter sizeTracker = new NbtAccounter(Long.MAX_VALUE); + test.readNbt(sizeTracker); + long size = ((NbtAccounterAccessor) sizeTracker).create$getUsage(); + test.release(); + return size; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/data/ContraptionSyncLimiting.java b/src/main/java/com/simibubi/create/content/contraptions/data/ContraptionSyncLimiting.java new file mode 100644 index 0000000000..372a30a529 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/data/ContraptionSyncLimiting.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.contraptions.data; + +import com.simibubi.create.compat.Mods; + +import io.netty.buffer.Unpooled; +import net.minecraft.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; + +public class ContraptionSyncLimiting { + /** + * Contraption entity sync is limited by the clientbound custom payload limit, since that's what Forge's + * extended spawn packet uses. The NBT limit is irrelevant since it's bypassed on deserialization. + */ + public static final int SIZE_LIMIT = 1_048_576; + + // increased packet limits provided by other mods. + public static final int PACKET_FIXER_LIMIT = SIZE_LIMIT * 100; + public static final int XL_PACKETS_LIMIT = Integer.MAX_VALUE; + + // leave some room for the rest of the packet. + public static final int BUFFER = 20_000; + + // the actual limit to be used + public static final int LIMIT = Util.make(() -> { + // the smallest limit needs to be used, as we can't guarantee that all mixins are applied if multiple are present. + if (Mods.PACKETFIXER.isLoaded()) { + return PACKET_FIXER_LIMIT; + } else if (Mods.XLPACKETS.isLoaded()) { + return XL_PACKETS_LIMIT; + } + + // none are present, use vanilla default + return SIZE_LIMIT; + }) - BUFFER; + + /** + * @return true if the given NBT is too large for a contraption to be synced to clients. + */ + public static boolean isTooLargeForSync(CompoundTag data) { + return byteSize(data) > LIMIT; + } + + /** + * @return the size of the given NBT when encoded, in bytes + */ + private static long byteSize(CompoundTag data) { + FriendlyByteBuf test = new FriendlyByteBuf(Unpooled.buffer()); + test.writeNbt(data); + return test.writerIndex(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/data/README.md b/src/main/java/com/simibubi/create/content/contraptions/data/README.md new file mode 100644 index 0000000000..7bae5dbf77 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/data/README.md @@ -0,0 +1,37 @@ +# Data Limiting +This pair of classes prevents clients from getting chunkbanned when contraptions are too large. + +This information is up-to-date as of 1.20.1. + +There's a few different packet limits in play: +- the NBT limit: `2_097_152`, enforced by `FriendlyByteBuf.readNbt()` +- the clientbound custom payload limit: `1_048_576` bytes, applies to `ClientboundCustomPayloadPacket` +- the serverbound custom payload limit: `32767` bytes, applies to `ServerboundCustomPayloadPacket` +- the packet limit: `8_388_608` bytes, applies to all packets + +# NBT Size vs Bytes +There's two units in play as well - NBT Size and Bytes. The NBT limit uses NBT size, while the other +three use bytes. I'm (TropheusJ) not sure what exactly an NBT Size unit is - it's not bits, but it's +close. + +Because of this discrepancy, the NBT limit is actually much lower than it seems. It will usually be +the first limit hit. + +Bytes are found by writing a tag to a buffer and getting its `writerIndex`. NBT Size is found using +an `NbtAccounter`. + +# Sync +Sync is pretty straightforward. + +The only limit relevant here is the clientbound custom payload limit. The NBT limit would be relevant, but +client-side deserialization bypasses it. + +Sync is much less of an issue compared to pickup, since a lot of data can be skipped when syncing. + +# Pickup +Two limits are relevant for pickup: the NBT limit and the packet limit. + +The NBT limit is hit way sooner, and is usually the limiting factor. Other mods may increase it, in +which case the packet limit may become relevant. + +The custom payload limit is not relevant since item sync goes through the vanilla `ClientboundContainerSetSlotPacket`. diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorColumn.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorColumn.java index 61d03c2353..7dd6cfc26b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorColumn.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorColumn.java @@ -11,11 +11,11 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.WorldAttached; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.data.WorldAttached; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -117,7 +117,7 @@ public class ElevatorColumn { targetedYLevel = yLevel; targetAvailable = true; } - + public boolean isTargetAvailable() { return targetAvailable; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlock.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlock.java index 6e7534b3e8..fefdfe9b2d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlock.java @@ -7,16 +7,16 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; import com.simibubi.create.content.redstone.diodes.BrassDiodeBlock; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; -import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.utility.BlockHelper; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -40,12 +40,13 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.phys.BlockHitResult; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; public class ElevatorContactBlock extends WrenchableDirectionalBlock - implements IBE, ISpecialBlockItemRequirement { + implements IBE, SpecialBlockItemRequirement { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty CALLING = BooleanProperty.create("calling"); @@ -85,7 +86,7 @@ public class ElevatorContactBlock extends WrenchableDirectionalBlock return onWrenched; } - + @Nullable public static ColumnCoords getColumnCoords(LevelAccessor level, BlockPos pos) { BlockState blockState = level.getBlockState(pos); diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlockEntity.java index 8a3f09b27e..110609b38c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlockEntity.java @@ -7,9 +7,9 @@ import com.simibubi.create.content.decoration.slidingDoor.DoorControlBehaviour; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.entity.BlockEntityType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactScreen.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactScreen.java index 77cb827659..ee0060c6f7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactScreen.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactScreen.java @@ -6,22 +6,22 @@ import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; import com.simibubi.create.content.decoration.slidingDoor.DoorControl; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.TooltipArea; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.FormattedCharSequence; @@ -40,7 +40,7 @@ public class ElevatorContactScreen extends AbstractSimiScreen { private BlockPos pos; public ElevatorContactScreen(BlockPos pos, String prevShortName, String prevLongName, DoorControl prevDoorControl) { - super(Lang.translateDirect("elevator_contact.title")); + super(CreateLang.translateDirect("elevator_contact.title")); this.pos = pos; this.doorControl = prevDoorControl; background = AllGuiTextures.ELEVATOR_CONTACT; @@ -50,7 +50,7 @@ public class ElevatorContactScreen extends AbstractSimiScreen { @Override public void init() { - setWindowSize(background.width + 30, background.height); + setWindowSize(background.getWidth() + 30, background.getHeight()); super.init(); int x = guiLeft; @@ -75,21 +75,21 @@ public class ElevatorContactScreen extends AbstractSimiScreen { longNameInput.setValue(longName); longNameInput.setResponder(s -> longName = s); - MutableComponent rmbToEdit = Lang.translate("gui.schedule.lmb_edit") + MutableComponent rmbToEdit = CreateLang.translate("gui.schedule.lmb_edit") .style(ChatFormatting.DARK_GRAY) .style(ChatFormatting.ITALIC) .component(); addRenderableOnly(new TooltipArea(x + 21, y + 23, 30, 18) - .withTooltip(ImmutableList.of(Lang.translate("elevator_contact.floor_identifier") + .withTooltip(ImmutableList.of(CreateLang.translate("elevator_contact.floor_identifier") .color(0x5391E1) .component(), rmbToEdit))); addRenderableOnly(new TooltipArea(x + 57, y + 23, 147, 18).withTooltip(ImmutableList.of( - Lang.translate("elevator_contact.floor_description") + CreateLang.translate("elevator_contact.floor_description") .color(0x5391E1) .component(), - Lang.translate("crafting_blueprint.optional") + CreateLang.translate("crafting_blueprint.optional") .style(ChatFormatting.GRAY) .component(), rmbToEdit))); @@ -107,7 +107,7 @@ public class ElevatorContactScreen extends AbstractSimiScreen { } private EditBox editBox(int x, int width, int chars) { - EditBox editBox = new EditBox(font, guiLeft + x, guiTop + 30, width, 10, Components.immutableEmpty()); + EditBox editBox = new EditBox(font, guiLeft + x, guiTop + 30, width, 10, CommonComponents.EMPTY); editBox.setTextColor(-1); editBox.setTextColorUneditable(-1); editBox.setBordered(false); @@ -127,10 +127,10 @@ public class ElevatorContactScreen extends AbstractSimiScreen { FormattedCharSequence formattedcharsequence = title.getVisualOrderText(); graphics.drawString(font, formattedcharsequence, - (float) (x + (background.width - 8) / 2 - font.width(formattedcharsequence) / 2), (float) y + 6, 0x2F3738, false); + (float) (x + (background.getWidth() - 8) / 2 - font.width(formattedcharsequence) / 2), (float) y + 6, 0x2F3738, false); GuiGameElement.of(AllBlocks.ELEVATOR_CONTACT.asStack()).at(x + background.width + 6, y + background.height - 56, -200) + .GuiRenderBuilder>at(x + background.getWidth() + 6, y + background.getHeight() - 56, -200) .scale(5) .render(graphics); diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContraption.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContraption.java index 8c99bf860c..6ff637e28c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContraption.java @@ -7,19 +7,20 @@ import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllContraptionTypes; import com.simibubi.create.AllPackets; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.AssemblyException; -import com.simibubi.create.content.contraptions.ContraptionType; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement.ElevatorFloorSelection; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; import com.simibubi.create.content.contraptions.pulley.PulleyContraption; import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -28,6 +29,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + import net.minecraftforge.network.PacketDistributor; public class ElevatorContraption extends PulleyContraption { @@ -39,7 +41,7 @@ public class ElevatorContraption extends PulleyContraption { private int namesListVersion = -1; public List>> namesList = ImmutableList.of(); public int clientYTarget; - + public int maxContactY; public int minContactY; @@ -94,7 +96,7 @@ public class ElevatorContraption extends PulleyContraption { return null; return targetedYLevel; } - + public boolean isTargetUnreachable(int contactY) { return contactY < minContactY || contactY > maxContactY; } @@ -106,14 +108,14 @@ public class ElevatorContraption extends PulleyContraption { if (blocks.size() <= 0) return false; if (contacts == 0) - throw new AssemblyException(Lang.translateDirect("gui.assembly.exception.no_contacts")); + throw new AssemblyException(CreateLang.translateDirect("gui.assembly.exception.no_contacts")); if (contacts > 1) - throw new AssemblyException(Lang.translateDirect("gui.assembly.exception.too_many_contacts")); - + throw new AssemblyException(CreateLang.translateDirect("gui.assembly.exception.too_many_contacts")); + ElevatorColumn column = ElevatorColumn.get(world, getGlobalColumn()); if (column != null && column.isActive()) - throw new AssemblyException(Lang.translateDirect("gui.assembly.exception.column_conflict")); - + throw new AssemblyException(CreateLang.translateDirect("gui.assembly.exception.column_conflict")); + startMoving(world); return true; } @@ -172,7 +174,7 @@ public class ElevatorContraption extends PulleyContraption { @Override public ContraptionType getType() { - return ContraptionType.ELEVATOR; + return AllContraptionTypes.ELEVATOR.get(); } public void setClientYTarget(int clientYTarget) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorControlsHandler.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorControlsHandler.java index 4fcbcabbd3..bdf9028ce2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorControlsHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorControlsHandler.java @@ -16,17 +16,19 @@ import com.simibubi.create.content.contraptions.actors.contraptionControls.Contr import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement.ElevatorFloorSelection; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -37,8 +39,8 @@ public class ElevatorControlsHandler { private static class ElevatorControlsSlot extends ContraptionControlsBlockEntity.ControlsSlot { @Override - public boolean testHit(BlockState state, Vec3 localHit) { - Vec3 offset = getLocalOffset(state); + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(level, pos, state); if (offset == null) return false; return localHit.distanceTo(offset) < scale * .85; @@ -94,7 +96,7 @@ public class ElevatorControlsHandler { if (!AllBlocks.CONTRAPTION_CONTROLS.has(info.state())) continue; - if (!slot.testHit(info.state(), rayTraceResult.getLocation() + if (!slot.testHit(mc.level, pos, info.state(), rayTraceResult.getLocation() .subtract(Vec3.atLowerCornerOf(pos)))) continue; @@ -111,7 +113,8 @@ public class ElevatorControlsHandler { ElevatorFloorSelection efs = (ElevatorFloorSelection) ctx.temporaryData; int prev = efs.currentIndex; - efs.currentIndex += delta; + // Round away from 0. delta may be ~0.9, which is implicitly floor'd during a pure cast. + efs.currentIndex += (int) (delta > 0 ? Math.ceil(delta) : Math.floor(delta)); ContraptionControlsMovement.tickFloorSelection(efs, ec); if (prev != efs.currentIndex && !ec.namesList.isEmpty()) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorFloorListPacket.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorFloorListPacket.java index f978fa0627..de9cccbbe1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorFloorListPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorFloorListPacket.java @@ -6,13 +6,14 @@ import java.util.List; import com.simibubi.create.AllPackets; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; + import net.minecraftforge.network.NetworkEvent.Context; import net.minecraftforge.network.PacketDistributor; diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyRenderer.java index d9a89b15b7..b430a52f88 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyRenderer.java @@ -8,11 +8,11 @@ import com.simibubi.create.content.contraptions.pulley.AbstractPulleyRenderer; import com.simibubi.create.content.contraptions.pulley.PulleyRenderer; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -29,15 +29,7 @@ public class ElevatorPulleyRenderer extends KineticBlockEntityRenderer .75f) { @@ -109,7 +99,7 @@ public class ElevatorPulleyRenderer extends KineticBlockEntityRenderer implements SimpleDynamicVisual { +public class ElevatorPulleyVisual extends ShaftVisual implements SimpleDynamicVisual, ShaderLightVisual { + private final InstanceRecycler belt; + private final ScrollInstance halfBelt; + + private final ScrollInstance coil; + + private final TransformedInstance magnet; + + private final Matrix4fc cachedMagnetTransform; + + private float lastOffset = Float.NaN; + + private final long topSection; + + private long lastBottomSection; public ElevatorPulleyVisual(VisualizationContext context, ElevatorPulleyBlockEntity blockEntity, float partialTick) { super(context, blockEntity, partialTick); + + float blockStateAngle = + AngleHelper.horizontalAngle(blockState.getValue(ElevatorPulleyBlock.HORIZONTAL_FACING)); + + Quaternionfc rotation = new Quaternionf().rotationY(Mth.DEG_TO_RAD * blockStateAngle); + + topSection = SectionPos.of(pos).asLong(); + + belt = new InstanceRecycler<>(() -> context.instancerProvider() + .instancer(AllInstanceTypes.SCROLLING, SpecialModels.flatLit(AllPartialModels.ELEVATOR_BELT)) + .createInstance() + .rotation(rotation) + .setSpriteShift(AllSpriteShifts.ELEVATOR_BELT)); + + halfBelt = context.instancerProvider() + .instancer(AllInstanceTypes.SCROLLING, SpecialModels.flatLit(AllPartialModels.ELEVATOR_BELT_HALF)) + .createInstance() + .rotation(rotation) + .setSpriteShift(AllSpriteShifts.ELEVATOR_BELT); + + coil = context.instancerProvider() + .instancer(AllInstanceTypes.SCROLLING, Models.partial(AllPartialModels.ELEVATOR_COIL)) + .createInstance() + .position(getVisualPosition()) + .rotation(rotation) + .setSpriteShift(AllSpriteShifts.ELEVATOR_COIL); + + coil.setChanged(); + + magnet = context.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, SpecialModels.flatLit(AllPartialModels.ELEVATOR_MAGNET)) + .createInstance(); + + // Cache the magnet's transform to avoid recalculating this unchanging bit every frame + magnet.setIdentityTransform() + .translate(getVisualPosition()) + .center() + .rotateYDegrees(blockStateAngle) + .uncenter(); + + cachedMagnetTransform = new Matrix4f(magnet.pose); + + animate(PulleyRenderer.getBlockEntityOffset(partialTick, blockEntity)); + } + + @Override + public void updateLight(float partialTick) { + super.updateLight(partialTick); + + relight(coil); + } + + @Override + public void setSectionCollector(SectionCollector sectionCollector) { + super.setSectionCollector(sectionCollector); + + sectionCollector.sections(getLightSections(lastOffset)); } @Override public void beginFrame(DynamicVisual.Context ctx) { + animate(PulleyRenderer.getBlockEntityOffset(ctx.partialTick(), blockEntity)); + } + + @Override + protected void _delete() { + super._delete(); + + belt.delete(); + halfBelt.delete(); + coil.delete(); + magnet.delete(); + } + + private void animate(float offset) { + if (offset == lastOffset) { + return; + } + lastOffset = offset; + + maybeUpdateSections(offset); + + animateCoil(offset); + + animateHalfBelt(offset); + + animateBelt(offset); + + animateMagnet(offset); + } + + private void maybeUpdateSections(float offset) { + if (lightSections == null) { + return; + } + if (lastBottomSection == SectionPos.offset(topSection, 0, -offset2SectionCount(offset), 0)) { + return; + } + + lightSections.sections(getLightSections(offset)); + } + + private void animateMagnet(float offset) { + magnet.setTransform(cachedMagnetTransform) + .translateY(-offset) + .setChanged(); + } + + private void animateBelt(float offset) { + belt.resetCount(); + + for (int i = 0; i < offset - .25f; i++) { + var segment = belt.get() + .position(getVisualPosition()) + .shift(0, -(offset - i), 0); + + segment.offsetV = offset; + + segment.setChanged(); + } + + belt.discardExtra(); + } + + private void animateHalfBelt(float offset) { + float f = offset % 1; + if (f < .25f || f > .75f) { + halfBelt.setVisible(true); + halfBelt.position(getVisualPosition()) + .shift(0, -(f > .75f ? f - 1 : f), 0); + + halfBelt.offsetV = offset; + + halfBelt.setChanged(); + } else { + halfBelt.setVisible(false); + } + } + + private void animateCoil(float offset) { + coil.offsetV = -offset * 2; + + coil.setChanged(); + } + + private LongSet getLightSections(float offset) { + var out = new LongArraySet(); + + int sectionCount = offset2SectionCount(offset); + + for (int i = 0; i < sectionCount; i++) { + out.add(SectionPos.offset(topSection, 0, -i, 0)); + } + + lastBottomSection = SectionPos.offset(topSection, 0, -sectionCount, 0); + + return out; + } + + private static int offset2SectionCount(float offset) { + return (int) Math.ceil((offset + 1) / 16); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorTargetFloorPacket.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorTargetFloorPacket.java index 2e54d8a637..82f8d1925f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorTargetFloorPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorTargetFloorPacket.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.elevator; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlock.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlock.java index 84b4a9c4d3..f8748e8091 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlock.java @@ -3,11 +3,10 @@ package com.simibubi.create.content.contraptions.gantry; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -54,7 +53,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements } public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { + BlockHitResult hit) { if (!player.mayBuild() || player.isShiftKeyDown()) return InteractionResult.PASS; if (player.getItemInHand(handIn) @@ -77,7 +76,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements @Override public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos updatePos, - boolean p_220069_6_) { + boolean p_220069_6_) { if (updatePos.equals(pos.relative(state.getValue(FACING) .getOpposite())) && !canSurvive(state, world, pos)) world.destroyBlock(pos, true); @@ -85,7 +84,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements @Override public BlockState updateShape(BlockState state, Direction direction, BlockState otherState, LevelAccessor world, - BlockPos pos, BlockPos p_196271_6_) { + BlockPos pos, BlockPos p_196271_6_) { if (state.getValue(FACING) != direction.getOpposite()) return state; return cycleAxisIfNecessary(state, direction, otherState); @@ -108,9 +107,8 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements } public static Axis getValidGantryShaftAxis(BlockState state) { - if (!(state.getBlock() instanceof GantryCarriageBlock)) + if (!(state.getBlock() instanceof GantryCarriageBlock block)) return Axis.Y; - IRotate block = (IRotate) state.getBlock(); Axis rotationAxis = block.getRotationAxis(state); Axis facingAxis = state.getValue(FACING) .getAxis(); @@ -138,5 +136,5 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.GANTRY_PINION.get(); } - + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageRenderer.java index b27a04ca10..63af5ff508 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageRenderer.java @@ -4,13 +4,13 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -54,7 +54,7 @@ public class GantryCarriageRenderer extends KineticBlockEntityRenderer p.equals(pos) ? Blocks.AIR.defaultBlockState() : state); + RayTraceLevel rayTraceLevel = + new RayTraceLevel(world, (p, state) -> p.equals(pos) ? Blocks.AIR.defaultBlockState() : state); BlockHitResult ray = - rayTraceWorld.clip(new ClipContext(start, end, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, placer)); + rayTraceLevel.clip(new ClipContext(start, end, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, placer)); Direction face = ray.getDirection(); if (face == null || ray.getType() == Type.MISS) diff --git a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueItem.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueItem.java index 753c3cf31a..8296b3e84f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueItem.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.contraptions.glue; import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ItemParticleOption; @@ -15,6 +15,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.event.entity.player.PlayerInteractEvent; diff --git a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRemovalPacket.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRemovalPacket.java index b11bbdad73..830a34311a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRemovalPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRemovalPacket.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.glue; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHandler.java index ce7bd73e91..743b9a13f9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHandler.java @@ -8,17 +8,17 @@ import com.google.common.base.Objects; import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.RaycastHelper; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.item.ItemStack; @@ -28,6 +28,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult.Type; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.ForgeMod; public class SuperGlueSelectionHandler { @@ -62,8 +63,8 @@ public class SuperGlueSelectionHandler { if (clusterCooldown > 0) { if (clusterCooldown == 25) - player.displayClientMessage(Components.immutableEmpty(), true); - CreateClient.OUTLINER.keep(clusterOutlineSlot); + player.displayClientMessage(CommonComponents.EMPTY, true); + Outliner.getInstance().keep(clusterOutlineSlot); clusterCooldown--; } @@ -97,7 +98,7 @@ public class SuperGlueSelectionHandler { for (SuperGlueEntity glueEntity : glueNearby) { boolean h = clusterCooldown == 0 && glueEntity == selected; AllSpecialTextures faceTex = h ? AllSpecialTextures.GLUE : null; - CreateClient.OUTLINER.showAABB(glueEntity, glueEntity.getBoundingBox()) + Outliner.getInstance().showAABB(glueEntity, glueEntity.getBoundingBox()) .colored(h ? HIGHLIGHT : PASSIVE) .withFaceTextures(faceTex, faceTex) .disableLineNormals() @@ -115,7 +116,7 @@ public class SuperGlueSelectionHandler { } if (firstPos != null && !firstPos.closerThan(hovered, 24)) { - Lang.translate("super_glue.too_far") + CreateLang.translate("super_glue.too_far") .color(FAIL) .sendStatus(player); return; @@ -147,18 +148,18 @@ public class SuperGlueSelectionHandler { key = "super_glue.click_to_discard"; } - Lang.translate(key) + CreateLang.translate(key) .color(color) .sendStatus(player); if (currentSelectionBox != null) - CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox) + Outliner.getInstance().showAABB(bbOutlineSlot, currentSelectionBox) .colored(canReach && canAfford && !cancel ? HIGHLIGHT : FAIL) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.GLUE) .disableLineNormals() .lineWidth(1 / 16f); - CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) + Outliner.getInstance().showCluster(clusterOutlineSlot, currentCluster) .colored(0x4D9162) .disableLineNormals() .lineWidth(1 / 64f); @@ -216,7 +217,7 @@ public class SuperGlueSelectionHandler { if (mc.hitResult instanceof BlockHitResult bhr) { face = bhr.getDirection(); BlockState blockState = level.getBlockState(hoveredPos); - if (blockState.getBlock()instanceof AbstractChassisBlock cb) + if (blockState.getBlock() instanceof AbstractChassisBlock cb) if (cb.getGlueableSide(blockState, bhr.getDirection()) != null) return false; } @@ -235,7 +236,7 @@ public class SuperGlueSelectionHandler { firstPos = hoveredPos; if (face != null) SuperGlueItem.spawnParticles(level, firstPos, face, true); - Lang.translate("super_glue.first_pos") + CreateLang.translate("super_glue.first_pos") .sendStatus(player); AllSoundEvents.SLIME_ADDED.playAt(level, firstPos, 0.5F, 0.85F, false); level.playSound(player, firstPos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.75f, 1); @@ -246,7 +247,7 @@ public class SuperGlueSelectionHandler { LocalPlayer player = Minecraft.getInstance().player; currentCluster = null; firstPos = null; - Lang.translate("super_glue.abort") + CreateLang.translate("super_glue.abort") .sendStatus(player); clusterCooldown = 0; } @@ -258,14 +259,14 @@ public class SuperGlueSelectionHandler { player.level().playSound(player, hoveredPos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.75f, 1); if (currentCluster != null) - CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) + Outliner.getInstance().showCluster(clusterOutlineSlot, currentCluster) .colored(0xB5F2C6) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.HIGHLIGHT_CHECKERED) .disableLineNormals() .lineWidth(1 / 24f); discard(); - Lang.translate("super_glue.success") + CreateLang.translate("super_glue.success") .sendStatus(player); clusterCooldown = 40; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHelper.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHelper.java index 70436fd763..555caf1398 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHelper.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHelper.java @@ -5,9 +5,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import com.simibubi.create.content.contraptions.BlockMovementChecks; -import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.api.contraption.BlockMovementChecks; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; @@ -74,6 +74,8 @@ public class SuperGlueSelectionHelper { ItemStack stack = items.get(slot); if (stack.isEmpty()) continue; + if (stack.getTag() != null && stack.getTag().contains("Unbreakable")) + return true; if (!stack.isDamageableItem()) continue; if (!(stack.getItem() instanceof SuperGlueItem)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionPacket.java index eb253d9e16..0b88c576be 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionPacket.java @@ -1,10 +1,7 @@ package com.simibubi.create.content.contraptions.glue; -import java.util.Set; - import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; @@ -13,6 +10,8 @@ import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.network.NetworkEvent.Context; +import java.util.Set; + public class SuperGlueSelectionPacket extends SimplePacketBase { private BlockPos from; @@ -59,7 +58,7 @@ public class SuperGlueSelectionPacket extends SimplePacketBase { SuperGlueEntity entity = new SuperGlueEntity(player.level(), bb); player.level().addFreshEntity(entity); entity.spawnParticles(); - + AllAdvancements.SUPER_GLUE.awardTo(player); }); return true; diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingCreationPacket.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingCreationPacket.java index cf93f8f577..09fff9c09c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingCreationPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingCreationPacket.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.contraptions.minecart; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.vehicle.AbstractMinecart; diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandler.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandler.java index b6a83a60a9..a6ffadb570 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandler.java @@ -11,17 +11,18 @@ import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; + import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.event.entity.EntityMountEvent; import net.minecraftforge.eventbus.api.Event.Result; @@ -71,9 +72,9 @@ public class CouplingHandler { Entity entity1 = world.getEntity(cartId1); Entity entity2 = world.getEntity(cartId2); - if (!(entity1 instanceof AbstractMinecart)) + if (!(entity1 instanceof AbstractMinecart cart1)) return false; - if (!(entity2 instanceof AbstractMinecart)) + if (!(entity2 instanceof AbstractMinecart cart2)) return false; String tooMany = "two_couplings_max"; @@ -96,8 +97,6 @@ public class CouplingHandler { return false; } - AbstractMinecart cart1 = (AbstractMinecart) entity1; - AbstractMinecart cart2 = (AbstractMinecart) entity2; UUID mainID = cart1.getUUID(); UUID connectedID = cart2.getUUID(); MinecartController mainController = CapabilityMinecartController.getIfPresent(world, mainID); @@ -178,7 +177,7 @@ public class CouplingHandler { public static void status(Player player, String key) { if (player == null) return; - player.displayClientMessage(Lang.translateDirect("minecart_coupling." + key), true); + player.displayClientMessage(CreateLang.translateDirect("minecart_coupling." + key), true); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandlerClient.java index 5f7f8c0520..6f7962d832 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandlerClient.java @@ -4,8 +4,8 @@ import org.joml.Vector3f; import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingPhysics.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingPhysics.java index 44ad6fb59d..3f4620646a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingPhysics.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingPhysics.java @@ -1,10 +1,10 @@ package com.simibubi.create.content.contraptions.minecart; import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.tags.BlockTags; import net.minecraft.util.Mth; @@ -40,7 +40,7 @@ public class CouplingPhysics { Couple corrections = Couple.create(null, null); Couple maxSpeed = carts.map(AbstractMinecart::getMaxCartSpeedOnRail); boolean firstLoop = true; - for (boolean current : new boolean[] { true, false, true }) { + for (boolean current : new boolean[]{true, false, true}) { AbstractMinecart cart = carts.get(current); AbstractMinecart otherCart = carts.get(!current); @@ -54,8 +54,7 @@ public class CouplingPhysics { BlockPos railPosition = cart.getCurrentRailPosition(); BlockState railState = world.getBlockState(railPosition.above()); - if (railState.getBlock() instanceof BaseRailBlock) { - BaseRailBlock block = (BaseRailBlock) railState.getBlock(); + if (railState.getBlock() instanceof BaseRailBlock block) { shape = block.getRailDirection(railState, world, railPosition, cart); } @@ -64,14 +63,14 @@ public class CouplingPhysics { Vec3 link = otherCart.position() .subtract(pos); float correctionMagnitude = firstLoop ? -stress / 2f : -stress; - + if (!MinecartSim2020.canAddMotion(cart)) correctionMagnitude /= 2; - + correction = shape != null ? followLinkOnRail(link, pos, correctionMagnitude, MinecartSim2020.getRailVec(shape)).subtract(pos) : link.normalize() - .scale(correctionMagnitude); + .scale(correctionMagnitude); float maxResolveSpeed = 1.75f; correction = VecHelper.clamp(correction, Math.min(maxResolveSpeed, maxSpeed.get(current))); @@ -93,7 +92,7 @@ public class CouplingPhysics { public static void softCollisionStep(Level world, Couple carts, double couplingLength) { Couple maxSpeed = carts.map(AbstractMinecart::getMaxCartSpeedOnRail); Couple canAddmotion = carts.map(MinecartSim2020::canAddMotion); - + // Assuming Minecarts will never move faster than 1 block/tick Couple motions = carts.map(Entity::getDeltaMovement); motions.replaceWithParams(VecHelper::clamp, Couple.create(1f, 1f)); @@ -102,15 +101,14 @@ public class CouplingPhysics { Couple shapes = carts.mapWithContext((minecart, current) -> { Vec3 vec = nextPositions.get(current); int x = Mth.floor(vec.x()); - int y = Mth.floor(vec.y()); - int z = Mth.floor(vec.z()); - BlockPos pos = new BlockPos(x, y - 1, z); - if (minecart.level().getBlockState(pos).is(BlockTags.RAILS)) pos = pos.below(); + int y = Mth.floor(vec.y()); + int z = Mth.floor(vec.z()); + BlockPos pos = new BlockPos(x, y - 1, z); + if (minecart.level().getBlockState(pos).is(BlockTags.RAILS)) pos = pos.below(); BlockPos railPosition = pos; BlockState railState = world.getBlockState(railPosition.above()); - if (!(railState.getBlock() instanceof BaseRailBlock)) + if (!(railState.getBlock() instanceof BaseRailBlock block)) return null; - BaseRailBlock block = (BaseRailBlock) railState.getBlock(); return block.getRailDirection(railState, world, railPosition, minecart); }); @@ -140,7 +138,7 @@ public class CouplingPhysics { .scale(correctionMagnitude); correction = VecHelper.clamp(correction, maxSpeed.get(current)); - + motions.set(current, motions.get(current) .add(correction)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingRenderer.java index c0fc44402e..2f991b0f6a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingRenderer.java @@ -5,17 +5,17 @@ import static net.minecraft.util.Mth.lerp; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; import com.simibubi.create.content.kinetics.KineticDebugger; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.LevelRenderer; @@ -65,9 +65,9 @@ public class CouplingRenderer { BlockState renderState = Blocks.AIR.defaultBlockState(); VertexConsumer builder = buffer.getBuffer(RenderType.solid()); - SuperByteBuffer attachment = CachedBufferer.partial(AllPartialModels.COUPLING_ATTACHMENT, renderState); - SuperByteBuffer ring = CachedBufferer.partial(AllPartialModels.COUPLING_RING, renderState); - SuperByteBuffer connector = CachedBufferer.partial(AllPartialModels.COUPLING_CONNECTOR, renderState); + SuperByteBuffer attachment = CachedBuffers.partial(AllPartialModels.COUPLING_ATTACHMENT, renderState); + SuperByteBuffer ring = CachedBuffers.partial(AllPartialModels.COUPLING_RING, renderState); + SuperByteBuffer connector = CachedBuffers.partial(AllPartialModels.COUPLING_CONNECTOR, renderState); Vec3 zero = Vec3.ZERO; Vec3 firstEndpoint = transforms.getFirst() @@ -227,13 +227,13 @@ public class CouplingRenderer { int color = Color.mixColors(0xabf0e9, 0xee8572, (float) Mth .clamp(Math.abs(first.getCouplingLength(true) - connectedCenter.distanceTo(mainCenter)) * 8, 0, 1)); - CreateClient.OUTLINER.showLine(mainCart.getId() + "", mainCenter, connectedCenter) + Outliner.getInstance().showLine(mainCart.getId() + "", mainCenter, connectedCenter) .colored(color) .lineWidth(1 / 8f); Vec3 point = mainCart.position() .add(0, yOffset, 0); - CreateClient.OUTLINER.showLine(mainCart.getId() + "_dot", point, point.add(0, 1 / 128f, 0)) + Outliner.getInstance().showLine(mainCart.getId() + "_dot", point, point.add(0, 1 / 128f, 0)) .colored(0xffffff) .lineWidth(1 / 4f); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartCouplingItem.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartCouplingItem.java index e55cbaeda2..cbc88121f2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartCouplingItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartCouplingItem.java @@ -3,8 +3,8 @@ package com.simibubi.create.content.contraptions.minecart; import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; @@ -12,6 +12,7 @@ import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.LazyOptional; @@ -32,9 +33,8 @@ public class MinecartCouplingItem extends Item { @SubscribeEvent(priority = EventPriority.HIGH) public static void handleInteractionWithMinecart(PlayerInteractEvent.EntityInteract event) { Entity interacted = event.getTarget(); - if (!(interacted instanceof AbstractMinecart)) + if (!(interacted instanceof AbstractMinecart minecart)) return; - AbstractMinecart minecart = (AbstractMinecart) interacted; Player player = event.getEntity(); if (player == null) return; @@ -59,7 +59,7 @@ public class MinecartCouplingItem extends Item { } protected static boolean onCouplingInteractOnMinecart(PlayerInteractEvent.EntityInteract event, - AbstractMinecart minecart, Player player, MinecartController controller) { + AbstractMinecart minecart, Player player, MinecartController controller) { Level world = event.getLevel(); if (controller.isFullyCoupled()) { if (!world.isClientSide) @@ -72,7 +72,7 @@ public class MinecartCouplingItem extends Item { } private static boolean onWrenchInteractOnMinecart(EntityInteract event, AbstractMinecart minecart, Player player, - MinecartController controller) { + MinecartController controller) { int couplings = (controller.isConnectedToCoupling() ? 1 : 0) + (controller.isLeadingCoupling() ? 1 : 0); if (couplings == 0) return false; diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartSim2020.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartSim2020.java index 8b232476a9..793e216274 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartSim2020.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartSim2020.java @@ -6,8 +6,8 @@ import com.google.common.collect.Maps; import com.mojang.datafixers.util.Pair; import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -19,6 +19,7 @@ import net.minecraft.world.level.block.BaseRailBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.util.LazyOptional; /** diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java index 6b045b69a4..33a9fadce8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java @@ -1,21 +1,18 @@ package com.simibubi.create.content.contraptions.minecart; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import com.simibubi.create.content.contraptions.Contraption.ContraptionInvWrapper; -import com.simibubi.create.content.contraptions.MountedStorageManager; -import com.simibubi.create.foundation.fluid.CombinedTankWrapper; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageWrapper; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageWrapper; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.MountedStorageManager; -import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.IItemHandlerModifiable; public class TrainCargoManager extends MountedStorageManager { @@ -28,20 +25,13 @@ public class TrainCargoManager extends MountedStorageManager { } @Override - public void createHandlers() { - super.createHandlers(); - } - - @Override - protected ContraptionInvWrapper wrapItems(Collection list, boolean fuel) { - if (fuel) - return super.wrapItems(list, fuel); - return new CargoInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); - } - - @Override - protected CombinedTankWrapper wrapFluids(Collection list) { - return new CargoTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class)); + public void initialize() { + super.initialize(); + this.items = new CargoInvWrapper(this.items); + if (this.fuelItems != null) { + this.fuelItems = new CargoInvWrapper(this.fuelItems); + } + this.fluids = new CargoTankWrapper(this.fluids); } @Override @@ -51,36 +41,35 @@ public class TrainCargoManager extends MountedStorageManager { } @Override - public void read(CompoundTag nbt, Map presentBlockEntities, boolean clientPacket) { - super.read(nbt, presentBlockEntities, clientPacket); + public void read(CompoundTag nbt, boolean clientPacket, @Nullable Contraption contraption) { + super.read(nbt, clientPacket, contraption); ticksSinceLastExchange = nbt.getInt("TicksSinceLastExchange"); } public void resetIdleCargoTracker() { ticksSinceLastExchange = 0; } - + public void tickIdleCargoTracker() { ticksSinceLastExchange++; } - + public int getTicksSinceLastExchange() { return ticksSinceLastExchange; } - + public int getVersion() { return version.get(); } - + void changeDetected() { version.incrementAndGet(); resetIdleCargoTracker(); } - class CargoInvWrapper extends ContraptionInvWrapper { - - public CargoInvWrapper(IItemHandlerModifiable... itemHandler) { - super(false, itemHandler); + class CargoInvWrapper extends MountedItemStorageWrapper { + CargoInvWrapper(MountedItemStorageWrapper wrapped) { + super(wrapped.storages); } @Override @@ -108,10 +97,9 @@ public class TrainCargoManager extends MountedStorageManager { } - class CargoTankWrapper extends CombinedTankWrapper { - - public CargoTankWrapper(IFluidHandler... fluidHandler) { - super(fluidHandler); + class CargoTankWrapper extends MountedFluidStorageWrapper { + CargoTankWrapper(MountedFluidStorageWrapper wrapped) { + super(wrapped.storages); } @Override @@ -137,7 +125,7 @@ public class TrainCargoManager extends MountedStorageManager { changeDetected(); return drained; } - + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/CapabilityMinecartController.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/CapabilityMinecartController.java index 2b6ea7a430..460ee0bd4b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/CapabilityMinecartController.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/CapabilityMinecartController.java @@ -14,11 +14,11 @@ import javax.annotation.Nullable; import com.simibubi.create.AllItems; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.minecart.CouplingHandler; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.WorldAttached; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectLists; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.WorldAttached; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; @@ -28,6 +28,7 @@ import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityToken; @@ -130,7 +131,7 @@ public class CapabilityMinecartController implements ICapabilitySerializable toRemove = new ArrayList<>(); - + for (Entry entry : carts.entrySet()) { MinecartController controller = entry.getValue(); if (controller != null) { @@ -141,7 +142,7 @@ public class CapabilityMinecartController implements ICapabilitySerializable { int j = Mth.floor(cart.getY()); int k = Mth.floor(cart.getZ()); if (world.getBlockState(new BlockPos(i, j - 1, k)) - .is(BlockTags.RAILS)) { + .is(BlockTags.RAILS)) { --j; } BlockPos blockpos = new BlockPos(i, j, k); BlockState blockstate = world.getBlockState(blockpos); if (cart.canUseRail() && blockstate.is(BlockTags.RAILS) - && blockstate.getBlock() instanceof PoweredRailBlock - && ((PoweredRailBlock) blockstate.getBlock()) - .isActivatorRail()) { + && blockstate.getBlock() instanceof PoweredRailBlock + && ((PoweredRailBlock) blockstate.getBlock()) + .isActivatorRail()) { if (cart.isVehicle()) { cart.ejectPassengers(); } @@ -176,11 +177,11 @@ public class MinecartController implements INBTSerializable { List passengers = cart().getPassengers(); if (!passengers.isEmpty()) { Entity entity = passengers.get(0); - if (entity instanceof AbstractContraptionEntity) + if (entity instanceof AbstractContraptionEntity) ((AbstractContraptionEntity) entity).disassemble(); } } - + couplings.set(main, Optional.empty()); needsEntryRefresh |= main; sendData(); @@ -217,9 +218,8 @@ public class MinecartController implements INBTSerializable { if (passengers.isEmpty()) return; Entity entity = passengers.get(0); - if (!(entity instanceof OrientedContraptionEntity)) + if (!(entity instanceof OrientedContraptionEntity contraption)) return; - OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity; UUID couplingId = contraption.getCouplingId(); if (couplingId == cd.mainCartID) { contraption.setCouplingId(cd.connectedCartID); @@ -393,7 +393,8 @@ public class MinecartController implements INBTSerializable { Vec3 motion; float yaw, pitch; - private StallData() {} + private StallData() { + } StallData(AbstractMinecart entity) { position = entity.position(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssembleRailType.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssembleRailType.java index bca741cc78..937318652e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssembleRailType.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssembleRailType.java @@ -3,9 +3,9 @@ package com.simibubi.create.content.contraptions.mounted; import java.util.function.Supplier; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.util.entry.BlockEntry; +import net.createmod.catnip.lang.Lang; import net.minecraft.util.StringRepresentable; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; @@ -13,13 +13,13 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; public enum CartAssembleRailType implements StringRepresentable { - + REGULAR(Blocks.RAIL), POWERED_RAIL(Blocks.POWERED_RAIL), DETECTOR_RAIL(Blocks.DETECTOR_RAIL), ACTIVATOR_RAIL(Blocks.ACTIVATOR_RAIL), CONTROLLER_RAIL(AllBlocks.CONTROLLER_RAIL) - + ; private final Supplier railBlockSupplier; @@ -42,11 +42,11 @@ public enum CartAssembleRailType implements StringRepresentable { public Item getItem() { return railItemSupplier.get(); } - + public boolean matches(BlockState rail) { return rail.getBlock() == railBlockSupplier.get(); } - + @Override public String getSerializedName() { return Lang.asId(name()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlock.java index cd968fae8b..4da7853779 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlock.java @@ -9,9 +9,9 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.redstone.rail.ControllerRailBlock; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.block.IBE; @@ -60,7 +60,7 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class CartAssemblerBlock extends BaseRailBlock - implements IBE, IWrenchable, ISpecialBlockItemRequirement { + implements IBE, IWrenchable, SpecialBlockItemRequirement { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty BACKWARDS = BooleanProperty.create("backwards"); @@ -91,11 +91,11 @@ public class CartAssemblerBlock extends BaseRailBlock public static BlockState getRailBlock(BlockState state) { BaseRailBlock railBlock = (BaseRailBlock) state.getValue(RAIL_TYPE) .getBlock(); - + @SuppressWarnings("deprecation") BlockState railState = railBlock.defaultBlockState() .setValue(railBlock.getShapeProperty(), state.getValue(RAIL_SHAPE)); - + if (railState.hasProperty(ControllerRailBlock.BACKWARDS)) railState = railState.setValue(ControllerRailBlock.BACKWARDS, state.getValue(BACKWARDS)); return railState; diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockEntity.java index f7de3c401d..3aa85fb96b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockEntity.java @@ -19,11 +19,12 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -38,6 +39,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -173,7 +175,7 @@ public class CartAssemblerBlockEntity extends SmartBlockEntity implements IDispl nbt.putDouble("PushX", 0); cart.deserializeNBT(nbt); } - + if (contraption.containsBlockBreakers()) award(AllAdvancements.CONTRAPTION_ACTORS); } @@ -184,9 +186,8 @@ public class CartAssemblerBlockEntity extends SmartBlockEntity implements IDispl return; Entity entity = cart.getPassengers() .get(0); - if (!(entity instanceof OrientedContraptionEntity)) + if (!(entity instanceof OrientedContraptionEntity contraption)) return; - OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity; UUID couplingId = contraption.getCouplingId(); if (couplingId == null) { @@ -234,7 +235,7 @@ public class CartAssemblerBlockEntity extends SmartBlockEntity implements IDispl @Override public void addBehaviours(List behaviours) { movementMode = new ScrollOptionBehaviour<>(CartMovementMode.class, - Lang.translateDirect("contraptions.cart_movement_mode"), this, getMovementModeSlot()); + CreateLang.translateDirect("contraptions.cart_movement_mode"), this, getMovementModeSlot()); behaviours.add(movementMode); registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockItem.java index b7fc2ea08f..3fa5d1d1ab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockItem.java @@ -5,7 +5,7 @@ import javax.annotation.Nonnull; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.redstone.rail.ControllerRailBlock; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -49,7 +49,7 @@ public class CartAssemblerBlockItem extends BlockItem { if (player == null) return false; if (!(block instanceof BaseRailBlock)) { - Lang.translate("block.cart_assembler.invalid") + CreateLang.translate("block.cart_assembler.invalid") .sendStatus(player); return false; } @@ -86,4 +86,4 @@ public class CartAssemblerBlockItem extends BlockItem { AdvancementBehaviour.setPlacedBy(world, pos, player); return true; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/MinecartContraptionItem.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/MinecartContraptionItem.java index 431cf4f489..890f74e07b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/mounted/MinecartContraptionItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/MinecartContraptionItem.java @@ -7,20 +7,20 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.MutablePair; import com.simibubi.create.AllItems; -import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; +import com.simibubi.create.api.contraption.ContraptionMovementSetting; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.ContraptionData; -import com.simibubi.create.content.contraptions.ContraptionMovementSetting; import com.simibubi.create.content.contraptions.OrientedContraptionEntity; import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceMovement; import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.data.ContraptionPickupLimiting; import com.simibubi.create.content.kinetics.deployer.DeployerFakePlayer; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockSource; @@ -44,6 +44,7 @@ import net.minecraft.world.level.block.DispenserBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -64,7 +65,7 @@ public class MinecartContraptionItem extends Item { public static MinecartContraptionItem chest(Properties builder) { return new MinecartContraptionItem(Type.CHEST, builder); } - + @Override public boolean canFitInsideContainerItems() { return AllConfigs.server().kinetics.minecartContraptionInContainers.get(); @@ -110,7 +111,7 @@ public class MinecartContraptionItem extends Item { BlockState blockstate1 = world.getBlockState(blockpos.below()); RailShape railshape1 = blockstate1.getBlock() instanceof BaseRailBlock ? ((BaseRailBlock) blockstate1.getBlock()).getRailDirection(blockstate1, world, blockpos.below(), - null) + null) : RailShape.NORTH_SOUTH; if (direction != Direction.DOWN && railshape1.isAscending()) { d3 = -0.4D; @@ -173,7 +174,7 @@ public class MinecartContraptionItem extends Item { } public static void addContraptionToMinecart(Level world, ItemStack itemstack, AbstractMinecart cart, - @Nullable Direction newFacing) { + @Nullable Direction newFacing) { CompoundTag tag = itemstack.getOrCreateTag(); if (tag.contains("Contraption")) { CompoundTag contraptionTag = tag.getCompound("Contraption"); @@ -184,7 +185,7 @@ public class MinecartContraptionItem extends Item { OrientedContraptionEntity contraptionEntity = newFacing == null ? OrientedContraptionEntity.create(world, mountedContraption, intialOrientation) : OrientedContraptionEntity.createAtYaw(world, mountedContraption, intialOrientation, - newFacing.toYRot()); + newFacing.toYRot()); contraptionEntity.startRiding(cart); contraptionEntity.setPos(cart.getX(), cart.getY(), cart.getZ()); @@ -211,25 +212,23 @@ public class MinecartContraptionItem extends Item { return; if (entity instanceof AbstractContraptionEntity) entity = entity.getVehicle(); - if (!(entity instanceof AbstractMinecart)) + if (!(entity instanceof AbstractMinecart cart)) return; if (!entity.isAlive()) return; if (player instanceof DeployerFakePlayer dfp && dfp.onMinecartContraption) return; - AbstractMinecart cart = (AbstractMinecart) entity; Type type = cart.getMinecartType(); if (type != Type.RIDEABLE && type != Type.FURNACE && type != Type.CHEST) return; List passengers = cart.getPassengers(); - if (passengers.isEmpty() || !(passengers.get(0) instanceof OrientedContraptionEntity)) + if (passengers.isEmpty() || !(passengers.get(0) instanceof OrientedContraptionEntity oce)) return; - OrientedContraptionEntity oce = (OrientedContraptionEntity) passengers.get(0); Contraption contraption = oce.getContraption(); if (ContraptionMovementSetting.isNoPickup(contraption.getBlocks() .values())) { - player.displayClientMessage(Lang.translateDirect("contraption.minecart_contraption_illegal_pickup") + player.displayClientMessage(CreateLang.translateDirect("contraption.minecart_contraption_illegal_pickup") .withStyle(ChatFormatting.RED), true); return; } @@ -243,14 +242,14 @@ public class MinecartContraptionItem extends Item { contraption.stop(event.getLevel()); for (MutablePair pair : contraption.getActors()) - if (AllMovementBehaviours.getBehaviour(pair.left.state())instanceof PortableStorageInterfaceMovement psim) + if (MovementBehaviour.REGISTRY.get(pair.left.state()) instanceof PortableStorageInterfaceMovement psim) psim.reset(pair.right); ItemStack generatedStack = create(type, oce).setHoverName(entity.getCustomName()); - if (ContraptionData.isTooLargeForPickup(generatedStack.serializeNBT())) { - MutableComponent message = Lang.translateDirect("contraption.minecart_contraption_too_big") - .withStyle(ChatFormatting.RED); + if (ContraptionPickupLimiting.isTooLargeForPickup(generatedStack.serializeNBT())) { + MutableComponent message = CreateLang.translateDirect("contraption.minecart_contraption_too_big") + .withStyle(ChatFormatting.RED); player.displayClientMessage(message, true); return; } @@ -271,17 +270,17 @@ public class MinecartContraptionItem extends Item { ItemStack stack = ItemStack.EMPTY; switch (type) { - case RIDEABLE: - stack = AllItems.MINECART_CONTRAPTION.asStack(); - break; - case FURNACE: - stack = AllItems.FURNACE_MINECART_CONTRAPTION.asStack(); - break; - case CHEST: - stack = AllItems.CHEST_MINECART_CONTRAPTION.asStack(); - break; - default: - break; + case RIDEABLE: + stack = AllItems.MINECART_CONTRAPTION.asStack(); + break; + case FURNACE: + stack = AllItems.FURNACE_MINECART_CONTRAPTION.asStack(); + break; + case CHEST: + stack = AllItems.CHEST_MINECART_CONTRAPTION.asStack(); + break; + default: + break; } if (stack.isEmpty()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java index 0c2052a3d8..213cfa77a1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java @@ -7,14 +7,15 @@ import java.util.Queue; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllContraptionTypes; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AssemblyException; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.ContraptionType; import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity.CartMovementMode; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -30,6 +31,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.RailShape; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.AABB; + import net.minecraftforge.items.wrapper.InvWrapper; public class MountedContraption extends Contraption { @@ -47,7 +49,7 @@ public class MountedContraption extends Contraption { @Override public ContraptionType getType() { - return ContraptionType.MOUNTED; + return AllContraptionTypes.MOUNTED.get(); } @Override @@ -59,7 +61,7 @@ public class MountedContraption extends Contraption { return false; Axis axis = state.getValue(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z; - addBlock(pos, Pair.of(new StructureBlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState() + addBlock(world, pos, Pair.of(new StructureBlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState() .setValue(BlockStateProperties.HORIZONTAL_AXIS, axis), null), null)); if (blocks.size() == 1) @@ -153,7 +155,7 @@ public class MountedContraption extends Contraption { public void addExtraInventories(Entity cart) { if (cart instanceof Container container) - storage.attachExternal(new ContraptionInvWrapper(true, new InvWrapper(container))); + storage.attachExternal(new InvWrapper(container)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/LinearActuatorBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/piston/LinearActuatorBlockEntity.java index 7f627f7d3f..22dd3b27cf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/piston/LinearActuatorBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/LinearActuatorBlockEntity.java @@ -14,7 +14,7 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.ServerSpeedProvider; import net.minecraft.core.BlockPos; @@ -52,13 +52,13 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity @Override public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); - movementMode = new ScrollOptionBehaviour<>(MovementMode.class, Lang.translateDirect("contraptions.movement_mode"), + movementMode = new ScrollOptionBehaviour<>(MovementMode.class, CreateLang.translateDirect("contraptions.movement_mode"), this, getMovementModeSlot()); movementMode.withCallback(t -> waitingForSpeedChange = false); behaviours.add(movementMode); registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); } - + @Override protected boolean syncSequenceContext() { return true; @@ -74,7 +74,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity if (isPassive()) return; - + if (level.isClientSide) clientOffsetDiff *= .75f; @@ -134,7 +134,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity resetContraptionToOffset(); sendData(); } - + if (contraptionPresent) { if (moveAndCollideContraption()) { movedContraption.setContraptionMotion(Vec3.ZERO); @@ -167,7 +167,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity protected boolean isPassive() { return false; } - + @Override public void lazyTick() { super.lazyTick(); @@ -189,10 +189,10 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity public void onSpeedChanged(float prevSpeed) { super.onSpeedChanged(prevSpeed); sequencedOffsetLimit = -1; - + if (isPassive()) return; - + assembleNextTick = true; waitingForSpeedChange = false; diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlock.java b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlock.java index a30a17c09e..dd7f93b10f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlock.java @@ -6,9 +6,9 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; @@ -32,6 +32,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.common.Tags; public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implements IBE { @@ -99,14 +100,14 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement } @Override - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos fromPos, - boolean p_220069_6_) { + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, + boolean isMoving) { Direction direction = state.getValue(FACING); if (!fromPos.equals(pos.relative(direction.getOpposite()))) return; - if (!world.isClientSide && !world.getBlockTicks() + if (!level.isClientSide && !level.getBlockTicks() .willTickThisTick(pos, this)) - world.scheduleTick(pos, this, 0); + level.scheduleTick(pos, this, 1); } @Override @@ -207,7 +208,7 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement public Class getBlockEntityClass() { return MechanicalPistonBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.MECHANICAL_PISTON.get(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java index 3072c36041..9f90f524a5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java @@ -14,14 +14,15 @@ import java.util.Queue; import org.apache.commons.lang3.tuple.Pair; +import com.simibubi.create.AllContraptionTypes; +import com.simibubi.create.api.contraption.BlockMovementChecks; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AssemblyException; -import com.simibubi.create.content.contraptions.BlockMovementChecks; -import com.simibubi.create.content.contraptions.ContraptionType; import com.simibubi.create.content.contraptions.TranslatingContraption; import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -47,10 +48,11 @@ public class PistonContraption extends TranslatingContraption { @Override public ContraptionType getType() { - return ContraptionType.PISTON; + return AllContraptionTypes.PISTON.get(); } - public PistonContraption() {} + public PistonContraption() { + } public PistonContraption(Direction direction, boolean retract) { orientation = direction; @@ -126,9 +128,9 @@ public class PistonContraption extends TranslatingContraption { extensionLength = extensionsInBack + extensionsInFront; initialExtensionProgress = extensionsInFront; pistonExtensionCollisionBox = new AABB( - BlockPos.ZERO.relative(direction, -1), - BlockPos.ZERO.relative(direction, -extensionLength - 1)).expandTowards(1, - 1, 1); + BlockPos.ZERO.relative(direction, -1), + BlockPos.ZERO.relative(direction, -extensionLength - 1)).expandTowards(1, + 1, 1); if (extensionLength == 0) throw AssemblyException.noPistonPoles(); @@ -187,8 +189,8 @@ public class PistonContraption extends TranslatingContraption { } @Override - public void addBlock(BlockPos pos, Pair capture) { - super.addBlock(pos.relative(orientation, -initialExtensionProgress), capture); + public void addBlock(Level level, BlockPos pos, Pair capture) { + super.addBlock(level, pos.relative(orientation, -initialExtensionProgress), capture); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/PistonExtensionPoleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonExtensionPoleBlock.java index 76d0bcf138..4148c3f8bc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/piston/PistonExtensionPoleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonExtensionPoleBlock.java @@ -11,10 +11,10 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; import com.simibubi.create.foundation.placement.PoleHelper; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -45,12 +45,12 @@ import net.minecraft.world.phys.shapes.VoxelShape; public class PistonExtensionPoleBlock extends WrenchableDirectionalBlock implements IWrenchable, SimpleWaterloggedBlock { - private static final int placementHelperId = PlacementHelpers.register(PlacementHelper.get()); + private static final int placementHelperId = PlacementHelpers.register(PlacementHelper.get()); - public PistonExtensionPoleBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(FACING, Direction.UP).setValue(BlockStateProperties.WATERLOGGED, false)); - } + public PistonExtensionPoleBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(FACING, Direction.UP).setValue(BlockStateProperties.WATERLOGGED, false)); + } @Override public PushReaction getPistonPushReaction(BlockState state) { @@ -65,7 +65,7 @@ public class PistonExtensionPoleBlock extends WrenchableDirectionalBlock impleme BlockPos pistonHead = null; BlockPos pistonBase = null; - for (int modifier : new int[] { 1, -1 }) { + for (int modifier : new int[]{1, -1}) { for (int offset = modifier; modifier * offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset += modifier) { BlockPos currentPos = pos.relative(direction, offset); @@ -89,18 +89,17 @@ public class PistonExtensionPoleBlock extends WrenchableDirectionalBlock impleme if (pistonHead != null && pistonBase != null && worldIn.getBlockState(pistonHead) .getValue(BlockStateProperties.FACING) == worldIn.getBlockState(pistonBase) - .getValue(BlockStateProperties.FACING)) { + .getValue(BlockStateProperties.FACING)) { final BlockPos basePos = pistonBase; BlockPos.betweenClosedStream(pistonBase, pistonHead) - .filter(p -> !p.equals(pos) && !p.equals(basePos)) - .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); + .filter(p -> !p.equals(pos) && !p.equals(basePos)) + .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); worldIn.setBlockAndUpdate(basePos, worldIn.getBlockState(basePos) - .setValue(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); + .setValue(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); BlockEntity be = worldIn.getBlockEntity(basePos); - if (be instanceof MechanicalPistonBlockEntity) { - MechanicalPistonBlockEntity baseBE = (MechanicalPistonBlockEntity) be; + if (be instanceof MechanicalPistonBlockEntity baseBE) { baseBE.offset = 0; baseBE.onLengthBroken(); } @@ -120,18 +119,18 @@ public class PistonExtensionPoleBlock extends WrenchableDirectionalBlock impleme FluidState FluidState = context.getLevel() .getFluidState(context.getClickedPos()); return defaultBlockState().setValue(FACING, context.getClickedFace() - .getOpposite()) + .getOpposite()) .setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); } @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult ray) { + BlockHitResult ray) { ItemStack heldItem = player.getItemInHand(hand); - IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); - if (placementHelper.matchesItem(heldItem) && !player.isShiftKeyDown()) - return placementHelper.getOffset(player, world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (placementHelper.matchesItem(heldItem) && !player.isShiftKeyDown()) + return placementHelper.getOffset(player, world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); return InteractionResult.PASS; } @@ -148,38 +147,38 @@ public class PistonExtensionPoleBlock extends WrenchableDirectionalBlock impleme super.createBlockStateDefinition(builder); } - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { - if (state.getValue(BlockStateProperties.WATERLOGGED)) - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - return state; - } + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(BlockStateProperties.WATERLOGGED)) + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + return state; + } @Override public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { return false; } - @MethodsReturnNonnullByDefault - public static class PlacementHelper extends PoleHelper { + @MethodsReturnNonnullByDefault + public static class PlacementHelper extends PoleHelper { - private static final PlacementHelper instance = new PlacementHelper(); + private static final PlacementHelper instance = new PlacementHelper(); - public static PlacementHelper get() { - return instance; - } + public static PlacementHelper get() { + return instance; + } - private PlacementHelper(){ - super( - AllBlocks.PISTON_EXTENSION_POLE::has, - state -> state.getValue(FACING).getAxis(), - FACING - ); - } + private PlacementHelper() { + super( + AllBlocks.PISTON_EXTENSION_POLE::has, + state -> state.getValue(FACING).getAxis(), + FACING + ); + } - @Override - public Predicate getItemPredicate() { - return AllBlocks.PISTON_EXTENSION_POLE::isIn; - } - } + @Override + public Predicate getItemPredicate() { + return AllBlocks.PISTON_EXTENSION_POLE::isIn; + } + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyRenderer.java index caca5fd8db..5239d77bec 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyRenderer.java @@ -2,15 +2,14 @@ package com.simibubi.create.content.contraptions.pulley; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -51,18 +50,17 @@ public abstract class AbstractPulleyRenderer exten float offset = getOffset(be, partialTicks); boolean running = isRunning(be); - Axis rotationAxis = ((IRotate) be.getBlockState() - .getBlock()).getRotationAxis(be.getBlockState()); VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - kineticRotationTransform(getRotatedCoil(be), be, rotationAxis, AngleHelper.rad(offset * 180), light) + scrollCoil(getRotatedCoil(be), getCoilShift(), offset, 1) + .light(light) .renderInto(ms, vb); Level world = be.getLevel(); BlockState blockState = be.getBlockState(); BlockPos pos = be.getBlockPos(); - SuperByteBuffer halfMagnet = CachedBufferer.partial(this.halfMagnet, blockState); - SuperByteBuffer halfRope = CachedBufferer.partial(this.halfRope, blockState); + SuperByteBuffer halfMagnet = CachedBuffers.partial(this.halfMagnet, blockState); + SuperByteBuffer halfRope = CachedBuffers.partial(this.halfRope, blockState); SuperByteBuffer magnet = renderMagnet(be); SuperByteBuffer rope = renderRope(be); @@ -92,6 +90,8 @@ public abstract class AbstractPulleyRenderer exten protected abstract Axis getShaftAxis(T be); protected abstract PartialModel getCoil(); + + protected abstract SpriteShiftEntry getCoilShift(); protected abstract SuperByteBuffer renderRope(T be); @@ -108,10 +108,22 @@ public abstract class AbstractPulleyRenderer exten protected SuperByteBuffer getRotatedCoil(T be) { BlockState blockState = be.getBlockState(); - return CachedBufferer.partialFacing(getCoil(), blockState, + return CachedBuffers.partialFacing(getCoil(), blockState, Direction.get(AxisDirection.POSITIVE, getShaftAxis(be))); } + public static SuperByteBuffer scrollCoil(SuperByteBuffer sbb, SpriteShiftEntry coilShift, float offset, float speedModifier) { + if (offset == 0) + return sbb; + float spriteSize = coilShift.getTarget() + .getV1() + - coilShift.getTarget() + .getV0(); + offset *= speedModifier / 2; + double coilScroll = -(offset + 3 / 16f) - Math.floor((offset + 3 / 16f) * -2) / 2; + return sbb.shiftUVScrolling(coilShift, (float) coilScroll * spriteSize); + } + @Override public int getViewDistance() { return 256; diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyVisual.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyVisual.java index df9a1a158b..f716556001 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyVisual.java @@ -2,15 +2,18 @@ package com.simibubi.create.content.contraptions.pulley; import java.util.function.Consumer; +import org.joml.Quaternionf; +import org.joml.Quaternionfc; + import com.mojang.math.Axis; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.ShaftVisual; +import com.simibubi.create.content.processing.burner.ScrollInstance; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.instance.OrientedInstance; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.math.MoreMath; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; @@ -19,6 +22,8 @@ import it.unimi.dsi.fastutil.bytes.ByteArrayList; import it.unimi.dsi.fastutil.bytes.ByteList; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.SpriteShiftEntry; import net.minecraft.client.renderer.LightTexture; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -27,7 +32,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.level.LightLayer; public abstract class AbstractPulleyVisual extends ShaftVisual implements SimpleDynamicVisual { - private final OrientedInstance coil; + private final ScrollInstance coil; private final TransformedInstance magnet; private final SmartRecycler rope; @@ -41,11 +46,17 @@ public abstract class AbstractPulleyVisual extends public AbstractPulleyVisual(VisualizationContext dispatcher, T blockEntity, float partialTick) { super(dispatcher, blockEntity, partialTick); - rotatingAbout = Direction.get(Direction.AxisDirection.POSITIVE, axis); + rotatingAbout = Direction.get(Direction.AxisDirection.POSITIVE, rotationAxis()); rotationAxis = Axis.of(rotatingAbout.step()); + float blockStateAngle = AngleHelper.horizontalAngle(rotatingAbout); + Quaternionfc rotation = new Quaternionf().rotationY(Mth.DEG_TO_RAD * blockStateAngle); + coil = getCoilModel().createInstance() - .position(getVisualPosition()); + .rotation(rotation) + .position(getVisualPosition()) + .setSpriteShift(getCoilAnimation()); + coil.setChanged(); magnet = magnetInstancer().createInstance(); @@ -54,6 +65,7 @@ public abstract class AbstractPulleyVisual extends updateOffset(partialTick); updateLight(partialTick); + animate(); } @Override @@ -68,7 +80,7 @@ public abstract class AbstractPulleyVisual extends protected abstract Instancer getHalfMagnetModel(); - protected abstract Instancer getCoilModel(); + protected abstract Instancer getCoilModel(); protected abstract Instancer getHalfRopeModel(); @@ -76,6 +88,8 @@ public abstract class AbstractPulleyVisual extends protected abstract boolean isRunning(); + protected abstract SpriteShiftEntry getCoilAnimation(); + private Instancer magnetInstancer() { return offset > .25f ? getMagnetModel() : getHalfMagnetModel(); } @@ -83,8 +97,12 @@ public abstract class AbstractPulleyVisual extends @Override public void beginFrame(DynamicVisual.Context ctx) { updateOffset(ctx.partialTick()); - coil.rotation(rotationAxis.rotationDegrees(offset * 180)) - .setChanged(); + animate(); + } + + private void animate() { + coil.offsetV = -offset; + coil.setChanged(); magnet.setVisible(isRunning() || offset == 0); diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/HosePulleyVisual.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/HosePulleyVisual.java index 417541ca99..b2447ab03c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/pulley/HosePulleyVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/HosePulleyVisual.java @@ -1,14 +1,17 @@ package com.simibubi.create.content.contraptions.pulley; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.fluids.hosePulley.HosePulleyBlockEntity; +import com.simibubi.create.content.processing.burner.ScrollInstance; +import com.simibubi.create.foundation.render.AllInstanceTypes; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; -import dev.engine_room.flywheel.lib.instance.OrientedInstance; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; +import net.createmod.catnip.render.SpriteShiftEntry; public class HosePulleyVisual extends AbstractPulleyVisual { public HosePulleyVisual(VisualizationContext dispatcher, HosePulleyBlockEntity blockEntity, float partialTick) { @@ -31,8 +34,8 @@ public class HosePulleyVisual extends AbstractPulleyVisual getCoilModel() { - return instancerProvider().instancer(InstanceTypes.ORIENTED, Models.partial(AllPartialModels.HOSE_COIL, rotatingAbout)); + protected Instancer getCoilModel() { + return instancerProvider().instancer(AllInstanceTypes.SCROLLING, Models.partial(AllPartialModels.HOSE_COIL)); } @Override @@ -49,4 +52,10 @@ public class HosePulleyVisual extends AbstractPulleyVisual { - public PulleyBlock(Properties properties) { - super(properties); - } + public PulleyBlock(Properties properties) { + super(properties); + } - private static void onRopeBroken(Level world, BlockPos pulleyPos) { + private static void onRopeBroken(Level world, BlockPos pulleyPos) { BlockEntity be = world.getBlockEntity(pulleyPos); - if (be instanceof PulleyBlockEntity) { - PulleyBlockEntity pulley = (PulleyBlockEntity) be; + if (be instanceof PulleyBlockEntity pulley) { pulley.initialOffset = 0; pulley.onLengthBroken(); } @@ -59,127 +58,122 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements IBE be.assembleNextTick = true); - return InteractionResult.SUCCESS; - } - return InteractionResult.PASS; - } + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (!player.mayBuild()) + return InteractionResult.PASS; + if (player.isShiftKeyDown()) + return InteractionResult.PASS; + if (player.getItemInHand(handIn) + .isEmpty()) { + withBlockEntityDo(worldIn, pos, be -> be.assembleNextTick = true); + return InteractionResult.SUCCESS; + } + return InteractionResult.PASS; + } - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return AllShapes.PULLEY.get(state.getValue(HORIZONTAL_AXIS)); - } + @Override + public Class getBlockEntityClass() { + return PulleyBlockEntity.class; + } - @Override - public Class getBlockEntityClass() { - return PulleyBlockEntity.class; - } - - @Override - public BlockEntityType getBlockEntityType() { - return AllBlockEntityTypes.ROPE_PULLEY.get(); - } + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ROPE_PULLEY.get(); + } - private static class RopeBlockBase extends Block implements SimpleWaterloggedBlock { + private static class RopeBlockBase extends Block implements SimpleWaterloggedBlock { - public RopeBlockBase(Properties properties) { - super(properties); - registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); - } + public RopeBlockBase(Properties properties) { + super(properties); + registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); + } @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } - @Override - public PushReaction getPistonPushReaction(BlockState state) { - return PushReaction.BLOCK; - } + @Override + public PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.BLOCK; + } - @Override - public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, - Player player) { - return AllBlocks.ROPE_PULLEY.asStack(); - } + @Override + public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, + Player player) { + return AllBlocks.ROPE_PULLEY.asStack(); + } - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (!isMoving && (!state.hasProperty(BlockStateProperties.WATERLOGGED) || !newState.hasProperty(BlockStateProperties.WATERLOGGED) || state.getValue(BlockStateProperties.WATERLOGGED) == newState.getValue(BlockStateProperties.WATERLOGGED))) { - onRopeBroken(worldIn, pos.above()); - if (!worldIn.isClientSide) { - BlockState above = worldIn.getBlockState(pos.above()); - BlockState below = worldIn.getBlockState(pos.below()); - if (above.getBlock() instanceof RopeBlockBase) - worldIn.destroyBlock(pos.above(), true); - if (below.getBlock() instanceof RopeBlockBase) - worldIn.destroyBlock(pos.below(), true); - } - } - if (state.hasBlockEntity() && state.getBlock() != newState.getBlock()) { - worldIn.removeBlockEntity(pos); - } - } + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (!isMoving && (!state.hasProperty(BlockStateProperties.WATERLOGGED) || !newState.hasProperty(BlockStateProperties.WATERLOGGED) || state.getValue(BlockStateProperties.WATERLOGGED) == newState.getValue(BlockStateProperties.WATERLOGGED))) { + onRopeBroken(worldIn, pos.above()); + if (!worldIn.isClientSide) { + BlockState above = worldIn.getBlockState(pos.above()); + BlockState below = worldIn.getBlockState(pos.below()); + if (above.getBlock() instanceof RopeBlockBase) + worldIn.destroyBlock(pos.above(), true); + if (below.getBlock() instanceof RopeBlockBase) + worldIn.destroyBlock(pos.below(), true); + } + } + if (state.hasBlockEntity() && state.getBlock() != newState.getBlock()) { + worldIn.removeBlockEntity(pos); + } + } - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); - } + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); + } - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(BlockStateProperties.WATERLOGGED); - super.createBlockStateDefinition(builder); - } + @Override + protected void createBlockStateDefinition(Builder builder) { + builder.add(BlockStateProperties.WATERLOGGED); + super.createBlockStateDefinition(builder); + } - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, - LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { - if (state.getValue(BlockStateProperties.WATERLOGGED)) - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - return state; - } + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, + LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(BlockStateProperties.WATERLOGGED)) + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + return state; + } - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - FluidState FluidState = context.getLevel().getFluidState(context.getClickedPos()); - return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); - } + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + FluidState FluidState = context.getLevel().getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); + } - } + } - public static class MagnetBlock extends RopeBlockBase { + public static class MagnetBlock extends RopeBlockBase { - public MagnetBlock(Properties properties) { - super(properties); - } + public MagnetBlock(Properties properties) { + super(properties); + } - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return AllShapes.PULLEY_MAGNET; - } + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.PULLEY_MAGNET; + } - } + } - public static class RopeBlock extends RopeBlockBase { + public static class RopeBlock extends RopeBlockBase { - public RopeBlock(Properties properties) { - super(properties); - } + public RopeBlock(Properties properties) { + super(properties); + } - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return AllShapes.FOUR_VOXEL_POLE.get(Direction.UP); - } - } + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.FOUR_VOXEL_POLE.get(Direction.UP); + } + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlockEntity.java index 28bf7924d9..2cd910d390 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlockEntity.java @@ -7,9 +7,9 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; +import com.simibubi.create.api.contraption.BlockMovementChecks; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.AssemblyException; -import com.simibubi.create.content.contraptions.BlockMovementChecks; import com.simibubi.create.content.contraptions.ContraptionCollider; import com.simibubi.create.content.contraptions.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.piston.LinearActuatorBlockEntity; @@ -18,15 +18,17 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -74,9 +76,9 @@ public class PulleyBlockEntity extends LinearActuatorBlockEntity implements Thre if (level.isClientSide() && mirrorParent != null) if (sharedMirrorContraption == null || sharedMirrorContraption.get() == null || !sharedMirrorContraption.get() - .isAlive()) { + .isAlive()) { sharedMirrorContraption = null; - if (level.getBlockEntity(mirrorParent)instanceof PulleyBlockEntity pte && pte.movedContraption != null) + if (level.getBlockEntity(mirrorParent) instanceof PulleyBlockEntity pte && pte.movedContraption != null) sharedMirrorContraption = new WeakReference<>(pte.movedContraption); } @@ -202,8 +204,8 @@ public class PulleyBlockEntity extends LinearActuatorBlockEntity implements Thre .getCollisionShape(level, magnetPos) .isEmpty()); level.setBlock(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState() - .setValue(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)), + .setValue(BlockStateProperties.WATERLOGGED, + Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)), 66); } } @@ -230,7 +232,7 @@ public class PulleyBlockEntity extends LinearActuatorBlockEntity implements Thre .setValue(BlockStateProperties.WATERLOGGED, waterlog[i]), 66); } } - + } if (movedContraption != null && mirrorParent == null) @@ -253,8 +255,7 @@ public class PulleyBlockEntity extends LinearActuatorBlockEntity implements Thre @Override protected Vec3 toPosition(float offset) { - if (movedContraption.getContraption() instanceof PulleyContraption) { - PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption(); + if (movedContraption.getContraption() instanceof PulleyContraption contraption) { return Vec3.atLowerCornerOf(contraption.anchor) .add(0, contraption.getInitialOffset() - offset, 0); @@ -387,15 +388,30 @@ public class PulleyBlockEntity extends LinearActuatorBlockEntity implements Thre offset = forcedOffset; } - @Override - public float getPercent() { - int distance = worldPosition.getY() - level.getMinBuildHeight(); - if (distance <= 0) - return 100; - return 100 * getInterpolatedOffset(.5f) / distance; - } - public BlockPos getMirrorParent() { return mirrorParent; } + + // Threshold switch + + @Override + public int getCurrentValue() { + return worldPosition.getY() - (int) getInterpolatedOffset(.5f); + } + + @Override + public int getMinValue() { + return level.getMinBuildHeight(); + } + + @Override + public int getMaxValue() { + return worldPosition.getY(); + } + + @Override + public MutableComponent format(int value) { + return CreateLang.translateDirect("gui.threshold_switch.pulley_y_level", value); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyContraption.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyContraption.java index 8310a4cae6..267c8b6d0c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyContraption.java @@ -1,7 +1,8 @@ package com.simibubi.create.content.contraptions.pulley; +import com.simibubi.create.AllContraptionTypes; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AssemblyException; -import com.simibubi.create.content.contraptions.ContraptionType; import com.simibubi.create.content.contraptions.TranslatingContraption; import net.minecraft.core.BlockPos; @@ -14,7 +15,7 @@ public class PulleyContraption extends TranslatingContraption { @Override public ContraptionType getType() { - return ContraptionType.PULLEY; + return AllContraptionTypes.PULLEY.get(); } public PulleyContraption() {} diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyRenderer.java index 0b201bc2eb..4f7ca4b89a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyRenderer.java @@ -2,11 +2,13 @@ package com.simibubi.create.content.contraptions.pulley; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.core.Direction.Axis; import net.minecraft.util.Mth; @@ -30,12 +32,12 @@ public class PulleyRenderer extends AbstractPulleyRenderer { @Override protected SuperByteBuffer renderRope(PulleyBlockEntity be) { - return CachedBufferer.block(AllBlocks.ROPE.getDefaultState()); + return CachedBuffers.block(AllBlocks.ROPE.getDefaultState()); } @Override protected SuperByteBuffer renderMagnet(PulleyBlockEntity be) { - return CachedBufferer.block(AllBlocks.PULLEY_MAGNET.getDefaultState()); + return CachedBuffers.block(AllBlocks.PULLEY_MAGNET.getDefaultState()); } @Override @@ -52,6 +54,11 @@ public class PulleyRenderer extends AbstractPulleyRenderer { return be.running || be.mirrorParent != null || be.isVirtual(); } + @Override + protected SpriteShiftEntry getCoilShift() { + return AllSpriteShifts.ROPE_PULLEY_COIL; + } + public static float getBlockEntityOffset(float partialTicks, PulleyBlockEntity blockEntity) { float offset = blockEntity.getInterpolatedOffset(partialTicks); diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/RopePulleyVisual.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/RopePulleyVisual.java index 3930f79e3b..de5dbb3cf0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/pulley/RopePulleyVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/RopePulleyVisual.java @@ -1,16 +1,17 @@ package com.simibubi.create.content.contraptions.pulley; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.render.VirtualRenderHelper; +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.content.processing.burner.ScrollInstance; +import com.simibubi.create.foundation.render.AllInstanceTypes; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; -import dev.engine_room.flywheel.lib.instance.OrientedInstance; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; +import net.createmod.catnip.render.SpriteShiftEntry; public class RopePulleyVisual extends AbstractPulleyVisual { public RopePulleyVisual(VisualizationContext context, PulleyBlockEntity blockEntity, float partialTick) { @@ -19,12 +20,12 @@ public class RopePulleyVisual extends AbstractPulleyVisual { @Override protected Instancer getRopeModel() { - return instancerProvider().instancer(InstanceTypes.TRANSFORMED, VirtualRenderHelper.blockModel(AllBlocks.ROPE.getDefaultState())); + return instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.ROPE)); } @Override protected Instancer getMagnetModel() { - return instancerProvider().instancer(InstanceTypes.TRANSFORMED, VirtualRenderHelper.blockModel(AllBlocks.PULLEY_MAGNET.getDefaultState())); + return instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.PULLEY_MAGNET)); } @Override @@ -33,8 +34,8 @@ public class RopePulleyVisual extends AbstractPulleyVisual { } @Override - protected Instancer getCoilModel() { - return instancerProvider().instancer(InstanceTypes.ORIENTED, Models.partial(AllPartialModels.ROPE_COIL, rotatingAbout)); + protected Instancer getCoilModel() { + return instancerProvider().instancer(AllInstanceTypes.SCROLLING, Models.partial(AllPartialModels.ROPE_COIL)); } @Override @@ -51,4 +52,10 @@ public class RopePulleyVisual extends AbstractPulleyVisual { protected boolean isRunning() { return PulleyRenderer.isPulleyRunning(blockEntity); } + + @Override + protected SpriteShiftEntry getCoilAnimation() { + return AllSpriteShifts.ROPE_PULLEY_COIL; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionEntityRenderer.java index e19c50135b..c0b23ff4e5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionEntityRenderer.java @@ -4,17 +4,16 @@ import org.apache.commons.lang3.tuple.Pair; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.render.BlockEntityRenderHelper; -import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.culling.Frustum; @@ -99,7 +98,7 @@ public class ContraptionEntityRenderer exte context.world = level; StructureTemplate.StructureBlockInfo blockInfo = actor.getLeft(); - MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(blockInfo.state()); + MovementBehaviour movementBehaviour = MovementBehaviour.REGISTRY.get(blockInfo.state()); if (movementBehaviour != null) { if (c.isHiddenInPortal(blockInfo.pos())) continue; diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionMatrices.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionMatrices.java index c7584bdf79..d6faa3984c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionMatrices.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionMatrices.java @@ -4,8 +4,8 @@ import org.joml.Matrix4f; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfo.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfo.java index 1979d80011..d6f2d45835 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfo.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfo.java @@ -3,17 +3,16 @@ package com.simibubi.create.content.contraptions.render; import org.apache.commons.lang3.tuple.Pair; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.contraptions.Contraption.RenderedBlocks; import com.simibubi.create.content.contraptions.ContraptionWorld; -import com.simibubi.create.foundation.render.ShadedBlockSbbBuilder; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.SuperByteBufferCache; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationManager; -import dev.engine_room.flywheel.lib.model.ModelUtil; +import net.createmod.catnip.render.ShadedBlockSbbBuilder; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.render.SuperByteBufferCache; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.renderer.block.ModelBlockRenderer; @@ -71,12 +70,12 @@ public class ContraptionRenderInfo { } public SuperByteBuffer getBuffer(RenderType renderType) { - return CreateClient.BUFFER_CACHE.get(CONTRAPTION, Pair.of(contraption, renderType), () -> buildStructureBuffer(renderType)); + return SuperByteBufferCache.getInstance().get(CONTRAPTION, Pair.of(contraption, renderType), () -> buildStructureBuffer(renderType)); } public void invalidate() { for (RenderType renderType : RenderType.chunkBufferLayers()) { - CreateClient.BUFFER_CACHE.invalidate(CONTRAPTION, Pair.of(contraption, renderType)); + SuperByteBufferCache.getInstance().invalidate(CONTRAPTION, Pair.of(contraption, renderType)); } } @@ -103,7 +102,7 @@ public class ContraptionRenderInfo { } private SuperByteBuffer buildStructureBuffer(RenderType layer) { - BlockRenderDispatcher dispatcher = ModelUtil.VANILLA_RENDERER; + BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer(); ModelBlockRenderer renderer = dispatcher.getModelRenderer(); ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get(); @@ -139,6 +138,6 @@ public class ContraptionRenderInfo { private static class ThreadLocalObjects { public final PoseStack poseStack = new PoseStack(); public final RandomSource random = RandomSource.createNewThreadLocalInstance(); - public final ShadedBlockSbbBuilder sbbBuilder = new ShadedBlockSbbBuilder(); + public final ShadedBlockSbbBuilder sbbBuilder = ShadedBlockSbbBuilder.create(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfoManager.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfoManager.java index 81ab6c4b36..f575ff71ad 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfoManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfoManager.java @@ -1,14 +1,15 @@ package com.simibubi.create.content.contraptions.render; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.foundation.utility.WorldAttached; import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.createmod.catnip.data.WorldAttached; import net.minecraft.client.Minecraft; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionVisual.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionVisual.java index b0d03ed6a3..a1c401e310 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionVisual.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionVisual.java @@ -6,15 +6,15 @@ import java.util.List; import org.apache.commons.lang3.tuple.MutablePair; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.contraptions.Contraption.RenderedBlocks; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.utility.worldWrappers.WrappedBlockAndTintGetter; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import dev.engine_room.flywheel.api.material.CardinalLightingMode; import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.api.visual.BlockEntityVisual; @@ -28,6 +28,8 @@ import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.api.visualization.VisualizerRegistry; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.material.SimpleMaterial; +import dev.engine_room.flywheel.lib.model.ModelUtil; import dev.engine_room.flywheel.lib.model.baked.ForgeMultiBlockModelBuilder; import dev.engine_room.flywheel.lib.task.ForEachPlan; import dev.engine_room.flywheel.lib.task.NestedPlan; @@ -45,6 +47,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + import net.minecraftforge.client.model.data.ModelData; public class ContraptionVisual extends AbstractEntityVisual implements DynamicVisual, TickableVisual, LightUpdatedVisual, ShaderLightVisual { @@ -68,13 +71,22 @@ public class ContraptionVisual extends Abst super(ctx, entity, partialTick); embedding = ctx.createEmbedding(Vec3i.ZERO); - init(partialTick); - } - - protected void init(float partialTick) { setEmbeddingMatrices(partialTick); Contraption contraption = entity.getContraption(); + // The contraption could be null if it wasn't synced (ex. too much data) + if (contraption == null) + return; + + setupModel(contraption); + + setupChildren(partialTick, contraption); + + setupActors(partialTick, contraption); + } + + // Must be called before setup children or setup actors as this creates the render world + private void setupModel(Contraption contraption) { virtualRenderWorld = ContraptionRenderInfo.setupRenderWorld(level, contraption); RenderedBlocks blocks = contraption.getRenderedBlocks(); @@ -86,19 +98,37 @@ public class ContraptionVisual extends Abst }; model = new ForgeMultiBlockModelBuilder(modelWorld, blocks.positions()) - .modelDataLookup(pos -> contraption.modelData.getOrDefault(pos, ModelData.EMPTY)) - .build(); + .modelDataLookup(pos -> contraption.modelData.getOrDefault(pos, ModelData.EMPTY)) + .materialFunc((renderType, aBoolean) -> SimpleMaterial.builderOf(ModelUtil.getMaterial(renderType, aBoolean)) + .cardinalLightingMode(CardinalLightingMode.CHUNK)) + .build(); - structure = embedding.instancerProvider() - .instancer(InstanceTypes.TRANSFORMED, model) - .createInstance(); + var instancer = embedding.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, model); + + // Null in ctor, so we need to create it + // But we can steal it if it already exists + if (structure == null) { + structure = instancer.createInstance(); + } else { + instancer.stealInstance(structure); + } structure.setChanged(); + } + + private void setupChildren(float partialTick, Contraption contraption) { + children.forEach(BlockEntityVisual::delete); + children.clear(); for (BlockEntity be : contraption.getRenderedBEs()) { setupVisualizer(be, partialTick); } + } + private void setupActors(float partialTick, Contraption contraption) { + actors.forEach(ActorVisual::delete); + actors.clear(); for (var actor : contraption.getActors()) { setupActor(actor, partialTick); } @@ -139,7 +169,7 @@ public class ContraptionVisual extends Abst StructureTemplate.StructureBlockInfo blockInfo = actor.getLeft(); - MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(blockInfo.state()); + MovementBehaviour movementBehaviour = MovementBehaviour.REGISTRY.get(blockInfo.state()); if (movementBehaviour == null) { return; } @@ -180,12 +210,33 @@ public class ContraptionVisual extends Abst if (hasMovedBlocks()) { updateLight(partialTick); } + + var contraption = entity.getContraption(); + if (contraption.deferInvalidate) { + setupModel(contraption); + setupChildren(partialTick, contraption); + setupActors(partialTick, contraption); + + contraption.deferInvalidate = false; + } } private void setEmbeddingMatrices(float partialTick) { - double x = Mth.lerp(partialTick, entity.xOld, entity.getX()); - double y = Mth.lerp(partialTick, entity.yOld, entity.getY()); - double z = Mth.lerp(partialTick, entity.zOld, entity.getZ()); + var origin = renderOrigin(); + double x; + double y; + double z; + if (entity.isPrevPosInvalid()) { + // When the visual is created the entity's old position is often zero + x = entity.getX() - origin.getX(); + y = entity.getY() - origin.getY(); + z = entity.getZ() - origin.getZ(); + + } else { + x = Mth.lerp(partialTick, entity.xo, entity.getX()) - origin.getX(); + y = Mth.lerp(partialTick, entity.yo, entity.getY()) - origin.getY(); + z = Mth.lerp(partialTick, entity.zo, entity.getZ()) - origin.getZ(); + } contraptionMatrix.setIdentity(); contraptionMatrix.translate(x, y, z); diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/OrientedContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/render/OrientedContraptionEntityRenderer.java index 5451f9ff18..c185339cf1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/OrientedContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/OrientedContraptionEntityRenderer.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.contraptions.render; -import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.AllTags.AllContraptionTypeTags; import com.simibubi.create.content.contraptions.OrientedContraptionEntity; import net.minecraft.client.renderer.culling.Frustum; @@ -16,9 +16,9 @@ public class OrientedContraptionEntityRenderer extends ContraptionEntityRenderer double cameraZ) { if (!super.shouldRender(entity, frustum, cameraX, cameraY, cameraZ)) return false; - if (entity.getContraption() - .getType() == ContraptionType.MOUNTED && entity.getVehicle() == null) + if (entity.getVehicle() == null && AllContraptionTypeTags.REQUIRES_VEHICLE_FOR_RENDER.matches(entity.getContraption().getType())) return false; + return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ClientMotionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ClientMotionPacket.java index 1b242a084b..7054c907ab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/sync/ClientMotionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/ClientMotionPacket.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.sync; import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.phys.Vec3; diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java deleted file mode 100644 index 2c94225b87..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.content.contraptions.sync; - -import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ContraptionFluidPacket extends SimplePacketBase { - - private int entityId; - private BlockPos localPos; - private FluidStack containedFluid; - - public ContraptionFluidPacket(int entityId, BlockPos localPos, FluidStack containedFluid) { - this.entityId = entityId; - this.localPos = localPos; - this.containedFluid = containedFluid; - } - - public ContraptionFluidPacket(FriendlyByteBuf buffer) { - entityId = buffer.readInt(); - localPos = buffer.readBlockPos(); - containedFluid = FluidStack.readFromPacket(buffer); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityId); - buffer.writeBlockPos(localPos); - containedFluid.writeToPacket(buffer); - } - - @Override - public boolean handle(Context context) { - context.enqueueWork(() -> { - Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); - if (!(entityByID instanceof AbstractContraptionEntity)) - return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - contraptionEntity.getContraption().handleContraptionFluidPacket(localPos, containedFluid); - }); - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionInteractionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionInteractionPacket.java index 8cdda47ac0..5e958d6292 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionInteractionPacket.java @@ -10,6 +10,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.AABB; + import net.minecraftforge.common.ForgeMod; import net.minecraftforge.network.NetworkEvent.Context; @@ -50,16 +51,15 @@ public class ContraptionInteractionPacket extends SimplePacketBase { if (sender == null) return; Entity entityByID = sender.level().getEntity(target); - if (!(entityByID instanceof AbstractContraptionEntity)) + if (!(entityByID instanceof AbstractContraptionEntity contraptionEntity)) return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; AABB bb = contraptionEntity.getBoundingBox(); double boundsExtra = Math.max(bb.getXsize(), bb.getYsize()); double d = sender.getAttribute(ForgeMod.BLOCK_REACH.get()).getValue() + 10 + boundsExtra; if (!sender.hasLineOfSight(entityByID)) d -= 3; d *= d; - if (sender.distanceToSqr(entityByID) > d) + if (sender.distanceToSqr(entityByID) > d) return; if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand)) sender.swing(interactionHand, true); diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionSeatMappingPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionSeatMappingPacket.java index 0e29375603..70be71d3c5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionSeatMappingPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionSeatMappingPacket.java @@ -6,12 +6,13 @@ import java.util.UUID; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.network.NetworkEvent.Context; public class ContraptionSeatMappingPacket extends SimplePacketBase { @@ -23,7 +24,7 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase { public ContraptionSeatMappingPacket(int entityID, Map mapping) { this(entityID, mapping, -1); } - + public ContraptionSeatMappingPacket(int entityID, Map mapping, int dismountedID) { this.entityID = entityID; this.mapping = mapping; @@ -54,10 +55,9 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase { public boolean handle(Context context) { context.enqueueWork(() -> { Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); - if (!(entityByID instanceof AbstractContraptionEntity)) + if (!(entityByID instanceof AbstractContraptionEntity contraptionEntity)) return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - + if (dismountedID != -1) { Entity dismountedByID = Minecraft.getInstance().level.getEntity(dismountedID); if (Minecraft.getInstance().player != dismountedByID) @@ -67,7 +67,7 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase { dismountedByID.getPersistentData() .put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector)); } - + contraptionEntity.getContraption() .setSeatMapping(mapping); }); diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchHandler.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchHandler.java new file mode 100644 index 0000000000..b25a2318d1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchHandler.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.contraptions.wrench; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllKeys; + +import net.createmod.catnip.gui.ScreenOpener; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; + +public class RadialWrenchHandler { + + public static int COOLDOWN = 0; + + public static void clientTick() { + if (COOLDOWN > 0 && !AllKeys.ROTATE_MENU.isPressed()) + COOLDOWN--; + } + + public static void onKeyInput(int key, boolean pressed) { + if (!pressed) + return; + + if (key != AllKeys.ROTATE_MENU.getBoundCode()) + return; + + if (COOLDOWN > 0) + return; + + Minecraft mc = Minecraft.getInstance(); + if (mc.gameMode == null || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) + return; + + LocalPlayer player = mc.player; + if (player == null) + return; + + Level level = player.level(); + + ItemStack heldItem = player.getMainHandItem(); + if (heldItem.getItem() != AllItems.WRENCH.get()) + return; + + HitResult objectMouseOver = mc.hitResult; + if (!(objectMouseOver instanceof BlockHitResult blockHitResult)) + return; + + BlockState state = level.getBlockState(blockHitResult.getBlockPos()); + + RadialWrenchMenu.tryCreateFor(state, blockHitResult.getBlockPos(), level).ifPresent(ScreenOpener::open); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchMenu.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchMenu.java new file mode 100644 index 0000000000..dc776d2266 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchMenu.java @@ -0,0 +1,415 @@ +package com.simibubi.create.content.contraptions.wrench; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.joml.Matrix4f; + +import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllKeys; +import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlock; +import com.simibubi.create.content.redstone.DirectedDirectionalBlock; +import com.simibubi.create.foundation.gui.AllIcons; + +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.UIRenderHelper; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.gui.element.RenderElement; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.theme.Color; +import net.createmod.ponder.enums.PonderGuiTextures; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.HopperBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Property; + +public class RadialWrenchMenu extends AbstractSimiScreen { + + public static final Map, String> VALID_PROPERTIES = new HashMap<>(); + + static { + registerRotationProperty(RotatedPillarKineticBlock.AXIS, "Axis"); + registerRotationProperty(DirectionalKineticBlock.FACING, "Facing"); + registerRotationProperty(HorizontalAxisKineticBlock.HORIZONTAL_AXIS, "Axis"); + registerRotationProperty(HorizontalKineticBlock.HORIZONTAL_FACING, "Facing"); + registerRotationProperty(HopperBlock.FACING, "Facing"); + registerRotationProperty(DirectedDirectionalBlock.TARGET, "Target"); + + registerRotationProperty(SequencedGearshiftBlock.VERTICAL, "Vertical"); + } + + public static final Set BLOCK_BLACKLIST = new HashSet<>(); + + static { + registerBlacklistedBlock(AllBlocks.LARGE_WATER_WHEEL.getId()); + registerBlacklistedBlock(AllBlocks.WATER_WHEEL_STRUCTURAL.getId()); + } + + public static void registerRotationProperty(Property property, String label) { + if (VALID_PROPERTIES.containsKey(property)) + return; + + VALID_PROPERTIES.put(property, label); + } + + public static void registerBlacklistedBlock(ResourceLocation location) { + if (BLOCK_BLACKLIST.contains(location)) + return; + + BLOCK_BLACKLIST.add(location); + } + + private final BlockState state; + private final BlockPos pos; + private final BlockEntity blockEntity; + @Nullable private final Level level; + private final List, String>> propertiesForState; + private final int innerRadius = 50; + private final int outerRadius = 110; + + private int selectedPropertyIndex = 0; + private List allStates = List.of(); + private String propertyLabel = ""; + private int ticksOpen; + private int selectedStateIndex = 0; + + private final RenderElement iconScroll = RenderElement.of(PonderGuiTextures.ICON_SCROLL); + private final RenderElement iconUp = RenderElement.of(AllIcons.I_PRIORITY_HIGH); + private final RenderElement iconDown = RenderElement.of(AllIcons.I_PRIORITY_LOW); + + public static Optional tryCreateFor(BlockState state, BlockPos pos, @Nullable Level level) { + if (BLOCK_BLACKLIST.contains(CatnipServices.REGISTRIES.getKeyOrThrow(state.getBlock()))) + return Optional.empty(); + + var propertiesForState = VALID_PROPERTIES.entrySet().stream().filter(entry -> state.hasProperty(entry.getKey())).toList(); + + if (propertiesForState.isEmpty()) + return Optional.empty(); + + return Optional.of(new RadialWrenchMenu(state, pos, level, propertiesForState)); + } + + private RadialWrenchMenu(BlockState state, BlockPos pos, @Nullable Level level, List, String>> properties) { + this.state = state; + this.pos = pos; + this.level = level; + this.blockEntity = level.getBlockEntity(pos); + this.propertiesForState = properties; + + initForSelectedProperty(); + } + + private void initForSelectedProperty() { + Map.Entry, String> entry = propertiesForState.get(selectedPropertyIndex); + + allStates = new ArrayList<>(); + //allStates.add(state); + cycleAllPropertyValues(state, entry.getKey(), allStates); + + propertyLabel = entry.getValue(); + } + + private void cycleAllPropertyValues(BlockState state, Property property, List states) { + Optional> first = property.getPossibleValues().stream().findFirst(); + if (first.isEmpty()) + return; + + int offset = 0; + int safety = 100; + while (safety-- > 0) { + if (state.getValue(property).equals(first.get())) { + offset = 99 - safety; + break; + } + + state = state.cycle(property); + } + + safety = 100; + while (safety-- > 0) { + if (states.contains(state)) + break; + + states.add(state); + + state = state.cycle(property); + } + + offset = Mth.clamp(offset, 0, states.size() - 1); + selectedStateIndex = (offset == 0) ? 0 : (states.size() - offset); + } + + @Override + public void tick() { + ticksOpen++; + if (!level.getBlockState(pos).is(state.getBlock())) + Minecraft.getInstance().setScreen(null); + super.tick(); + } + + @Override + protected void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + int x = this.width / 2; + int y = this.height / 2; + + PoseStack ms = graphics.pose(); + + ms.pushPose(); + ms.translate(x, y, 0); + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + + int mouseOffsetX = mouseX - this.width / 2; + int mouseOffsetY = mouseY - this.height / 2; + + if (Mth.length(mouseOffsetX, mouseOffsetY) > innerRadius - 5) { + double theta = Mth.atan2(mouseOffsetX, mouseOffsetY); + + float sectorSize = 360f / allStates.size(); + + selectedStateIndex = (int) Math.floor( + ((-AngleHelper.deg(Mth.atan2(mouseOffsetX, mouseOffsetY)) + 180 + sectorSize / 2) % 360) + / sectorSize + ); + + renderDirectionIndicator(graphics, theta); + } + + renderRadialSectors(graphics); + + UIRenderHelper.streak(graphics, 0, 0, 0, 32, 65, Color.BLACK.setAlpha(0.8f)); + UIRenderHelper.streak(graphics, 180, 0, 0, 32, 65, Color.BLACK.setAlpha(0.8f)); + + if (selectedPropertyIndex > 0) { + iconScroll.at(-14, -46).render(graphics); + iconUp.at(-1, -46).render(graphics); + graphics.drawCenteredString(font, propertiesForState.get(selectedPropertyIndex - 1).getValue(), 0, -30, UIRenderHelper.COLOR_TEXT.getFirst().getRGB()); + } + + if (selectedPropertyIndex < propertiesForState.size() - 1) { + iconScroll.at(-14, 30).render(graphics); + iconDown.at(-1, 30).render(graphics); + graphics.drawCenteredString(font, propertiesForState.get(selectedPropertyIndex + 1).getValue(), 0, 22, UIRenderHelper.COLOR_TEXT.getFirst().getRGB()); + } + + graphics.drawCenteredString(font, "Currently", 0, -13, UIRenderHelper.COLOR_TEXT.getFirst().getRGB()); + graphics.drawCenteredString(font, "Changing:", 0, -3, UIRenderHelper.COLOR_TEXT.getFirst().getRGB()); + graphics.drawCenteredString(font, propertyLabel, 0, 7, UIRenderHelper.COLOR_TEXT.getFirst().getRGB()); + + ms.popPose(); + + } + + private void renderRadialSectors(GuiGraphics graphics) { + int sectors = allStates.size(); + if (sectors < 2) + return; + + PoseStack poseStack = graphics.pose(); + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) + return; + + float sectorAngle = 360f / sectors; + int sectorWidth = outerRadius - innerRadius; + + poseStack.pushPose(); + + for (int i = 0; i < sectors; i++) { + Color innerColor = Color.WHITE.setAlpha(0.05f); + Color outerColor = Color.WHITE.setAlpha(0.3f); + BlockState blockState = allStates.get(i); + Property property = propertiesForState.get(selectedPropertyIndex).getKey(); + + poseStack.pushPose(); + + if (i == selectedStateIndex) { + innerColor.mixWith(new Color(0.8f, 0.8f, 0.2f, 0.2f), 0.5f); + outerColor.mixWith(new Color(0.8f, 0.8f, 0.2f, 0.6f), 0.5f); + + UIRenderHelper.drawRadialSector(graphics, outerRadius + 2, outerRadius + 3, -(sectorAngle / 2 + 90), sectorAngle, outerColor, outerColor); + } + + UIRenderHelper.drawRadialSector(graphics, innerRadius, outerRadius, -(sectorAngle / 2 + 90), sectorAngle, innerColor, outerColor); + Color c = innerColor.copy().setAlpha(0.5f); + UIRenderHelper.drawRadialSector(graphics, innerRadius - 3, innerRadius - 2, -(sectorAngle / 2 + 90), sectorAngle, c, c); + + TransformStack.of(poseStack) + .translateY(-(sectorWidth / 2f + innerRadius)) + .rotateZDegrees(-i * sectorAngle); + + poseStack.translate(0, 0, 100); + + try { + GuiGameElement.of(blockState, blockEntity) + .rotateBlock(player.getXRot(), player.getYRot() + 180, 0f) + .scale(24) + .at(-12, 12) + .render(graphics); + } catch (Exception e) { + Create.LOGGER.warn("Failed to render blockstate in RadialWrenchMenu", e); + allStates.remove(i); + selectedStateIndex = 0; + return; + } + + poseStack.translate(0, 0, 50); + + if (i == selectedStateIndex) { + graphics.drawCenteredString(font, blockState.getValue(property).toString(), 0, 15, UIRenderHelper.COLOR_TEXT.getFirst().getRGB()); + } + + poseStack.popPose(); + + poseStack.pushPose(); + + TransformStack.of(poseStack) + .rotateZDegrees(sectorAngle / 2); + + poseStack.translate(0, -innerRadius - 20, 10); + + UIRenderHelper.angledGradient(graphics, -90, 0, 0, 0.5f, sectorWidth - 10, Color.WHITE.setAlpha(0.5f), Color.WHITE.setAlpha(0.15f)); + UIRenderHelper.angledGradient(graphics, 90, 0, 0, 0.5f, 25 , Color.WHITE.setAlpha(0.5f), Color.WHITE.setAlpha(0.15f)); + poseStack.popPose(); + + TransformStack.of(poseStack) + .rotateZDegrees(sectorAngle); + } + + poseStack.popPose(); + + } + + private void renderDirectionIndicator(GuiGraphics graphics, double theta) { + PoseStack poseStack = graphics.pose(); + + float r = 0.8f; + float g = 0.8f; + float b = 0.8f; + + poseStack.pushPose(); + TransformStack.of(poseStack) + .rotateZ((float) -theta) + .translateY(innerRadius + 3) + .translateZ(15); + + RenderSystem.setShader(GameRenderer::getPositionColorShader); + + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder bufferbuilder = tesselator.getBuilder(); + bufferbuilder.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); + + Matrix4f mat = poseStack.last().pose(); + + bufferbuilder.vertex(mat, 0, 0, 0).color(r, g, b, 0.75f).endVertex(); + + bufferbuilder.vertex(mat, 5, -5, 0).color(r, g, b, 0.4f).endVertex(); + bufferbuilder.vertex(mat, 3, -4.5f, 0).color(r, g, b, 0.4f).endVertex(); + bufferbuilder.vertex(mat, 0, -4.2f, 0).color(r, g, b, 0.4f).endVertex(); + bufferbuilder.vertex(mat, -3, -4.5f, 0).color(r, g, b, 0.4f).endVertex(); + bufferbuilder.vertex(mat, -5, -5, 0).color(r, g, b, 0.4f).endVertex(); + + tesselator.end(); + + poseStack.popPose(); + } + + private void submitChange() { + BlockState selectedState = allStates.get(selectedStateIndex); + if (selectedState != state) { + AllPackets.getChannel().sendToServer(new RadialWrenchMenuSubmitPacket(pos, selectedState)); + } + + onClose(); + } + + @Override + public void renderBackground(GuiGraphics graphics) { + Color color = BACKGROUND_COLOR + .scaleAlpha(Math.min(1, (ticksOpen + AnimationTickHolder.getPartialTicks()) / 20f)); + + graphics.fillGradient(0, 0, this.width, this.height, color.getRGB(), color.getRGB()); + } + + @Override + public boolean keyReleased(int code, int scanCode, int modifiers) { + InputConstants.Key mouseKey = InputConstants.getKey(code, scanCode); + if (AllKeys.ROTATE_MENU.getKeybind().isActiveAndMatches(mouseKey)) { + submitChange(); + return true; + } + return super.keyReleased(code, scanCode, modifiers); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + if (pButton == InputConstants.MOUSE_BUTTON_LEFT) { + submitChange(); + return true; + } else if (pButton == InputConstants.MOUSE_BUTTON_RIGHT) { + onClose(); + return true; + } + + return super.mouseClicked(pMouseX, pMouseY, pButton); + } + + @Override + public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) { + if (propertiesForState.size() < 2) + return super.mouseScrolled(pMouseX, pMouseY, pDelta); + + int indexDelta = (int) Math.round(Math.signum(-pDelta)); + + int newIndex = selectedPropertyIndex + indexDelta; + if (newIndex < 0) + return false; + + if (newIndex >= propertiesForState.size()) + return false; + + selectedPropertyIndex = newIndex; + initForSelectedProperty(); + + return true; + } + + @Override + public void removed() { + RadialWrenchHandler.COOLDOWN = 2; + + super.removed(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchMenuSubmitPacket.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchMenuSubmitPacket.java new file mode 100644 index 0000000000..3655256d4a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/RadialWrenchMenuSubmitPacket.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.contraptions.wrench; + +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.registries.GameData; + +public class RadialWrenchMenuSubmitPacket extends SimplePacketBase { + + private final BlockPos blockPos; + private final BlockState newState; + + public RadialWrenchMenuSubmitPacket(BlockPos blockPos, BlockState newState) { + this.blockPos = blockPos; + this.newState = newState; + } + + public RadialWrenchMenuSubmitPacket(FriendlyByteBuf buffer) { + this.blockPos = buffer.readBlockPos(); + this.newState = buffer.readById(GameData.getBlockStateIDMap()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(blockPos); + buffer.writeId(GameData.getBlockStateIDMap(), newState); + } + + @Override + public boolean handle(NetworkEvent.Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + Level level = player.level(); + + if (!level.getBlockState(blockPos).is(newState.getBlock())) + return; + + BlockState updatedState = Block.updateFromNeighbourShapes(newState, level, blockPos); + KineticBlockEntity.switchToBlockState(level, blockPos, updatedState); + + IWrenchable.playRotateSound(level, blockPos); + }); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/package-info.java new file mode 100644 index 0000000000..24b04c90e1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/package-info.java @@ -0,0 +1,9 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@FieldsAreNonnullByDefault +package com.simibubi.create.content.contraptions.wrench; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.FieldsAreNonnullByDefault; +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/decoration/CardboardBlock.java b/src/main/java/com/simibubi/create/content/decoration/CardboardBlock.java new file mode 100644 index 0000000000..1f47575e5f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/CardboardBlock.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.decoration; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.Property; + +public class CardboardBlock extends Block { + + public static final Property HORIZONTAL_AXIS = BlockStateProperties.HORIZONTAL_AXIS; + + public CardboardBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return this.defaultBlockState() + .setValue(HORIZONTAL_AXIS, pContext.getHorizontalDirection() + .getAxis()); + } + + @Override + public int getFireSpreadSpeed(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 100; + } + + @Override + public int getFlammability(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { + return 20; + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(HORIZONTAL_AXIS)); + } + + @Override + public BlockState rotate(BlockState state, Rotation rot) { + return state.setValue(HORIZONTAL_AXIS, + rot.rotate(Direction.get(AxisDirection.POSITIVE, state.getValue(HORIZONTAL_AXIS))) + .getAxis()); + } + + @Override + public BlockState mirror(BlockState state, Mirror mirrorIn) { + return state; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/CardboardBlockItem.java b/src/main/java/com/simibubi/create/content/decoration/CardboardBlockItem.java new file mode 100644 index 0000000000..bcad7baa70 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/CardboardBlockItem.java @@ -0,0 +1,21 @@ +package com.simibubi.create.content.decoration; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.block.Block; + +public class CardboardBlockItem extends BlockItem { + + public CardboardBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public int getBurnTime(ItemStack itemStack, @Nullable RecipeType recipeType) { + return 4000; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/MetalLadderBlock.java b/src/main/java/com/simibubi/create/content/decoration/MetalLadderBlock.java index 75db82350d..63395a7642 100644 --- a/src/main/java/com/simibubi/create/content/decoration/MetalLadderBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/MetalLadderBlock.java @@ -2,26 +2,34 @@ package com.simibubi.create.content.decoration; import java.util.function.Predicate; +import com.simibubi.create.AllShapes; import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem; import com.simibubi.create.content.equipment.wrench.IWrenchable; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LadderBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.ForgeMod; @@ -42,10 +50,33 @@ public class MetalLadderBlock extends LadderBlock implements IWrenchable { @Override @OnlyIn(Dist.CLIENT) + @SuppressWarnings("deprecation") public boolean skipRendering(BlockState pState, BlockState pAdjacentBlockState, Direction pDirection) { + if (pDirection != null && pDirection.getAxis() + .isHorizontal()) + return pAdjacentBlockState.isAir() || !pAdjacentBlockState.blocksMotion(); return pDirection == Direction.UP && pAdjacentBlockState.getBlock() instanceof LadderBlock; } + @Override + public VoxelShape getOcclusionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { + return AllShapes.SIX_VOXEL_POLE.get(Axis.Y); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, + BlockPos pCurrentPos, BlockPos pFacingPos) { + if (!pState.canSurvive(pLevel, pCurrentPos)) + return Blocks.AIR.defaultBlockState(); + return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } + + @Override + public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { + return super.canSurvive(pState, pLevel, pPos) || pLevel.getBlockState(pPos.relative(Direction.UP)) + .is(this); + } + @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult ray) { diff --git a/src/main/java/com/simibubi/create/content/decoration/RoofBlockCTBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/RoofBlockCTBehaviour.java new file mode 100644 index 0000000000..bd9b39a347 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/RoofBlockCTBehaviour.java @@ -0,0 +1,144 @@ +package com.simibubi.create.content.decoration; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.foundation.block.connected.AllCTTypes; +import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; +import com.simibubi.create.foundation.block.connected.CTType; +import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; + +import net.createmod.catnip.data.Iterate; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.Mth; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.SlabBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.StairBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Half; +import net.minecraft.world.level.block.state.properties.SlabType; +import net.minecraft.world.level.block.state.properties.StairsShape; + +public class RoofBlockCTBehaviour extends ConnectedTextureBehaviour.Base { + + private CTSpriteShiftEntry shift; + + public RoofBlockCTBehaviour(CTSpriteShiftEntry shift) { + this.shift = shift; + } + + @Override + public @Nullable CTSpriteShiftEntry getShift(BlockState state, Direction direction, + @Nullable TextureAtlasSprite sprite) { + if (direction == Direction.UP) + return shift; + return null; + } + + @Override + public boolean buildContextForOccludedDirections() { + return true; + } + + @Override + public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face, + ContextRequirement requirement) { + + if (isUprightStair(state)) + return getStairMapping(state); + + return super.buildContext(reader, pos, state, face, requirement); + } + + @Override + public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, + BlockPos otherPos, Direction face, Direction primaryOffset, Direction secondaryOffset) { + + if (connects(reader, pos, state, other) + || connectsHigh(reader, pos, state, other, reader.getBlockState(otherPos.above()))) + return true; + if (primaryOffset != null && secondaryOffset != null) + return false; + + for (boolean p : Iterate.trueAndFalse) { + Direction offset = p ? primaryOffset : secondaryOffset; + if (offset == null) + continue; + if (offset.getAxis() + .isVertical()) + continue; + + if (connectsHigh(reader, pos, state, reader.getBlockState(pos.relative(offset.getClockWise())), + reader.getBlockState(pos.relative(offset.getClockWise()) + .above())) + || connectsHigh(reader, pos, state, reader.getBlockState(pos.relative(offset.getCounterClockWise())), + reader.getBlockState(pos.relative(offset.getCounterClockWise()) + .above()))) + return true; + } + + return false; + } + + public boolean isUprightStair(BlockState state) { + return state.hasProperty(StairBlock.SHAPE) && state.getOptionalValue(StairBlock.HALF) + .orElse(Half.TOP) == Half.BOTTOM; + } + + public CTContext getStairMapping(BlockState state) { + CTContext context = new CTContext(); + StairsShape shape = state.getValue(StairBlock.SHAPE); + Direction facing = state.getValue(StairBlock.FACING); + + if (shape == StairsShape.OUTER_LEFT) + facing = facing.getCounterClockWise(); + if (shape == StairsShape.INNER_LEFT) + facing = facing.getCounterClockWise(); + + int type = shape == StairsShape.STRAIGHT ? 0 + : (shape == StairsShape.INNER_LEFT || shape == StairsShape.INNER_RIGHT) ? 1 : 2; + int rot = facing.get2DDataValue(); + context.up = type >= 2; + context.right = type % 2 == 1; + context.left = rot >= 2; + context.down = rot % 2 == 1; + return context; + } + + protected boolean connects(BlockAndTintGetter reader, BlockPos pos, BlockState state, BlockState other) { + double top = state.getCollisionShape(reader, pos) + .max(Axis.Y); + double topOther = other.getSoundType() != SoundType.COPPER ? 0 + : other.getCollisionShape(reader, pos) + .max(Axis.Y); + return Mth.equal(top, topOther); + } + + protected boolean connectsHigh(BlockAndTintGetter reader, BlockPos pos, BlockState state, BlockState other, + BlockState aboveOther) { + if (state.getBlock() instanceof SlabBlock && other.getBlock() instanceof SlabBlock) + if (state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM && other.getValue(SlabBlock.TYPE) != SlabType.BOTTOM) + return true; + + if (state.getBlock() instanceof SlabBlock && state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM) { + double top = state.getCollisionShape(reader, pos) + .max(Axis.Y); + double topOther = other.getCollisionShape(reader, pos) + .max(Axis.Y); + return !Mth.equal(top, topOther) && topOther > top; + } + + double topAboveOther = aboveOther.getCollisionShape(reader, pos) + .max(Axis.Y); + return topAboveOther > 0; + } + + @Override + public @Nullable CTType getDataType(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction direction) { + return isUprightStair(state) ? AllCTTypes.ROOF_STAIR : AllCTTypes.ROOF; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/TrainTrapdoorBlock.java b/src/main/java/com/simibubi/create/content/decoration/TrainTrapdoorBlock.java index a79b762ce2..a0d34b8068 100644 --- a/src/main/java/com/simibubi/create/content/decoration/TrainTrapdoorBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/TrainTrapdoorBlock.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.decoration; import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; import com.simibubi.create.content.equipment.wrench.IWrenchable; - import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlock.java b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlock.java index 52071130bb..94be0e067e 100644 --- a/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlock.java @@ -8,8 +8,8 @@ import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBlock; import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.util.StringRepresentable; diff --git a/src/main/java/com/simibubi/create/content/decoration/bracket/BracketedBlockEntityBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketedBlockEntityBehaviour.java index c2f358eaea..5a501c5bd0 100644 --- a/src/main/java/com/simibubi/create/content/decoration/bracket/BracketedBlockEntityBehaviour.java +++ b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketedBlockEntityBehaviour.java @@ -9,8 +9,8 @@ import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.world.level.Level; @@ -85,7 +85,7 @@ public class BracketedBlockEntityBehaviour extends BlockEntityBehaviour { public boolean isBracketPresent() { return bracket != null; } - + public boolean isBracketValid(BlockState bracketState) { return bracketState.getBlock() instanceof BracketBlock; } diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBarsModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBarsModel.java index bec5bc5cb4..54a93e0edb 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBarsModel.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBarsModel.java @@ -3,9 +3,9 @@ package com.simibubi.create.content.decoration.copycat; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.model.BakedQuadHelper; +import net.createmod.catnip.render.SpriteShiftEntry; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -14,6 +14,7 @@ import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.client.model.data.ModelData; public class CopycatBarsModel extends CopycatModel { @@ -26,10 +27,10 @@ public class CopycatBarsModel extends CopycatModel { public boolean useAmbientOcclusion() { return false; } - + @Override protected List getCroppedQuads(BlockState state, Direction side, RandomSource rand, BlockState material, - ModelData wrappedData, RenderType renderType) { + ModelData wrappedData, RenderType renderType) { BakedModel model = getModelOf(material); List superQuads = originalModel.getQuads(state, side, rand, wrappedData, renderType); TextureAtlasSprite targetSprite = model.getParticleIcon(wrappedData); @@ -39,8 +40,7 @@ public class CopycatBarsModel extends CopycatModel { if (side != null && (vertical || side.getAxis() == Axis.Y)) { List templateQuads = model.getQuads(material, null, rand, wrappedData, renderType); - for (int i = 0; i < templateQuads.size(); i++) { - BakedQuad quad = templateQuads.get(i); + for (BakedQuad quad : templateQuads) { if (quad.getDirection() != Direction.UP) continue; targetSprite = quad.getSprite(); @@ -53,8 +53,7 @@ public class CopycatBarsModel extends CopycatModel { List quads = new ArrayList<>(); - for (int i = 0; i < superQuads.size(); i++) { - BakedQuad quad = superQuads.get(i); + for (BakedQuad quad : superQuads) { TextureAtlasSprite original = quad.getSprite(); BakedQuad newQuad = BakedQuadHelper.clone(quad); int[] vertexData = newQuad.getVertices(); diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlockEntity.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlockEntity.java index 98d306920a..36136044d3 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlockEntity.java @@ -3,31 +3,33 @@ package com.simibubi.create.content.decoration.copycat; import java.util.List; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; +import com.simibubi.create.api.schematic.nbt.PartialSafeNBT; +import com.simibubi.create.api.schematic.requirement.SpecialBlockEntityItemRequirement; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.redstone.RoseQuartzLampBlock; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockEntityItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.IPartialSafeNBT; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.items.ItemHandlerHelper; public class CopycatBlockEntity extends SmartBlockEntity - implements ISpecialBlockEntityItemRequirement, ITransformableBlockEntity, IPartialSafeNBT { + implements SpecialBlockEntityItemRequirement, TransformableBlockEntity, PartialSafeNBT { private BlockState material; private ItemStack consumedItem; @@ -127,7 +129,7 @@ public class CopycatBlockEntity extends SmartBlockEntity } @Override - public void transform(StructureTransform transform) { + public void transform(BlockEntity be, StructureTransform transform) { material = transform.apply(material); notifyUpdate(); } @@ -167,19 +169,19 @@ public class CopycatBlockEntity extends SmartBlockEntity @Override public void writeSafe(CompoundTag tag) { super.writeSafe(tag); - + ItemStack stackWithoutNBT = consumedItem.copy(); stackWithoutNBT.setTag(null); - + write(tag, stackWithoutNBT, material); } - + @Override protected void write(CompoundTag tag, boolean clientPacket) { super.write(tag, clientPacket); write(tag, consumedItem, material); } - + protected void write(CompoundTag tag, ItemStack stack, BlockState material) { tag.put("Item", stack.serializeNBT()); tag.put("Material", NbtUtils.writeBlockState(material)); diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatModel.java index 3826cc1b5d..6a6e22fa7a 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatModel.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatModel.java @@ -8,8 +8,8 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.model.BakedModelWrapperWithData; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -22,6 +22,7 @@ import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.client.model.data.ModelData.Builder; import net.minecraftforge.client.model.data.ModelProperty; @@ -80,6 +81,12 @@ public abstract class CopycatModel extends BakedModelWrapperWithData { occlusionData.occlude(face); } } + + @Override + public List getQuads(BlockState state, Direction side, RandomSource rand) { + return getCroppedQuads(state, side, rand, getMaterial(ModelData.EMPTY), ModelData.EMPTY, + RenderType.cutoutMipped()); + } @Override public List getQuads(BlockState state, Direction side, RandomSource rand, ModelData data, RenderType renderType) { diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelBlock.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelBlock.java index 06106975c6..94898232a7 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelBlock.java @@ -5,10 +5,10 @@ import java.util.function.Predicate; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -54,7 +54,7 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock { @Override public BlockState prepareMaterial(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer, - InteractionHand pHand, BlockHitResult pHit, BlockState material) { + InteractionHand pHand, BlockHitResult pHit, BlockState material) { if (!CopycatSpecialCases.isTrapdoorMaterial(material)) return super.prepareMaterial(pLevel, pPos, pState, pPlayer, pHand, pHit, material); @@ -73,7 +73,7 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock { @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult ray) { + BlockHitResult ray) { if (!player.isShiftKeyDown() && player.mayBuild()) { ItemStack heldItem = player.getItemInHand(hand); @@ -90,7 +90,7 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock { @Override public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face, - BlockPos fromPos, BlockPos toPos) { + BlockPos fromPos, BlockPos toPos) { Direction facing = state.getValue(FACING); BlockState toState = reader.getBlockState(toPos); @@ -103,12 +103,12 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock { return facing == toState.getValue(FACING) .getOpposite() && !(coord != 0 && coord == facing.getAxisDirection() - .getStep()); + .getStep()); } @Override public boolean canConnectTexturesToward(BlockAndTintGetter reader, BlockPos fromPos, BlockPos toPos, - BlockState state) { + BlockState state) { Direction facing = state.getValue(FACING); BlockState toState = reader.getBlockState(toPos); @@ -164,11 +164,6 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock { return false; } - @Override - public boolean skipRendering(BlockState state, BlockState adjacentState, Direction direction) { - return state.equals(adjacentState) && direction.getAxis().isHorizontal(); - } - @Override public boolean supportsExternalFaceHiding(BlockState state) { return true; @@ -176,7 +171,7 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock { @Override public boolean hidesNeighborFace(BlockGetter level, BlockPos pos, BlockState state, BlockState neighborState, - Direction dir) { + Direction dir) { if (state.is(this) == neighborState.is(this)) { if (CopycatSpecialCases.isBarsMaterial(getMaterial(level, pos)) && CopycatSpecialCases.isBarsMaterial(getMaterial(level, pos.relative(dir)))) @@ -225,7 +220,7 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock { @Override public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, - BlockHitResult ray) { + BlockHitResult ray) { List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), state.getValue(FACING) .getAxis(), diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java index a6462c00f6..393d2aebb7 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java @@ -6,8 +6,8 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.model.BakedModelHelper; import com.simibubi.create.foundation.model.BakedQuadHelper; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.BlockRenderDispatcher; @@ -20,6 +20,7 @@ import net.minecraft.world.level.block.DirectionalBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.client.model.data.ModelData; public class CopycatPanelModel extends CopycatModel { diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepBlock.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepBlock.java index ac506465c3..3f78fe6cd6 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepBlock.java @@ -2,15 +2,16 @@ package com.simibubi.create.content.decoration.copycat; import java.util.function.Predicate; +import org.jetbrains.annotations.NotNull; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.kinetics.steamEngine.PoweredShaftBlock; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.foundation.placement.PoleHelper; -import com.simibubi.create.foundation.utility.VoxelShaper; +import net.createmod.catnip.math.VoxelShaper; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -37,8 +38,6 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -import org.jetbrains.annotations.NotNull; - public class CopycatStepBlock extends WaterloggedCopycatBlock { public static final EnumProperty HALF = BlockStateProperties.HALF; diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepModel.java index 673c27cf30..b1dc784832 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepModel.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepModel.java @@ -5,8 +5,8 @@ import java.util.List; import com.simibubi.create.foundation.model.BakedModelHelper; import com.simibubi.create.foundation.model.BakedQuadHelper; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; @@ -17,6 +17,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.client.model.data.ModelData; public class CopycatStepModel extends CopycatModel { diff --git a/src/main/java/com/simibubi/create/content/decoration/encasing/CasingBlock.java b/src/main/java/com/simibubi/create/content/decoration/encasing/CasingBlock.java index 2868ee2201..70b3d6b00a 100644 --- a/src/main/java/com/simibubi/create/content/decoration/encasing/CasingBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/CasingBlock.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.decoration.encasing; import com.simibubi.create.content.equipment.wrench.IWrenchable; - import net.minecraft.world.InteractionResult; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.block.Block; diff --git a/src/main/java/com/simibubi/create/content/decoration/encasing/EncasingRegistry.java b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasingRegistry.java index 7021664c52..16945f0934 100644 --- a/src/main/java/com/simibubi/create/content/decoration/encasing/EncasingRegistry.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasingRegistry.java @@ -1,5 +1,10 @@ package com.simibubi.create.content.decoration.encasing; +import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.level.block.Block; + import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -7,12 +12,6 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; -import com.tterrag.registrate.builders.BlockBuilder; -import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; - -import net.minecraft.core.registries.Registries; -import net.minecraft.world.level.block.Block; - public class EncasingRegistry { private static final Map> ENCASED_VARIANTS = new HashMap<>(); diff --git a/src/main/java/com/simibubi/create/content/decoration/girder/ConnectedGirderModel.java b/src/main/java/com/simibubi/create/content/decoration/girder/ConnectedGirderModel.java index b8878f6b1f..874e20ea16 100644 --- a/src/main/java/com/simibubi/create/content/decoration/girder/ConnectedGirderModel.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/ConnectedGirderModel.java @@ -6,8 +6,8 @@ import java.util.List; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.block.connected.CTModel; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; @@ -16,6 +16,7 @@ import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.client.model.data.ModelData.Builder; import net.minecraftforge.client.model.data.ModelProperty; diff --git a/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlock.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlock.java index 134258d2b4..07924a12db 100644 --- a/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlock.java @@ -18,10 +18,10 @@ import com.simibubi.create.content.trains.display.FlapDisplayBlock; import com.simibubi.create.content.trains.track.TrackBlock; import com.simibubi.create.content.trains.track.TrackShape; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlockStateGenerator.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlockStateGenerator.java index 72f3a181ca..f932ff4280 100644 --- a/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlockStateGenerator.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlockStateGenerator.java @@ -1,12 +1,13 @@ package com.simibubi.create.content.decoration.girder; import com.simibubi.create.foundation.data.AssetLookup; -import com.simibubi.create.foundation.utility.Iterate; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction.Axis; import net.minecraft.world.level.block.Block; + import net.minecraftforge.client.model.generators.MultiPartBlockStateBuilder; public class GirderBlockStateGenerator { diff --git a/src/main/java/com/simibubi/create/content/decoration/girder/GirderEncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderEncasedShaftBlock.java index 4a46cae8f7..6f9bd783ae 100644 --- a/src/main/java/com/simibubi/create/content/decoration/girder/GirderEncasedShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderEncasedShaftBlock.java @@ -5,10 +5,10 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.block.IBE; @@ -37,7 +37,7 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class GirderEncasedShaftBlock extends HorizontalAxisKineticBlock - implements IBE, SimpleWaterloggedBlock, IWrenchable, ISpecialBlockItemRequirement { + implements IBE, SimpleWaterloggedBlock, IWrenchable, SpecialBlockItemRequirement { public static final BooleanProperty TOP = GirderBlock.TOP; public static final BooleanProperty BOTTOM = GirderBlock.BOTTOM; diff --git a/src/main/java/com/simibubi/create/content/decoration/girder/GirderPlacementHelper.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderPlacementHelper.java index 21f5d0419f..7b1d00e05a 100644 --- a/src/main/java/com/simibubi/create/content/decoration/girder/GirderPlacementHelper.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderPlacementHelper.java @@ -6,10 +6,10 @@ import java.util.function.Predicate; import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -20,6 +20,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; + import net.minecraftforge.common.ForgeMod; public class GirderPlacementHelper implements IPlacementHelper { diff --git a/src/main/java/com/simibubi/create/content/decoration/girder/GirderWrenchBehavior.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderWrenchBehavior.java index e2716556bb..459ef04996 100644 --- a/src/main/java/com/simibubi/create/content/decoration/girder/GirderWrenchBehavior.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderWrenchBehavior.java @@ -8,13 +8,13 @@ import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; @@ -28,6 +28,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -91,7 +92,7 @@ public class GirderWrenchBehavior { .getNormal()) .scale(0.1 * normalMultiplier)); - CreateClient.OUTLINER.showAABB("girderWrench", new AABB(corner1, corner2)) + Outliner.getInstance().showAABB("girderWrench", new AABB(corner1, corner2)) .lineWidth(1 / 32f) .colored(new Color(127, 127, 127)); } diff --git a/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteBlocks.java b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteBlocks.java index 257603ed55..bd5ddb9465 100644 --- a/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteBlocks.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteBlocks.java @@ -8,12 +8,14 @@ import static com.simibubi.create.foundation.data.WindowGen.framedGlassPane; import static com.simibubi.create.foundation.data.WindowGen.woodenWindowBlock; import static com.simibubi.create.foundation.data.WindowGen.woodenWindowPane; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllCreativeModeTabs; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.Create; import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour; import com.simibubi.create.foundation.block.connected.SimpleCTBehaviour; import com.simibubi.create.foundation.data.BlockStateGen; +import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.WindowGen; import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.entry.BlockEntry; @@ -77,9 +79,18 @@ public class AllPaletteBlocks { MANGROVE_WINDOW = woodenWindowBlock(WoodType.MANGROVE, Blocks.MANGROVE_PLANKS), CRIMSON_WINDOW = woodenWindowBlock(WoodType.CRIMSON, Blocks.CRIMSON_PLANKS), WARPED_WINDOW = woodenWindowBlock(WoodType.WARPED, Blocks.WARPED_PLANKS), + CHERRY_WINDOW = woodenWindowBlock(WoodType.CHERRY, Blocks.CHERRY_PLANKS), + BAMBOO_WINDOW = woodenWindowBlock(WoodType.BAMBOO, Blocks.BAMBOO_PLANKS), ORNATE_IRON_WINDOW = customWindowBlock("ornate_iron_window", () -> Items.IRON_NUGGET, () -> AllSpriteShifts.ORNATE_IRON_WINDOW, - () -> RenderType::cutout, false, () -> MapColor.TERRACOTTA_LIGHT_GRAY); + () -> RenderType::cutout, false, () -> MapColor.TERRACOTTA_LIGHT_GRAY), + INDUSTRIAL_IRON_WINDOW = customWindowBlock("industrial_iron_window", AllBlocks.INDUSTRIAL_IRON_BLOCK, + () -> AllSpriteShifts.INDUSTRIAL_IRON_WINDOW, () -> RenderType::cutout, false, () -> MapColor.COLOR_GRAY), + WEATHERED_IRON_WINDOW = WindowGen + .randomisedWindowBlock("weathered_iron_window", AllBlocks.WEATHERED_IRON_BLOCK, + () -> RenderType::translucent, true, () -> MapColor.TERRACOTTA_LIGHT_GRAY) + .onRegister(CreateRegistrate.connectedTextures(() -> new WeatheredIronWindowCTBehaviour())) + .register(); public static final BlockEntry OAK_WINDOW_PANE = woodenWindowPane(WoodType.OAK, OAK_WINDOW), @@ -91,8 +102,16 @@ public class AllPaletteBlocks { MANGROVE_WINDOW_PANE = woodenWindowPane(WoodType.MANGROVE, MANGROVE_WINDOW), CRIMSON_WINDOW_PANE = woodenWindowPane(WoodType.CRIMSON, CRIMSON_WINDOW), WARPED_WINDOW_PANE = woodenWindowPane(WoodType.WARPED, WARPED_WINDOW), + CHERRY_WINDOW_PANE = woodenWindowPane(WoodType.CHERRY, CHERRY_WINDOW), + BAMBOO_WINDOW_PANE = woodenWindowPane(WoodType.BAMBOO, BAMBOO_WINDOW), ORNATE_IRON_WINDOW_PANE = customWindowPane("ornate_iron_window", ORNATE_IRON_WINDOW, - () -> AllSpriteShifts.ORNATE_IRON_WINDOW, () -> RenderType::cutoutMipped); + () -> AllSpriteShifts.ORNATE_IRON_WINDOW, () -> RenderType::cutoutMipped).register(), + INDUSTRIAL_IRON_WINDOW_PANE = customWindowPane("industrial_iron_window", INDUSTRIAL_IRON_WINDOW, + () -> AllSpriteShifts.INDUSTRIAL_IRON_WINDOW, () -> RenderType::cutoutMipped).register(), + WEATHERED_IRON_WINDOW_PANE = + customWindowPane("weathered_iron_window", WEATHERED_IRON_WINDOW, null, () -> RenderType::translucent) + .onRegister(CreateRegistrate.connectedTextures(() -> new WeatheredIronWindowPaneCTBehaviour())) + .register(); static { AllPaletteStoneTypes.register(REGISTRATE); diff --git a/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteStoneTypes.java b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteStoneTypes.java index 63c19c889b..8dce934e20 100644 --- a/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteStoneTypes.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteStoneTypes.java @@ -8,14 +8,15 @@ import java.util.function.Function; import com.simibubi.create.AllTags; import com.simibubi.create.Create; import com.simibubi.create.foundation.data.CreateRegistrate; -import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.util.nullness.NonNullSupplier; +import net.createmod.catnip.lang.Lang; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.material.MapColor; + import net.minecraftforge.registries.ForgeRegistries; public enum AllPaletteStoneTypes { diff --git a/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedPillarBlock.java b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedPillarBlock.java index 8c2d4ce600..a375347278 100644 --- a/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedPillarBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedPillarBlock.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.decoration.palettes; -import com.simibubi.create.foundation.utility.Iterate; - +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPartial.java b/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPartial.java index 4a4e1615a5..17c40e6d6a 100644 --- a/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPartial.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPartial.java @@ -7,7 +7,6 @@ import java.util.function.Supplier; import com.simibubi.create.Create; import com.simibubi.create.foundation.data.CreateRegistrate; -import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.ItemBuilder; import com.tterrag.registrate.providers.DataGenContext; @@ -17,6 +16,7 @@ import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.nullness.NonnullType; +import net.createmod.catnip.lang.Lang; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.recipes.ShapelessRecipeBuilder; @@ -31,6 +31,7 @@ import net.minecraft.world.level.block.SlabBlock; import net.minecraft.world.level.block.StairBlock; import net.minecraft.world.level.block.WallBlock; import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + import net.minecraftforge.client.model.generators.ModelFile; public abstract class PaletteBlockPartial { diff --git a/src/main/java/com/simibubi/create/content/decoration/palettes/PalettesVariantEntry.java b/src/main/java/com/simibubi/create/content/decoration/palettes/PalettesVariantEntry.java index e5edcf55c4..2655bbb49f 100644 --- a/src/main/java/com/simibubi/create/content/decoration/palettes/PalettesVariantEntry.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/PalettesVariantEntry.java @@ -1,9 +1,5 @@ package com.simibubi.create.content.decoration.palettes; -import static com.simibubi.create.Create.REGISTRATE; -import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; -import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly; - import com.google.common.collect.ImmutableList; import com.simibubi.create.Create; import com.simibubi.create.foundation.data.CreateRegistrate; @@ -13,7 +9,6 @@ import com.tterrag.registrate.providers.ProviderType; import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.nullness.NonNullSupplier; - import net.minecraft.client.renderer.RenderType; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.tags.TagKey; @@ -21,6 +16,10 @@ import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; +import static com.simibubi.create.Create.REGISTRATE; +import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; +import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly; + public class PalettesVariantEntry { public final ImmutableList> registeredBlocks; diff --git a/src/main/java/com/simibubi/create/content/decoration/palettes/WeatheredIronWindowCTBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/palettes/WeatheredIronWindowCTBehaviour.java new file mode 100644 index 0000000000..e578b8f990 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/WeatheredIronWindowCTBehaviour.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.decoration.palettes; + +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.foundation.block.connected.AllCTTypes; +import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; +import com.simibubi.create.foundation.block.connected.CTType; +import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +public class WeatheredIronWindowCTBehaviour extends ConnectedTextureBehaviour.Base { + + private List shifts; + + public WeatheredIronWindowCTBehaviour() { + this.shifts = List.of(AllSpriteShifts.OLD_FACTORY_WINDOW_1, AllSpriteShifts.OLD_FACTORY_WINDOW_2, + AllSpriteShifts.OLD_FACTORY_WINDOW_3, AllSpriteShifts.OLD_FACTORY_WINDOW_4); + } + + @Override + public @Nullable CTSpriteShiftEntry getShift(BlockState state, RandomSource rand, Direction direction, + @NotNull TextureAtlasSprite sprite) { + if (direction.getAxis() == Axis.Y || sprite == null) + return null; + CTSpriteShiftEntry entry = shifts.get(rand.nextInt(shifts.size())); + if (entry.getOriginal() == sprite) + return entry; + return super.getShift(state, rand, direction, sprite); + } + + @Override + public @Nullable CTSpriteShiftEntry getShift(BlockState state, Direction direction, + @Nullable TextureAtlasSprite sprite) { + return null; + } + + @Override + public @Nullable CTType getDataType(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction direction) { + return AllCTTypes.RECTANGLE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/palettes/WeatheredIronWindowPaneCTBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/palettes/WeatheredIronWindowPaneCTBehaviour.java new file mode 100644 index 0000000000..4f4188988d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/WeatheredIronWindowPaneCTBehaviour.java @@ -0,0 +1,54 @@ +package com.simibubi.create.content.decoration.palettes; + +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.foundation.block.connected.AllCTTypes; +import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; +import com.simibubi.create.foundation.block.connected.CTType; +import com.simibubi.create.foundation.block.connected.GlassPaneCTBehaviour; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +public class WeatheredIronWindowPaneCTBehaviour extends GlassPaneCTBehaviour { + + private List shifts; + + public WeatheredIronWindowPaneCTBehaviour() { + super(null); + this.shifts = List.of(AllSpriteShifts.OLD_FACTORY_WINDOW_1, AllSpriteShifts.OLD_FACTORY_WINDOW_2, + AllSpriteShifts.OLD_FACTORY_WINDOW_3, AllSpriteShifts.OLD_FACTORY_WINDOW_4); + } + + @Override + public @Nullable CTSpriteShiftEntry getShift(BlockState state, RandomSource rand, Direction direction, + @NotNull TextureAtlasSprite sprite) { + if (direction.getAxis() == Axis.Y || sprite == null) + return null; + CTSpriteShiftEntry entry = shifts.get(rand.nextInt(shifts.size())); + if (entry.getOriginal() == sprite) + return entry; + return super.getShift(state, rand, direction, sprite); + } + + @Override + public @Nullable CTSpriteShiftEntry getShift(BlockState state, Direction direction, + @Nullable TextureAtlasSprite sprite) { + return null; + } + + @Override + public @Nullable CTType getDataType(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction direction) { + return AllCTTypes.RECTANGLE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlock.java b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlock.java index 8a73cda1bd..161fc06940 100644 --- a/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlock.java @@ -6,10 +6,10 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItemStack; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.block.IBE; @@ -41,10 +41,11 @@ import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.items.ItemHandlerHelper; public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock - implements ProperWaterloggedBlock, IBE, ISpecialBlockItemRequirement, IWrenchable { + implements ProperWaterloggedBlock, IBE, SpecialBlockItemRequirement, IWrenchable { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; diff --git a/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlockEntity.java b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlockEntity.java index 208bd385ea..55e33d12b1 100644 --- a/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlockEntity.java @@ -7,8 +7,8 @@ import org.joml.Vector3f; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/decoration/placard/PlacardRenderer.java b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardRenderer.java index 8784eeb0ca..ee35f2b16e 100644 --- a/src/main/java/com/simibubi/create/content/decoration/placard/PlacardRenderer.java +++ b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardRenderer.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.decoration.placard; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControl.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControl.java index 7c23e4c384..cdf98026b9 100644 --- a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControl.java +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControl.java @@ -6,13 +6,15 @@ import java.util.function.Consumer; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.lang.Lang; import net.minecraft.client.Minecraft; import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -57,17 +59,17 @@ public enum DoorControl { playerFacing = SOUTH; } - Label label = new Label(x + 4, y + 6, Components.empty()).withShadow(); + Label label = new Label(x + 4, y + 6, Component.empty()).withShadow(); ScrollInput input = new SelectionScrollInput(x, y, 53, 16) - .forOptions(Lang.translatedOptions("contraption.door_control", valuesAsString())) - .titled(Lang.translateDirect("contraption.door_control")) + .forOptions(CreateLang.translatedOptions("contraption.door_control", valuesAsString())) + .titled(CreateLang.translateDirect("contraption.door_control")) .calling(s -> { DoorControl mode = values()[s]; - label.text = Lang.translateDirect("contraption.door_control." + Lang.asId(mode.name()) + ".short"); + label.text = CreateLang.translateDirect("contraption.door_control." + Lang.asId(mode.name()) + ".short"); callback.accept(mode); }) - .addHint(Lang.translateDirect("contraption.door_control.player_facing", - Lang.translateDirect("contraption.door_control." + Lang.asId(playerFacing.name()) + ".short"))) + .addHint(CreateLang.translateDirect("contraption.door_control.player_facing", + CreateLang.translateDirect("contraption.door_control." + Lang.asId(playerFacing.name()) + ".short"))) .setState(initial.ordinal()); input.onChanged(); return Pair.of(input, label); diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControlBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControlBehaviour.java index 755dca038e..bc89f17b5e 100644 --- a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControlBehaviour.java +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControlBehaviour.java @@ -3,21 +3,21 @@ package com.simibubi.create.content.decoration.slidingDoor; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; public class DoorControlBehaviour extends BlockEntityBehaviour { - + public static final BehaviourType TYPE = new BehaviourType<>(); - + public DoorControl mode; - + public DoorControlBehaviour(SmartBlockEntity be) { super(be); mode = DoorControl.ALL; } - + public void set(DoorControl mode) { if (this.mode == mode) return; @@ -30,13 +30,13 @@ public class DoorControlBehaviour extends BlockEntityBehaviour { NBTHelper.writeEnum(nbt, "DoorControl", mode); super.write(nbt, clientPacket); } - + @Override public void read(CompoundTag nbt, boolean clientPacket) { mode = NBTHelper.readEnum(nbt, "DoorControl", DoorControl.class); super.read(nbt, clientPacket); } - + @Override public BehaviourType getType() { return TYPE; diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlock.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlock.java index c21f0e60dc..d56751224c 100644 --- a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlock.java @@ -8,7 +8,6 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.content.contraptions.ContraptionWorld; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; - import com.simibubi.create.foundation.block.IHaveBigOutline; import net.minecraft.core.BlockPos; @@ -62,11 +61,11 @@ public class SlidingDoorBlock extends DoorBlock implements IWrenchable, IBE { @@ -55,7 +56,7 @@ public class SlidingDoorRenderer extends SafeBlockEntityRenderer, IWre super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); } - + @Override public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { return FluidTankBlock.isTank(pLevel.getBlockState(pPos.relative(getAttachedDirection(pState)))); diff --git a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlockEntity.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlockEntity.java index d5ab6925a5..a6370a9eb6 100644 --- a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlockEntity.java @@ -5,33 +5,32 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock.WhistleExtenderShape; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; import com.simibubi.create.content.kinetics.steamEngine.SteamJetParticleData; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -89,7 +88,7 @@ public class WhistleBlockEntity extends SmartBlockEntity implements IHaveGoggleI FluidTankBlockEntity tank = getTank(); boolean powered = isPowered() && (tank != null && tank.boiler.isActive() && (tank.boiler.passiveHeat || tank.boiler.activeHeat > 0) - || isVirtual()); + || isVirtual()); animation.chase(powered ? 1 : 0, powered ? .5f : .4f, powered ? Chaser.EXP : Chaser.LINEAR); animation.tickChaser(); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio(getOctave(), powered)); @@ -109,10 +108,10 @@ public class WhistleBlockEntity extends SmartBlockEntity implements IHaveGoggleI @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - String[] pitches = Lang.translateDirect("generic.notes") + String[] pitches = CreateLang.translateDirect("generic.notes") .getString() .split(";"); - Lang.translate("generic.pitch", pitches[pitch % pitches.length]).forGoggles(tooltip); + CreateLang.translate("generic.pitch", pitches[pitch % pitches.length]).forGoggles(tooltip); return true; } diff --git a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleExtenderBlock.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleExtenderBlock.java index 9027d07d79..9c5090ed96 100644 --- a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleExtenderBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleExtenderBlock.java @@ -4,8 +4,8 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; import com.simibubi.create.content.equipment.wrench.IWrenchable; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -62,7 +62,7 @@ public class WhistleExtenderBlock extends Block implements IWrenchable { if (!(world instanceof ServerLevel)) return InteractionResult.SUCCESS; world.setBlock(pos, state.setValue(SHAPE, WhistleExtenderShape.SINGLE), 3); - playRemoveSound(world, pos); + IWrenchable.playRemoveSound(world, pos); return InteractionResult.SUCCESS; } diff --git a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleRenderer.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleRenderer.java index 168fdcf1b8..6495b4376e 100644 --- a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleRenderer.java +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleRenderer.java @@ -4,11 +4,11 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -39,7 +39,7 @@ public class WhistleRenderer extends SafeBlockEntityRenderer offset -= Math.sin(wiggleProgress * (2 * Mth.PI) * (4 - size.ordinal())) / 16f; } - CachedBufferer.partial(mouth, blockState) + CachedBuffers.partial(mouth, blockState) .center() .rotateYDegrees(AngleHelper.horizontalAngle(direction)) .uncenter() diff --git a/src/main/java/com/simibubi/create/content/equipment/BuildersTeaItem.java b/src/main/java/com/simibubi/create/content/equipment/BuildersTeaItem.java index caea8034c0..338707e24c 100644 --- a/src/main/java/com/simibubi/create/content/equipment/BuildersTeaItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/BuildersTeaItem.java @@ -1,12 +1,5 @@ package com.simibubi.create.content.equipment; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResultHolder; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; @@ -16,47 +9,30 @@ import net.minecraft.world.item.UseAnim; import net.minecraft.world.level.Level; public class BuildersTeaItem extends Item { - - public BuildersTeaItem(Properties p_i48487_1_) { - super(p_i48487_1_); + public BuildersTeaItem(Properties properties) { + super(properties); } - public ItemStack finishUsingItem(ItemStack stack, Level world, LivingEntity entity) { - Player playerentity = entity instanceof Player ? (Player) entity : null; - if (playerentity instanceof ServerPlayer) - CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) playerentity, stack); - - if (!world.isClientSide) - entity.addEffect(new MobEffectInstance(MobEffects.DIG_SPEED, 3 * 60 * 20, 0, false, false, false)); - - if (playerentity != null) { - playerentity.awardStat(Stats.ITEM_USED.get(this)); - playerentity.getFoodData().eat(1, .6F); - if (!playerentity.getAbilities().instabuild) - stack.shrink(1); + @Override + public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity livingEntity) { + ItemStack eatResult = super.finishUsingItem(stack, level, livingEntity); + if (livingEntity instanceof Player player && !player.getAbilities().instabuild) { + if (eatResult.isEmpty()) { + return Items.GLASS_BOTTLE.getDefaultInstance(); + } else { + player.getInventory().add(Items.GLASS_BOTTLE.getDefaultInstance()); + } } - - if (playerentity == null || !playerentity.getAbilities().instabuild) { - if (stack.isEmpty()) - return new ItemStack(Items.GLASS_BOTTLE); - if (playerentity != null) - playerentity.getInventory().add(new ItemStack(Items.GLASS_BOTTLE)); - } - - return stack; + return eatResult; } - public int getUseDuration(ItemStack p_77626_1_) { + @Override + public int getUseDuration(ItemStack stack) { return 42; } - public UseAnim getUseAnimation(ItemStack p_77661_1_) { + @Override + public UseAnim getUseAnimation(ItemStack stack) { return UseAnim.DRINK; } - - public InteractionResultHolder use(Level p_77659_1_, Player p_77659_2_, InteractionHand p_77659_3_) { - p_77659_2_.startUsingItem(p_77659_3_); - return InteractionResultHolder.success(p_77659_2_.getItemInHand(p_77659_3_)); - } - } diff --git a/src/main/java/com/simibubi/create/content/equipment/TreeFertilizerItem.java b/src/main/java/com/simibubi/create/content/equipment/TreeFertilizerItem.java index 57e38aa901..2e69ea8d1d 100644 --- a/src/main/java/com/simibubi/create/content/equipment/TreeFertilizerItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/TreeFertilizerItem.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.equipment; -import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationServerWorld; +import net.createmod.catnip.levelWrappers.PlacementSimulationServerLevel; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.BlockTags; @@ -89,17 +89,17 @@ public class TreeFertilizerItem extends Item { return original.setValue(BlockStateProperties.STAGE, 1); } - private static class TreesDreamWorld extends PlacementSimulationServerWorld { + private static class TreesDreamWorld extends PlacementSimulationServerLevel { private final BlockState soil; protected TreesDreamWorld(ServerLevel wrapped, BlockPos saplingPos) { super(wrapped); BlockState stateUnderSapling = wrapped.getBlockState(saplingPos.below()); - + // Tree features don't seem to succeed with mud as soil if (stateUnderSapling.is(BlockTags.DIRT)) stateUnderSapling = Blocks.DIRT.defaultBlockState(); - + soil = stateUnderSapling; } diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/AllArmorMaterials.java b/src/main/java/com/simibubi/create/content/equipment/armor/AllArmorMaterials.java index 446069c104..7a2f67020f 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/AllArmorMaterials.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/AllArmorMaterials.java @@ -3,10 +3,12 @@ package com.simibubi.create.content.equipment.armor; import java.util.function.Supplier; import com.google.common.base.Suppliers; +import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; import net.minecraft.world.item.ArmorItem.Type; import net.minecraft.world.item.ArmorMaterial; import net.minecraft.world.item.Items; @@ -15,7 +17,11 @@ import net.minecraft.world.item.crafting.Ingredient; public enum AllArmorMaterials implements ArmorMaterial { COPPER(Create.asResource("copper").toString(), 7, new int[] { 2, 4, 3, 1 }, 25, () -> AllSoundEvents.COPPER_ARMOR_EQUIP.getMainEvent(), 0.0F, 0.0F, - () -> Ingredient.of(Items.COPPER_INGOT)) + () -> Ingredient.of(Items.COPPER_INGOT)), + + CARDBOARD(Create.asResource("cardboard") + .toString(), 4, new int[] { 1, 1, 1, 1 }, 25, () -> SoundEvents.ARMOR_EQUIP_LEATHER, 0.0F, 0.0F, + () -> Ingredient.of(AllItems.CARDBOARD)) ; diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankArmorLayer.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankArmorLayer.java index 2d3441ae48..b5a8a447c5 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankArmorLayer.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankArmorLayer.java @@ -2,11 +2,11 @@ package com.simibubi.create.content.equipment.armor; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.renderer.MultiBufferSource; @@ -30,7 +30,7 @@ public class BacktankArmorLayer @Override public void render(PoseStack ms, MultiBufferSource buffer, int light, LivingEntity entity, float yaw, float pitch, - float pt, float p_225628_8_, float p_225628_9_, float p_225628_10_) { + float pt, float p_225628_8_, float p_225628_9_, float p_225628_10_) { if (entity.getPose() == Pose.SLEEPING) return; @@ -39,15 +39,15 @@ public class BacktankArmorLayer return; M entityModel = getParentModel(); - if (!(entityModel instanceof HumanoidModel)) + if (!(entityModel instanceof HumanoidModel model)) return; - HumanoidModel model = (HumanoidModel) entityModel; VertexConsumer vc = buffer.getBuffer(Sheets.cutoutBlockSheet()); BlockState renderedState = item.getBlock().defaultBlockState() - .setValue(BacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); - SuperByteBuffer backtank = CachedBufferer.block(renderedState); - SuperByteBuffer cogs = CachedBufferer.partial(BacktankRenderer.getCogsModel(renderedState), renderedState); + .setValue(BacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); + SuperByteBuffer backtank = CachedBuffers.block(renderedState); + SuperByteBuffer cogs = CachedBuffers.partial(BacktankRenderer.getCogsModel(renderedState), renderedState); + SuperByteBuffer nob = CachedBuffers.partial(BacktankRenderer.getShaftModel(renderedState), renderedState); ms.pushPose(); @@ -59,6 +59,11 @@ public class BacktankArmorLayer .light(light) .renderInto(ms, vc); + nob.disableDiffuse() + .translate(0, -3f / 16, 0) + .light(light) + .renderInto(ms, vc); + cogs.center() .rotateYDegrees(180) .uncenter() @@ -80,11 +85,10 @@ public class BacktankArmorLayer registerOn(renderer); } - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) public static void registerOn(EntityRenderer entityRenderer) { - if (!(entityRenderer instanceof LivingEntityRenderer)) + if (!(entityRenderer instanceof LivingEntityRenderer livingRenderer)) return; - LivingEntityRenderer livingRenderer = (LivingEntityRenderer) entityRenderer; if (!(livingRenderer.getModel() instanceof HumanoidModel)) return; BacktankArmorLayer layer = new BacktankArmorLayer<>(livingRenderer); diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlock.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlock.java index 93e7fc44df..1ecd71e649 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlock.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlock.java @@ -6,8 +6,8 @@ import java.util.Optional; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllEnchantments; import com.simibubi.create.AllShapes; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.block.IBE; @@ -46,9 +46,10 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.common.util.FakePlayer; -public class BacktankBlock extends HorizontalKineticBlock implements IBE, SimpleWaterloggedBlock, ISpecialBlockItemRequirement { +public class BacktankBlock extends HorizontalKineticBlock implements IBE, SimpleWaterloggedBlock, SpecialBlockItemRequirement { public BacktankBlock(Properties properties) { super(properties); diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlockEntity.java index 6b03b0947f..1fb707ab1a 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlockEntity.java @@ -12,8 +12,8 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.ComparatorUtil; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.particle.AirParticleData; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; import net.minecraft.core.particles.ParticleTypes; diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankItem.java index b5787a5013..aeee4ae61d 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankItem.java @@ -1,13 +1,7 @@ package com.simibubi.create.content.equipment.armor; -import java.util.Locale; -import java.util.function.Supplier; - -import org.jetbrains.annotations.Nullable; - import com.simibubi.create.content.equipment.armor.CapacityEnchantment.ICapacityEnchantable; import com.simibubi.create.foundation.item.LayeredArmorItem; - import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; @@ -22,12 +16,16 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.block.Block; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; +import java.util.function.Supplier; public class BacktankItem extends BaseArmorItem implements ICapacityEnchantable { public static final EquipmentSlot SLOT = EquipmentSlot.CHEST; public static final ArmorItem.Type TYPE = ArmorItem.Type.CHESTPLATE; public static final int BAR_COLOR = 0xEFEFEF; - + private final Supplier blockItem; public BacktankItem(ArmorMaterial material, Properties properties, ResourceLocation textureLoc, Supplier placeable) { diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankRenderer.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankRenderer.java index 9ab3170c55..2dce458179 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankRenderer.java @@ -4,12 +4,12 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -27,7 +27,7 @@ public class BacktankRenderer extends KineticBlockEntityRenderer>> BACKTANK_SUPPLIERS = new ArrayList<>(); - + static { addBacktankSupplier(entity -> { List stacks = new ArrayList<>(); @@ -77,7 +79,7 @@ public class BacktankUtil { if (!(entity instanceof ServerPlayer player)) return; - + sendWarning(player, air, newAir, maxAir / 10f); sendWarning(player, air, newAir, 1); } @@ -89,16 +91,16 @@ public class BacktankUtil { return; boolean depleted = threshold == 1; - MutableComponent component = Lang.translateDirect(depleted ? "backtank.depleted" : "backtank.low"); + MutableComponent component = CreateLang.translateDirect(depleted ? "backtank.depleted" : "backtank.low"); AllSoundEvents.DENY.play(player.level(), null, player.blockPosition(), 1, 1.25f); AllSoundEvents.STEAM.play(player.level(), null, player.blockPosition(), .5f, .5f); player.connection.send(new ClientboundSetTitlesAnimationPacket(10, 40, 10)); player.connection.send(new ClientboundSetSubtitleTextPacket( - Components.literal("\u26A0 ").withStyle(depleted ? ChatFormatting.RED : ChatFormatting.GOLD) + Component.literal("\u26A0 ").withStyle(depleted ? ChatFormatting.RED : ChatFormatting.GOLD) .append(component.withStyle(ChatFormatting.GRAY)))); - player.connection.send(new ClientboundSetTitleTextPacket(Components.immutableEmpty())); + player.connection.send(new ClientboundSetTitleTextPacket(CommonComponents.EMPTY)); } public static int maxAir(ItemStack backtank) { @@ -174,7 +176,7 @@ public class BacktankUtil { if (player == null) return 0; List backtanks = getAllWithAir(player); - + // Fallback colour if (backtanks.isEmpty()) return Mth.hsvToRgb(Math.max(0.0F, 1.0F - (float) stack.getDamageValue() / stack.getMaxDamage()) / 3.0F, diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankVisual.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankVisual.java deleted file mode 100644 index 8f8b9fca87..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankVisual.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.simibubi.create.content.equipment.armor; - -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; - -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.model.Models; - -public class BacktankVisual extends SingleRotatingVisual { - - public BacktankVisual(VisualizationContext context, BacktankBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Model model() { - return Models.partial(BacktankRenderer.getShaftModel(blockState)); - } -} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BaseArmorItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/BaseArmorItem.java index 66908b53f2..1c7e016af1 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/BaseArmorItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BaseArmorItem.java @@ -1,7 +1,5 @@ package com.simibubi.create.content.equipment.armor; -import java.util.Locale; - import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; @@ -9,6 +7,8 @@ import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ArmorMaterial; import net.minecraft.world.item.ItemStack; +import java.util.Locale; + public class BaseArmorItem extends ArmorItem { protected final ResourceLocation textureLoc; diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorHandler.java b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorHandler.java new file mode 100644 index 0000000000..c9f0803b70 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorHandler.java @@ -0,0 +1,99 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.UUID; + +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.advancement.AllAdvancements; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.NeutralMob; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.ai.goal.target.TargetGoal; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.event.entity.EntityEvent; +import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; +import net.minecraftforge.event.entity.living.LivingEvent.LivingVisibilityEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class CardboardArmorHandler { + + @SubscribeEvent + public static void playerHitboxChangesWhenHidingAsBox(EntityEvent.Size event) { + Entity entity = event.getEntity(); + if (!entity.isAddedToWorld()) + return; + if (!testForStealth(entity)) + return; + + event.setNewSize(EntityDimensions.fixed(0.6F, 0.8F)); + event.setNewEyeHeight(0.6F); + + if (!entity.level() + .isClientSide() && entity instanceof Player p) + AllAdvancements.CARDBOARD_ARMOR.awardTo(p); + } + + @SubscribeEvent + public static void playersStealthWhenWearingCardboard(LivingVisibilityEvent event) { + LivingEntity entity = event.getEntity(); + if (!testForStealth(entity)) + return; + event.modifyVisibility(0); + } + + @SubscribeEvent + public static void mobsMayLoseTargetWhenItIsWearingCardboard(LivingTickEvent event) { + LivingEntity entity = event.getEntity(); + if (entity.tickCount % 16 != 0) + return; + if (!(entity instanceof Mob mob)) + return; + + if (testForStealth(mob.getTarget())) { + mob.setTarget(null); + if (mob.targetSelector != null) + mob.targetSelector.getRunningGoals() + .forEach(wrappedGoal -> { + if (wrappedGoal.getGoal() instanceof TargetGoal tg) + tg.stop(); + }); + } + + if (entity instanceof NeutralMob nMob && entity.level() instanceof ServerLevel sl) { + UUID uuid = nMob.getPersistentAngerTarget(); + if (uuid != null && testForStealth(sl.getEntity(uuid))) + nMob.stopBeingAngry(); + } + + if (testForStealth(mob.getLastHurtByMob())) { + mob.setLastHurtByMob(null); + mob.setLastHurtByPlayer(null); + } + } + + public static boolean testForStealth(Entity entityIn) { + if (!(entityIn instanceof LivingEntity entity)) + return false; + if (entity.getPose() != Pose.CROUCHING) + return false; + if (entity instanceof Player player && player.getAbilities().flying) + return false; + if (!AllItems.CARDBOARD_HELMET.isIn(entity.getItemBySlot(EquipmentSlot.HEAD))) + return false; + if (!AllItems.CARDBOARD_CHESTPLATE.isIn(entity.getItemBySlot(EquipmentSlot.CHEST))) + return false; + if (!AllItems.CARDBOARD_LEGGINGS.isIn(entity.getItemBySlot(EquipmentSlot.LEGS))) + return false; + if (!AllItems.CARDBOARD_BOOTS.isIn(entity.getItemBySlot(EquipmentSlot.FEET))) + return false; + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorHandlerClient.java b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorHandlerClient.java new file mode 100644 index 0000000000..a32f059aaf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorHandlerClient.java @@ -0,0 +1,89 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import com.google.common.cache.Cache; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.box.PackageRenderer; +import com.simibubi.create.foundation.utility.TickBasedCache; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.minecraft.client.CameraType; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Player; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderPlayerEvent; +import net.minecraftforge.event.TickEvent.Phase; +import net.minecraftforge.event.TickEvent.PlayerTickEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(value = Dist.CLIENT) +public class CardboardArmorHandlerClient { + + private static final Cache BOXES_PLAYERS_ARE_HIDING_AS = new TickBasedCache<>(20, true); + + @SubscribeEvent + public static void keepCacheAliveDesignDespiteNotRendering(PlayerTickEvent event) { + if (event.phase == Phase.START) + return; + Player player = event.player; + if (!CardboardArmorHandler.testForStealth(player)) + return; + try { + getCurrentBoxIndex(player); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void playerRendersAsBoxWhenSneaking(RenderPlayerEvent.Pre event) { + Player player = event.getEntity(); + if (!CardboardArmorHandler.testForStealth(player)) + return; + + event.setCanceled(true); + + if (player == Minecraft.getInstance().player + && Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) + return; + + PoseStack ms = event.getPoseStack(); + ms.pushPose(); + ms.translate(0, 2 / 16f, 0); + + float movement = (float) player.position() + .subtract(player.xo, player.yo, player.zo) + .length(); + + if (player.onGround()) + ms.translate(0, + Math.min(Math.abs(Mth.cos((AnimationTickHolder.getRenderTime() % 256) / 2.0f)) * 2 / 16f, movement * 5), + 0); + + float interpolatedYaw = Mth.lerp(event.getPartialTick(), player.yRotO, player.getYRot()); + + try { + PartialModel model = AllPartialModels.PACKAGES_TO_HIDE_AS.get(getCurrentBoxIndex(player)); + PackageRenderer.renderBox(player, interpolatedYaw, ms, event.getMultiBufferSource(), + event.getPackedLight(), model); + } catch (ExecutionException e) { + e.printStackTrace(); + } + + ms.popPose(); + } + + private static Integer getCurrentBoxIndex(Player player) throws ExecutionException { + return BOXES_PLAYERS_ARE_HIDING_AS.get(player.getUUID(), + () -> player.level().random.nextInt(AllPartialModels.PACKAGES_TO_HIDE_AS.size())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorItem.java new file mode 100644 index 0000000000..22b44f6da5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorItem.java @@ -0,0 +1,21 @@ +package com.simibubi.create.content.equipment.armor; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.Create; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; + +public class CardboardArmorItem extends BaseArmorItem { + + public CardboardArmorItem(Type type, Properties properties) { + super(AllArmorMaterials.CARDBOARD, type, properties, Create.asResource("cardboard")); + } + + @Override + public int getBurnTime(ItemStack itemStack, @Nullable RecipeType recipeType) { + return 1000; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorStealthOverlay.java b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorStealthOverlay.java new file mode 100644 index 0000000000..708b31080b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardArmorStealthOverlay.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.equipment.armor; + +import com.simibubi.create.Create; + +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; + +import net.minecraftforge.client.extensions.common.IClientItemExtensions; + +public class CardboardArmorStealthOverlay extends Gui implements IClientItemExtensions { + + public CardboardArmorStealthOverlay() { + super(Minecraft.getInstance(), Minecraft.getInstance() + .getItemRenderer()); + } + + private static final ResourceLocation PACKAGE_BLUR_LOCATION = Create.asResource("textures/misc/package_blur.png"); + + private static LerpedFloat opacity = LerpedFloat.linear() + .startWithValue(0) + .chase(0, 0.25f, Chaser.EXP); + + public static void clientTick() { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) + return; + + opacity.tickChaser(); + opacity.updateChaseTarget(CardboardArmorHandler.testForStealth(player) ? 1 : 0); + } + + @Override + public void renderHelmetOverlay(ItemStack stack, Player player, int width, int height, float partialTick) { + Minecraft mc = Minecraft.getInstance(); + float value = opacity.getValue(partialTick); + if (value == 0) + return; + screenWidth = width; + screenHeight = height; + renderTextureOverlay(new GuiGraphics(mc, mc.renderBuffers() + .bufferSource()), PACKAGE_BLUR_LOCATION, value); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/CardboardHelmetItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardHelmetItem.java new file mode 100644 index 0000000000..eab4121bc1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/CardboardHelmetItem.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.function.Consumer; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.extensions.common.IClientItemExtensions; + +public class CardboardHelmetItem extends CardboardArmorItem { + + public CardboardHelmetItem(Type type, Properties properties) { + super(type, properties); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void initializeClient(Consumer consumer) { + super.initializeClient(consumer); + consumer.accept(new CardboardArmorStealthOverlay()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/DivingBootsItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/DivingBootsItem.java index f5dcf063ce..b231c0f69d 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/DivingBootsItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/DivingBootsItem.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.equipment.armor; -import com.simibubi.create.foundation.utility.NBTHelper; - +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.FluidTags; import net.minecraft.world.entity.Entity; @@ -13,6 +12,7 @@ import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ArmorMaterial; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -77,8 +77,7 @@ public class DivingBootsItem extends BaseArmorItem { return false; if (entity.getPose() == Pose.SWIMMING) return false; - if (entity instanceof Player) { - Player playerEntity = (Player) entity; + if (entity instanceof Player playerEntity) { if (playerEntity.getAbilities().flying) return false; } diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/DivingHelmetItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/DivingHelmetItem.java index a2a19f6d92..e63bc16a51 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/DivingHelmetItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/DivingHelmetItem.java @@ -1,10 +1,6 @@ package com.simibubi.create.content.equipment.armor; -import java.util.List; -import java.util.Map; - import com.simibubi.create.foundation.advancement.AllAdvancements; - import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.effect.MobEffectInstance; @@ -23,6 +19,9 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import java.util.List; +import java.util.Map; + @EventBusSubscriber public class DivingHelmetItem extends BaseArmorItem { public static final EquipmentSlot SLOT = EquipmentSlot.HEAD; diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/RemainingAirOverlay.java b/src/main/java/com/simibubi/create/content/equipment/armor/RemainingAirOverlay.java index 454ad23df0..1bd89461e9 100644 --- a/src/main/java/com/simibubi/create/content/equipment/armor/RemainingAirOverlay.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/RemainingAirOverlay.java @@ -4,10 +4,9 @@ import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Components; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.player.LocalPlayer; @@ -16,6 +15,7 @@ import net.minecraft.tags.FluidTags; import net.minecraft.util.StringUtil; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; + import net.minecraftforge.client.gui.overlay.ForgeGui; import net.minecraftforge.client.gui.overlay.IGuiOverlay; @@ -49,7 +49,7 @@ public class RemainingAirOverlay implements IGuiOverlay { poseStack.translate(width / 2 + 90, height - 53 + (backtank.getItem() .isFireResistant() ? 9 : 0), 0); - Component text = Components.literal(StringUtil.formatTickDuration(Math.max(0, timeLeft - 1) * 20)); + Component text = Component.literal(StringUtil.formatTickDuration(Math.max(0, timeLeft - 1) * 20)); GuiGameElement.of(backtank) .at(0, 0) .render(graphics); diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/TrimmableArmorModelGenerator.java b/src/main/java/com/simibubi/create/content/equipment/armor/TrimmableArmorModelGenerator.java new file mode 100644 index 0000000000..08363b4993 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/TrimmableArmorModelGenerator.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.equipment.armor; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.Map; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.mixin.accessor.ItemModelGeneratorsAccessor; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateItemModelProvider; + +import net.minecraft.data.models.ItemModelGenerators; +import net.minecraft.data.models.model.ModelLocationUtils; +import net.minecraft.data.models.model.TextureMapping; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.Item; + +import net.minecraftforge.client.model.generators.ItemModelBuilder; +import net.minecraftforge.client.model.generators.ModelBuilder; + +public class TrimmableArmorModelGenerator { + public static final VarHandle TEXTURES_HANDLE; + + static { + try { + MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ModelBuilder.class, MethodHandles.lookup()); + TEXTURES_HANDLE = lookup.findVarHandle(ModelBuilder.class, "textures", Map.class); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public static void generate(DataGenContext c, RegistrateItemModelProvider p) { + T item = c.get(); + ItemModelBuilder builder = p.generated(c); + for (ItemModelGenerators.TrimModelData data : ItemModelGeneratorsAccessor.create$getGENERATED_TRIM_MODELS()) { + ResourceLocation modelLoc = ModelLocationUtils.getModelLocation(item); + ResourceLocation textureLoc = TextureMapping.getItemTexture(item); + String trimId = data.name(item.getMaterial()); + ResourceLocation trimModelLoc = modelLoc.withSuffix("_" + trimId + "_trim"); + ResourceLocation trimLoc = + new ResourceLocation("trims/items/" + item.getType().getName() + "_trim_" + trimId); + String parent = "item/generated"; + if (item.getMaterial() == AllArmorMaterials.CARDBOARD) { + trimLoc = Create.asResource("trims/items/card_" + item.getType().getName() + "_trim_" + trimId); + } + ItemModelBuilder itemModel = p.withExistingParent(trimModelLoc.getPath(), parent) + .texture("layer0", textureLoc); + Map textures = (Map) TEXTURES_HANDLE.get(itemModel); + textures.put("layer1", trimLoc.toString()); + builder.override() + .predicate(ItemModelGenerators.TRIM_TYPE_PREDICATE_ID, data.itemModelIndex()) + .model(itemModel) + .end(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlockEntity.java index 7b6283af09..512d359b62 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlockEntity.java @@ -4,15 +4,16 @@ import java.util.List; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/BasicParticleData.java b/src/main/java/com/simibubi/create/content/equipment/bell/BasicParticleData.java index 452042e7f3..283a36f6c9 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/BasicParticleData.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/BasicParticleData.java @@ -5,8 +5,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.brigadier.StringReader; import com.mojang.serialization.Codec; import com.simibubi.create.foundation.particle.ICustomParticleDataWithSprite; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.Particle; @@ -15,6 +15,7 @@ import net.minecraft.client.particle.SpriteSet; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.network.FriendlyByteBuf; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -22,12 +23,13 @@ import net.minecraftforge.api.distmarker.OnlyIn; @MethodsReturnNonnullByDefault public abstract class BasicParticleData implements ParticleOptions, ICustomParticleDataWithSprite> { - public BasicParticleData() { } + public BasicParticleData() { + } @Override public Deserializer> getDeserializer() { BasicParticleData data = this; - return new ParticleOptions.Deserializer>() { + return new ParticleOptions.Deserializer<>() { @Override public BasicParticleData fromCommand(ParticleType> arg0, StringReader reader) { return data; @@ -56,14 +58,15 @@ public abstract class BasicParticleData implements ParticleO @OnlyIn(Dist.CLIENT) public ParticleEngine.SpriteParticleRegistration> getMetaFactory() { return animatedSprite -> (data, worldIn, x, y, z, vx, vy, vz) -> - getBasicFactory().makeParticle(worldIn, x, y, z, vx, vy, vz, animatedSprite); + getBasicFactory().makeParticle(worldIn, x, y, z, vx, vy, vz, animatedSprite); } @Override public String writeToString() { - return RegisteredObjects.getKeyOrThrow(getType()).toString(); + return CatnipServices.REGISTRIES.getKeyOrThrow(getType()).toString(); } @Override - public void writeToNetwork(FriendlyByteBuf buffer) { } + public void writeToNetwork(FriendlyByteBuf buffer) { + } } diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/BellRenderer.java b/src/main/java/com/simibubi/create/content/equipment/bell/BellRenderer.java index 2257497b6c..420053b53f 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/BellRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/BellRenderer.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.equipment.bell; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -26,7 +26,7 @@ public class BellRenderer extends SafeBlockE Direction facing = state.getValue(BellBlock.FACING); BellAttachType attachment = state.getValue(BellBlock.ATTACHMENT); - SuperByteBuffer bell = CachedBufferer.partial(be.getBellModel(), state); + SuperByteBuffer bell = CachedBuffers.partial(be.getBellModel(), state); if (be.isRinging) bell.rotateCentered(getSwingAngle(be.ringingTicks + partialTicks), be.ringDirection.getCounterClockWise()); diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/CustomRotationParticle.java b/src/main/java/com/simibubi/create/content/equipment/bell/CustomRotationParticle.java index 227b68f7e0..f0de0c17a7 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/CustomRotationParticle.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/CustomRotationParticle.java @@ -6,7 +6,7 @@ import org.joml.Vector3f; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; -import dev.engine_room.flywheel.lib.util.ShadersModHandler; +import dev.engine_room.flywheel.lib.util.ShadersModHelper; import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.SimpleAnimatedParticle; @@ -65,7 +65,7 @@ public class CustomRotationParticle extends SimpleAnimatedParticle { float maxU = mirror ? getU0() : getU1(); float minV = getV0(); float maxV = getV1(); - int brightness = ShadersModHandler.isShaderPackInUse() ? LightTexture.pack(12, 15) : getLightColor(partialTicks); + int brightness = ShadersModHelper.isShaderPackInUse() ? LightTexture.pack(12, 15) : getLightColor(partialTicks); builder.vertex(vertices[0].x(), vertices[0].y(), vertices[0].z()).uv(maxU, maxV).color(rCol, gCol, bCol, alpha).uv2(brightness).endVertex(); builder.vertex(vertices[1].x(), vertices[1].y(), vertices[1].z()).uv(maxU, minV).color(rCol, gCol, bCol, alpha).uv2(brightness).endVertex(); builder.vertex(vertices[2].x(), vertices[2].y(), vertices[2].z()).uv(minU, minV).color(rCol, gCol, bCol, alpha).uv2(brightness).endVertex(); diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellPulser.java b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellPulser.java index d599f97e04..e43b2a1d96 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellPulser.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellPulser.java @@ -1,15 +1,10 @@ package com.simibubi.create.content.equipment.bell; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.utility.IntAttached; - +import net.createmod.catnip.data.IntAttached; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -20,6 +15,10 @@ import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.network.PacketDistributor; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + @EventBusSubscriber public class HauntedBellPulser { diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/SoulBaseParticle.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulBaseParticle.java index d9423e5c13..11f768df4d 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/SoulBaseParticle.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulBaseParticle.java @@ -1,15 +1,13 @@ package com.simibubi.create.content.equipment.bell; -import org.joml.Quaternionf; - import com.mojang.math.Axis; import com.simibubi.create.AllParticleTypes; - import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.SpriteSet; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleType; +import org.joml.Quaternionf; public class SoulBaseParticle extends CustomRotationParticle { diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/SoulParticle.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulParticle.java index adedd6a7aa..54fafdb4ba 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/SoulParticle.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulParticle.java @@ -1,11 +1,8 @@ package com.simibubi.create.content.equipment.bell; -import org.joml.Quaternionf; - import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; import com.simibubi.create.AllParticleTypes; - import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.SpriteSet; @@ -13,6 +10,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.util.Mth; +import org.joml.Quaternionf; public class SoulParticle extends CustomRotationParticle { diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffect.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffect.java index 87c9cee985..83614f8aba 100644 --- a/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffect.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffect.java @@ -7,8 +7,8 @@ import java.util.stream.Stream; import com.google.common.collect.Streams; import com.simibubi.create.content.equipment.bell.SoulParticle.ExpandingPerimeterData; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.SpawnPlacements; diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintAssignCompleteRecipePacket.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintAssignCompleteRecipePacket.java index 375268c5fc..0eb0defad3 100644 --- a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintAssignCompleteRecipePacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintAssignCompleteRecipePacket.java @@ -5,6 +5,7 @@ import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; + import net.minecraftforge.network.NetworkEvent.Context; public class BlueprintAssignCompleteRecipePacket extends SimplePacketBase { @@ -30,12 +31,11 @@ public class BlueprintAssignCompleteRecipePacket extends SimplePacketBase { ServerPlayer player = context.getSender(); if (player == null) return; - if (player.containerMenu instanceof BlueprintMenu) { - BlueprintMenu c = (BlueprintMenu) player.containerMenu; + if (player.containerMenu instanceof BlueprintMenu c) { player.level() - .getRecipeManager() - .byKey(recipeID) - .ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.player.level(), c.ghostInventory, r)); + .getRecipeManager() + .byKey(recipeID) + .ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.player.level(), c.ghostInventory, r)); } }); return true; diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintEntity.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintEntity.java index e5b175fcd2..9b2dadd4c7 100644 --- a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintEntity.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintEntity.java @@ -12,15 +12,15 @@ import org.apache.commons.lang3.Validate; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.Create; +import com.simibubi.create.api.schematic.requirement.SpecialEntityItemRequirement; import com.simibubi.create.content.logistics.filter.FilterItemStack; -import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.networking.ISyncPersistentData; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.IInteractionChecker; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -59,6 +59,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.ForgeHooks; @@ -72,7 +73,7 @@ import net.minecraftforge.items.wrapper.InvWrapper; import net.minecraftforge.network.NetworkHooks; public class BlueprintEntity extends HangingEntity - implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement, ISyncPersistentData, IInteractionChecker { + implements IEntityAdditionalSpawnData, SpecialEntityItemRequirement, ISyncPersistentData, IInteractionChecker { protected int size; protected Direction verticalOrientation; @@ -172,15 +173,15 @@ public class BlueprintEntity extends HangingEntity Axis axis = direction.getAxis(); if (size == 2) pos = pos.add(Vec3.atLowerCornerOf(axis.isHorizontal() ? direction.getCounterClockWise() - .getNormal() - : verticalOrientation.getClockWise() - .getNormal()) - .scale(0.5)) + .getNormal() + : verticalOrientation.getClockWise() + .getNormal()) + .scale(0.5)) .add(Vec3 .atLowerCornerOf(axis.isHorizontal() ? Direction.UP.getNormal() : direction == Direction.UP ? verticalOrientation.getNormal() - : verticalOrientation.getOpposite() - .getNormal()) + : verticalOrientation.getOpposite() + .getNormal()) .scale(0.5)); d1 = pos.x; @@ -192,14 +193,14 @@ public class BlueprintEntity extends HangingEntity double d6 = (double) this.getWidth(); Direction.Axis direction$axis = this.direction.getAxis(); switch (direction$axis) { - case X: - d4 = 1.0D; - break; - case Y: - d5 = 1.0D; - break; - case Z: - d6 = 1.0D; + case X: + d4 = 1.0D; + break; + case Y: + d5 = 1.0D; + break; + case Z: + d6 = 1.0D; } d4 = d4 / 32.0D; @@ -208,6 +209,12 @@ public class BlueprintEntity extends HangingEntity this.setBoundingBox(new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6)); } + @Override + public void setPos(double pX, double pY, double pZ) { + setPosRaw(pX, pY, pZ); + super.setPos(pX, pY, pZ); + } + @Override public boolean survives() { if (!level().noCollision(this)) @@ -218,7 +225,7 @@ public class BlueprintEntity extends HangingEntity BlockPos blockpos = this.pos.relative(this.direction.getOpposite()); Direction upDirection = direction.getAxis() .isHorizontal() ? Direction.UP - : direction == Direction.UP ? verticalOrientation : verticalOrientation.getOpposite(); + : direction == Direction.UP ? verticalOrientation : verticalOrientation.getOpposite(); Direction newDirection = direction.getAxis() .isVertical() ? verticalOrientation.getClockWise() : direction.getCounterClockWise(); BlockPos.MutableBlockPos blockpos$mutable = new BlockPos.MutableBlockPos(); @@ -255,10 +262,9 @@ public class BlueprintEntity extends HangingEntity @Override public boolean skipAttackInteraction(Entity source) { - if (!(source instanceof Player) || level().isClientSide) + if (!(source instanceof Player player) || level().isClientSide) return super.skipAttackInteraction(source); - Player player = (Player) source; double attrib = player.getAttribute(ForgeMod.BLOCK_REACH.get()) .getValue() + (player.isCreative() ? 0 : -0.5F); @@ -290,8 +296,7 @@ public class BlueprintEntity extends HangingEntity return; playSound(SoundEvents.PAINTING_BREAK, 1.0F, 1.0F); - if (p_110128_1_ instanceof Player) { - Player playerentity = (Player) p_110128_1_; + if (p_110128_1_ instanceof Player playerentity) { if (playerentity.getAbilities().instabuild) return; } @@ -322,7 +327,7 @@ public class BlueprintEntity extends HangingEntity @Override @OnlyIn(Dist.CLIENT) public void lerpTo(double p_180426_1_, double p_180426_3_, double p_180426_5_, float p_180426_7_, float p_180426_8_, - int p_180426_9_, boolean p_180426_10_) { + int p_180426_9_, boolean p_180426_10_) { BlockPos blockpos = this.pos.offset(BlockPos.containing(p_180426_1_ - this.getX(), p_180426_3_ - this.getY(), p_180426_5_ - this.getZ())); this.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); @@ -365,7 +370,8 @@ public class BlueprintEntity extends HangingEntity Map craftingGrid = new HashMap<>(); boolean success = true; - Search: for (int i = 0; i < 9; i++) { + Search: + for (int i = 0; i < 9; i++) { FilterItemStack requestedItem = FilterItemStack.of(items.getStackInSlot(i)); if (requestedItem.isEmpty()) { craftingGrid.put(i, ItemStack.EMPTY); diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintItem.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintItem.java index ef299606ad..f6c6eb7abe 100644 --- a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintItem.java @@ -5,7 +5,8 @@ import java.util.Collection; import com.simibubi.create.AllItems; import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; import com.simibubi.create.content.logistics.filter.FilterItem; -import com.simibubi.create.content.logistics.filter.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.InTagAttribute; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -28,6 +29,7 @@ import net.minecraft.world.item.crafting.Ingredient.TagValue; import net.minecraft.world.item.crafting.Ingredient.Value; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.level.Level; + import net.minecraftforge.common.crafting.IShapedRecipe; import net.minecraftforge.common.crafting.MultiItemValue; import net.minecraftforge.items.ItemStackHandler; @@ -44,14 +46,14 @@ public class BlueprintItem extends Item { Player player = ctx.getPlayer(); ItemStack stack = ctx.getItemInHand(); BlockPos pos = ctx.getClickedPos() - .relative(face); + .relative(face); if (player != null && !player.mayUseItemAt(pos, face, stack)) return InteractionResult.FAIL; Level world = ctx.getLevel(); HangingEntity hangingentity = new BlueprintEntity(world, pos, face, face.getAxis() - .isHorizontal() ? Direction.DOWN : ctx.getHorizontalDirection()); + .isHorizontal() ? Direction.DOWN : ctx.getHorizontalDirection()); CompoundTag compoundnbt = stack.getTag(); if (compoundnbt != null) @@ -79,12 +81,11 @@ public class BlueprintItem extends Item { inv.setStackInSlot(i, ItemStack.EMPTY); inv.setStackInSlot(9, recipe.getResultItem(level.registryAccess())); - if (recipe instanceof IShapedRecipe) { - IShapedRecipe shapedRecipe = (IShapedRecipe) recipe; + if (recipe instanceof IShapedRecipe shapedRecipe) { for (int row = 0; row < shapedRecipe.getRecipeHeight(); row++) for (int col = 0; col < shapedRecipe.getRecipeWidth(); col++) inv.setStackInSlot(row * 3 + col, - convertIngredientToFilter(ingredients.get(row * shapedRecipe.getRecipeWidth() + col))); + convertIngredientToFilter(ingredients.get(row * shapedRecipe.getRecipeWidth() + col))); } else { for (int i = 0; i < ingredients.size(); i++) inv.setStackInSlot(i, convertIngredientToFilter(ingredients.get(i))); @@ -105,7 +106,7 @@ public class BlueprintItem extends Item { for (int i = 0; i < acceptedItems.length; i++) filterItems.setStackInSlot(i, convertIItemListToFilter(acceptedItems[i])); result.getOrCreateTag() - .put("Items", filterItems.serializeNBT()); + .put("Items", filterItems.serializeNBT()); return result; } @@ -120,15 +121,13 @@ public class BlueprintItem extends Item { ResourceLocation resourcelocation = new ResourceLocation(GsonHelper.getAsString(itemList.serialize(), "tag")); ItemStack filterItem = AllItems.ATTRIBUTE_FILTER.asStack(); filterItem.getOrCreateTag() - .putInt("WhitelistMode", WhitelistMode.WHITELIST_DISJ.ordinal()); + .putInt("WhitelistMode", WhitelistMode.WHITELIST_DISJ.ordinal()); ListTag attributes = new ListTag(); - ItemAttribute at = new ItemAttribute.InTag(ItemTags.create(resourcelocation)); - CompoundTag compoundNBT = new CompoundTag(); - at.serializeNBT(compoundNBT); + CompoundTag compoundNBT = ItemAttribute.saveStatic(new InTagAttribute(ItemTags.create(resourcelocation))); compoundNBT.putBoolean("Inverted", false); attributes.add(compoundNBT); filterItem.getOrCreateTag() - .put("MatchedAttributes", attributes); + .put("MatchedAttributes", attributes); return filterItem; } diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintMenu.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintMenu.java index 5c7f4da7e3..197ef51a05 100644 --- a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintMenu.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintMenu.java @@ -21,6 +21,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.IItemHandler; @@ -69,12 +70,12 @@ public class BlueprintMenu extends GhostItemMenu { ServerPlayer serverplayerentity = (ServerPlayer) player; CraftingContainer craftingInventory = new BlueprintCraftingInventory(this, ghostInventory); Optional optional = player.getServer() - .getRecipeManager() - .getRecipeFor(RecipeType.CRAFTING, craftingInventory, player.getCommandSenderWorld()); + .getRecipeManager() + .getRecipeFor(RecipeType.CRAFTING, craftingInventory, player.getCommandSenderWorld()); if (!optional.isPresent()) { if (ghostInventory.getStackInSlot(9) - .isEmpty()) + .isEmpty()) return; if (!contentHolder.inferredIcon) return; @@ -91,7 +92,7 @@ public class BlueprintMenu extends GhostItemMenu { contentHolder.inferredIcon = true; ItemStack toSend = itemstack.copy(); toSend.getOrCreateTag() - .putBoolean("InferredFromRecipe", true); + .putBoolean("InferredFromRecipe", true); serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 36 + 9, toSend)); } @@ -100,9 +101,9 @@ public class BlueprintMenu extends GhostItemMenu { if (slotId == 36 + 9) { if (stack.hasTag()) { contentHolder.inferredIcon = stack.getTag() - .getBoolean("InferredFromRecipe"); + .getBoolean("InferredFromRecipe"); stack.getTag() - .remove("InferredFromRecipe"); + .remove("InferredFromRecipe"); } else contentHolder.inferredIcon = false; } @@ -130,9 +131,8 @@ public class BlueprintMenu extends GhostItemMenu { int entityID = extraData.readVarInt(); int section = extraData.readVarInt(); Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); - if (!(entityByID instanceof BlueprintEntity)) + if (!(entityByID instanceof BlueprintEntity blueprintEntity)) return null; - BlueprintEntity blueprintEntity = (BlueprintEntity) entityByID; BlueprintSection blueprintSection = blueprintEntity.getSection(section); return blueprintSection; } diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintOverlayRenderer.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintOverlayRenderer.java index a982168c5f..c5cc0c7021 100644 --- a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintOverlayRenderer.java @@ -11,31 +11,44 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllItems; import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintCraftingInventory; import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintSection; +import com.simibubi.create.content.logistics.BigItemStack; import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItemStack; -import com.simibubi.create.content.logistics.filter.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.InTagAttribute; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.tableCloth.BlueprintOverlayShopContext; +import com.simibubi.create.content.logistics.tableCloth.ShoppingListItem.ShoppingList; +import com.simibubi.create.content.logistics.tableCloth.TableClothBlockEntity; import com.simibubi.create.content.trains.track.TrackPlacement.PlacementInfo; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.tooltip.TooltipRenderUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.GameType; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult.Type; + import net.minecraftforge.client.gui.overlay.ForgeGui; import net.minecraftforge.client.gui.overlay.IGuiOverlay; import net.minecraftforge.items.ItemHandlerHelper; @@ -53,10 +66,11 @@ public class BlueprintOverlayRenderer { static boolean noOutput; static boolean lastSneakState; static BlueprintSection lastTargetedSection; + static BlueprintOverlayShopContext shopContext; static Map cachedRenderedFilters = new IdentityHashMap<>(); static List> ingredients = new ArrayList<>(); - static ItemStack result = ItemStack.EMPTY; + static List results = new ArrayList<>(); static boolean resultCraftable = false; public static void tick() { @@ -66,6 +80,7 @@ public class BlueprintOverlayRenderer { lastTargetedSection = null; active = false; noOutput = false; + shopContext = null; if (mc.gameMode.getPlayerMode() == GameType.SPECTATOR) return; @@ -77,10 +92,9 @@ public class BlueprintOverlayRenderer { return; EntityHitResult entityRay = (EntityHitResult) mouseOver; - if (!(entityRay.getEntity() instanceof BlueprintEntity)) + if (!(entityRay.getEntity() instanceof BlueprintEntity blueprintEntity)) return; - BlueprintEntity blueprintEntity = (BlueprintEntity) entityRay.getEntity(); BlueprintSection sectionAt = blueprintEntity.getSectionAt(entityRay.getLocation() .subtract(blueprintEntity.position())); @@ -98,15 +112,12 @@ public class BlueprintOverlayRenderer { public static void displayTrackRequirements(PlacementInfo info, ItemStack pavementItem) { if (active) return; - - active = true; - empty = false; - noOutput = true; - ingredients.clear(); + prepareCustomOverlay(); int tracks = info.requiredTracks; while (tracks > 0) { - ingredients.add(Pair.of(new ItemStack(info.trackMaterial.getBlock(), Math.min(64, tracks)), info.hasRequiredTracks)); + ingredients.add( + Pair.of(new ItemStack(info.trackMaterial.getBlock(), Math.min(64, tracks)), info.hasRequiredTracks)); tracks -= 64; } @@ -118,6 +129,74 @@ public class BlueprintOverlayRenderer { } } + public static void displayChainRequirements(Item chainItem, int count, boolean fulfilled) { + if (active) + return; + prepareCustomOverlay(); + + int chains = count; + while (chains > 0) { + ingredients.add(Pair.of(new ItemStack(chainItem, Math.min(64, chains)), fulfilled)); + chains -= 64; + } + } + + public static void displayClothShop(TableClothBlockEntity dce, int alreadyPurchased, ShoppingList list) { + if (active) + return; + prepareCustomOverlay(); + noOutput = false; + + shopContext = new BlueprintOverlayShopContext(false, dce.getStockLevelForTrade(list), alreadyPurchased); + + ingredients.add(Pair.of(dce.getPaymentItem() + .copyWithCount(dce.getPaymentAmount()), + !dce.getPaymentItem() + .isEmpty() && shopContext.stockLevel() > shopContext.purchases())); + for (BigItemStack entry : dce.requestData.encodedRequest.stacks()) + results.add(entry.stack.copyWithCount(entry.count)); + } + + public static void displayShoppingList(Couple bakedList) { + if (active || bakedList == null) + return; + Minecraft mc = Minecraft.getInstance(); + prepareCustomOverlay(); + noOutput = false; + + shopContext = new BlueprintOverlayShopContext(true, 1, 0); + + for (BigItemStack entry : bakedList.getSecond() + .getStacksByCount()) { + ingredients.add(Pair.of(entry.stack.copyWithCount(entry.count), canAfford(mc.player, entry))); + } + + for (BigItemStack entry : bakedList.getFirst() + .getStacksByCount()) + results.add(entry.stack.copyWithCount(entry.count)); + } + + private static boolean canAfford(Player player, BigItemStack entry) { + int itemsPresent = 0; + for (int i = 0; i < player.getInventory().items.size(); i++) { + ItemStack item = player.getInventory() + .getItem(i); + if (item.isEmpty() || !ItemHandlerHelper.canItemStacksStack(item, entry.stack)) + continue; + itemsPresent += item.getCount(); + } + return itemsPresent >= entry.count; + } + + private static void prepareCustomOverlay() { + active = true; + empty = false; + noOutput = true; + ingredients.clear(); + results.clear(); + shopContext = null; + } + public static void rebuild(BlueprintSection sectionAt, boolean sneak) { cachedRenderedFilters.clear(); ItemStackHandler items = sectionAt.getItems(); @@ -131,7 +210,7 @@ public class BlueprintOverlayRenderer { } BlueprintOverlayRenderer.empty = empty; - BlueprintOverlayRenderer.result = ItemStack.EMPTY; + BlueprintOverlayRenderer.results.clear(); if (empty) return; @@ -161,7 +240,8 @@ public class BlueprintOverlayRenderer { newlyAdded.clear(); newlyMissing.clear(); - Search: for (int i = 0; i < 9; i++) { + Search: + for (int i = 0; i < 9; i++) { FilterItemStack requestedItem = FilterItemStack.of(items.getStackInSlot(i)); if (requestedItem.isEmpty()) { craftingGrid.put(i, ItemStack.EMPTY); @@ -198,10 +278,11 @@ public class BlueprintOverlayRenderer { success = false; } else { amountCrafted += resultFromRecipe.getCount(); - if (result.isEmpty()) - result = resultFromRecipe.copy(); + if (results.isEmpty()) + results.add(resultFromRecipe.copy()); else - result.grow(resultFromRecipe.getCount()); + results.get(0) + .grow(resultFromRecipe.getCount()); resultCraftable = true; firstPass = false; } @@ -214,7 +295,9 @@ public class BlueprintOverlayRenderer { if (!success) { if (firstPass) { - result = invalid ? ItemStack.EMPTY : items.getStackInSlot(9); + results.clear(); + if (!invalid) + results.add(items.getStackInSlot(9)); resultCraftable = false; } break; @@ -239,28 +322,47 @@ public class BlueprintOverlayRenderer { } } - public static void renderOverlay(ForgeGui gui, GuiGraphics graphics, float partialTicks, int width, - int height) { + public static void renderOverlay(ForgeGui gui, GuiGraphics graphics, float partialTicks, int width, int height) { Minecraft mc = Minecraft.getInstance(); - if (mc.options.hideGui) + if (mc.options.hideGui || mc.screen != null) return; if (!active || empty) return; + boolean invalidShop = shopContext != null && (ingredients.isEmpty() || ingredients.get(0) + .getFirst() + .isEmpty() || shopContext.stockLevel() == 0); + int w = 21 * ingredients.size(); - if (!noOutput) - w += 51; + if (!noOutput) { + w += 21 * results.size(); + w += 30; + } int x = (width - w) / 2; int y = (int) (height - 100); + if (shopContext != null) { + TooltipRenderUtil.renderTooltipBackground(graphics, x - 2, y + 1, w + 4, 19, 0, 0x55_000000, 0x55_000000, 0, + 0); + + AllGuiTextures.TRADE_OVERLAY.render(graphics, width / 2 - 48, y - 19); + if (shopContext.purchases() > 0) { + graphics.renderItem(AllItems.SHOPPING_LIST.asStack(), width / 2 + 20, y - 20); + graphics.drawString(mc.font, Component.literal("x" + shopContext.purchases()), width / 2 + 20 + 16, + y - 20 + 4, 0xff_eeeeee, true); + } + } + + // Ingredients for (Pair pair : ingredients) { RenderSystem.enableBlend(); (pair.getSecond() ? AllGuiTextures.HOTSLOT_ACTIVE : AllGuiTextures.HOTSLOT).render(graphics, x, y); ItemStack itemStack = pair.getFirst(); - String count = pair.getSecond() ? null : ChatFormatting.GOLD.toString() + itemStack.getCount(); + String count = shopContext != null && !shopContext.checkout() || pair.getSecond() ? null + : ChatFormatting.GOLD.toString() + itemStack.getCount(); drawItemStack(graphics, mc, x, y, itemStack, count); x += 21; } @@ -268,25 +370,58 @@ public class BlueprintOverlayRenderer { if (noOutput) return; + // Arrow x += 5; RenderSystem.enableBlend(); - AllGuiTextures.HOTSLOT_ARROW.render(graphics, x, y + 4); + if (invalidShop) + AllGuiTextures.HOTSLOT_ARROW_BAD.render(graphics, x, y + 4); + else + AllGuiTextures.HOTSLOT_ARROW.render(graphics, x, y + 4); x += 25; - if (result.isEmpty()) { + // Outputs + if (results.isEmpty()) { AllGuiTextures.HOTSLOT.render(graphics, x, y); GuiGameElement.of(Items.BARRIER) .at(x + 3, y + 3) .render(graphics); } else { - (resultCraftable ? AllGuiTextures.HOTSLOT_SUPER_ACTIVE : AllGuiTextures.HOTSLOT).render(graphics, - resultCraftable ? x - 1 : x, resultCraftable ? y - 1 : y); - drawItemStack(graphics, mc, x, y, result, null); + for (ItemStack result : results) { + AllGuiTextures slot = resultCraftable ? AllGuiTextures.HOTSLOT_SUPER_ACTIVE : AllGuiTextures.HOTSLOT; + if (!invalidShop && shopContext != null && shopContext.stockLevel() > shopContext.purchases()) + slot = AllGuiTextures.HOTSLOT_ACTIVE; + slot.render(graphics, resultCraftable ? x - 1 : x, resultCraftable ? y - 1 : y); + drawItemStack(graphics, mc, x, y, result, null); + x += 21; + } } + + if (shopContext != null && !shopContext.checkout()) { + int cycle = 0; + for (boolean count : Iterate.trueAndFalse) + for (int i = 0; i < results.size(); i++) { + ItemStack result = results.get(i); + List tooltipLines = result.getTooltipLines(mc.player, TooltipFlag.NORMAL); + if (tooltipLines.size() <= 1) + continue; + if (count) { + cycle++; + continue; + } + if ((gui.getGuiTicks() / 40) % cycle != i) + continue; + graphics.renderComponentTooltip(gui.getFont(), tooltipLines, mc.getWindow() + .getGuiScaledWidth(), + mc.getWindow() + .getGuiScaledHeight()); + } + } + RenderSystem.disableBlend(); } - public static void drawItemStack(GuiGraphics graphics, Minecraft mc, int x, int y, ItemStack itemStack, String count) { + public static void drawItemStack(GuiGraphics graphics, Minecraft mc, int x, int y, ItemStack itemStack, + String count) { if (itemStack.getItem() instanceof FilterItem) { int step = AnimationTickHolder.getTicks(mc.level) / 10; ItemStack[] itemsMatchingFilter = getItemsMatchingFilter(itemStack); @@ -312,15 +447,15 @@ public class BlueprintOverlayRenderer { if (!stackInSlot.isEmpty()) list.add(stackInSlot); } - return list.toArray(new ItemStack[list.size()]); + return list.toArray(ItemStack[]::new); } if (AllItems.ATTRIBUTE_FILTER.isIn(itemStack)) { WhitelistMode whitelistMode = WhitelistMode.values()[tag.getInt("WhitelistMode")]; ListTag attributes = tag.getList("MatchedAttributes", net.minecraft.nbt.Tag.TAG_COMPOUND); if (whitelistMode == WhitelistMode.WHITELIST_DISJ && attributes.size() == 1) { - ItemAttribute fromNBT = ItemAttribute.fromNBT((CompoundTag) attributes.get(0)); - if (fromNBT instanceof ItemAttribute.InTag inTag) { + ItemAttribute fromNBT = ItemAttribute.loadStatic((CompoundTag) attributes.get(0)); + if (fromNBT instanceof InTagAttribute inTag) { ITagManager tagManager = ForgeRegistries.ITEMS.tags(); if (tagManager.isKnownTagName(inTag.tag)) { ITag taggedItems = tagManager.getTag(inTag.tag); diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintRenderer.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintRenderer.java index 041ff5a5e7..a77b0ae81e 100644 --- a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintRenderer.java @@ -5,12 +5,12 @@ import org.joml.Matrix3f; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintSection; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.Couple; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.Couple; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.Sheets; @@ -34,7 +34,7 @@ public class BlueprintRenderer extends EntityRenderer { int light) { PartialModel partialModel = entity.size == 3 ? AllPartialModels.CRAFTING_BLUEPRINT_3x3 : entity.size == 2 ? AllPartialModels.CRAFTING_BLUEPRINT_2x2 : AllPartialModels.CRAFTING_BLUEPRINT_1x1; - SuperByteBuffer sbb = CachedBufferer.partial(partialModel, Blocks.AIR.defaultBlockState()); + SuperByteBuffer sbb = CachedBuffers.partial(partialModel, Blocks.AIR.defaultBlockState()); sbb.rotateYDegrees(-yaw) .rotateXDegrees(90.0F + entity.getXRot()) .translate(-.5, -1 / 32f, -.5); diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintScreen.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintScreen.java index fb500d60c1..b8d1b393e1 100644 --- a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintScreen.java @@ -1,11 +1,5 @@ package com.simibubi.create.content.equipment.blueprint; -import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - import com.google.common.collect.ImmutableList; import com.simibubi.create.AllPackets; import com.simibubi.create.AllPartialModels; @@ -13,17 +7,22 @@ import com.simibubi.create.content.logistics.filter.FilterScreenPacket; import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.utility.Lang; - +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.Rect2i; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; + public class BlueprintScreen extends AbstractSimiContainerScreen { protected AllGuiTextures background; @@ -39,20 +38,20 @@ public class BlueprintScreen extends AbstractSimiContainerScreen @Override protected void init() { - setWindowSize(background.width, background.height + 4 + PLAYER_INVENTORY.height); + setWindowSize(background.getWidth(), background.getHeight() + 4 + PLAYER_INVENTORY.getHeight()); setWindowOffset(1, 0); super.init(); int x = leftPos; int y = topPos; - resetButton = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_TRASH); + resetButton = new IconButton(x + background.getWidth() - 62, y + background.getHeight() - 24, AllIcons.I_TRASH); resetButton.withCallback(() -> { menu.clearContents(); contentsCleared(); menu.sendClearPacket(); }); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { minecraft.player.closeContainer(); }); @@ -60,13 +59,13 @@ public class BlueprintScreen extends AbstractSimiContainerScreen addRenderableWidget(resetButton); addRenderableWidget(confirmButton); - extraAreas = ImmutableList.of(new Rect2i(x + background.width, y + background.height - 36, 56, 44)); + extraAreas = ImmutableList.of(new Rect2i(x + background.getWidth(), y + background.getHeight() - 36, 56, 44)); } @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - int invX = getLeftOfCentered(PLAYER_INVENTORY.width); - int invY = topPos + background.height + 4; + int invX = getLeftOfCentered(PLAYER_INVENTORY.getWidth()); + int invY = topPos + background.getHeight() + 4; renderPlayerInventory(graphics, invX, invY); int x = leftPos; @@ -76,7 +75,7 @@ public class BlueprintScreen extends AbstractSimiContainerScreen graphics.drawString(font, title, x + 15, y + 4, 0xFFFFFF, false); GuiGameElement.of(AllPartialModels.CRAFTING_BLUEPRINT_1x1).at(x + background.width + 20, y + background.height - 32, 0) + .GuiRenderBuilder>at(x + background.getWidth() + 20, y + background.getHeight() - 32, 0) .rotate(45, -45, 22.5f) .scale(40) .render(graphics); @@ -102,26 +101,26 @@ public class BlueprintScreen extends AbstractSimiContainerScreen return list; if (slot < 9) { - list.add(Lang.translateDirect("crafting_blueprint.crafting_slot") + list.add(CreateLang.translateDirect("crafting_blueprint.crafting_slot") .withStyle(ChatFormatting.GOLD)); if (isEmptySlot) - list.add(Lang.translateDirect("crafting_blueprint.filter_items_viable") + list.add(CreateLang.translateDirect("crafting_blueprint.filter_items_viable") .withStyle(ChatFormatting.GRAY)); } else if (slot == 9) { - list.add(Lang.translateDirect("crafting_blueprint.display_slot") + list.add(CreateLang.translateDirect("crafting_blueprint.display_slot") .withStyle(ChatFormatting.GOLD)); if (!isEmptySlot) - list.add(Lang + list.add(CreateLang .translateDirect( "crafting_blueprint." + (menu.contentHolder.inferredIcon ? "inferred" : "manually_assigned")) .withStyle(ChatFormatting.GRAY)); } else if (slot == 10) { - list.add(Lang.translateDirect("crafting_blueprint.secondary_display_slot") + list.add(CreateLang.translateDirect("crafting_blueprint.secondary_display_slot") .withStyle(ChatFormatting.GOLD)); if (isEmptySlot) - list.add(Lang.translateDirect("crafting_blueprint.optional") + list.add(CreateLang.translateDirect("crafting_blueprint.optional") .withStyle(ChatFormatting.GRAY)); } diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlock.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlock.java index 1236f8607c..77a496d4c9 100644 --- a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlock.java +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlock.java @@ -8,8 +8,8 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.gui.ScreenOpener; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -90,14 +90,14 @@ public class ClipboardBlock extends FaceAttachedHorizontalDirectionalBlock breakAndCollect(pState, pLevel, pPos, pPlayer); return InteractionResult.SUCCESS; } - + return onBlockEntityUse(pLevel, pPos, cbe -> { if (pLevel.isClientSide()) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openScreen(pPlayer, cbe.dataContainer, pPos)); return InteractionResult.SUCCESS; }); } - + @OnlyIn(Dist.CLIENT) private void openScreen(Player player, ItemStack stack, BlockPos pos) { if (Minecraft.getInstance().player == player) diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java index 2537f6a88e..03bc8f9b2a 100644 --- a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.UUID; import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.logistics.AddressEditBoxHelper; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; @@ -39,6 +40,13 @@ public class ClipboardBlockEntity extends SmartBlockEntity { notifyUpdate(); updateWrittenState(); } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide()) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::advertiseToAddressHelper); + } public void updateWrittenState() { BlockState blockState = getBlockState(); @@ -87,5 +95,10 @@ public class ClipboardBlockEntity extends SmartBlockEntity { return; cs.reopenWith(dataContainer); } + + @OnlyIn(Dist.CLIENT) + private void advertiseToAddressHelper() { + AddressEditBoxHelper.advertiseClipboard(this); + } } diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java index ac442062b1..9aae35a44c 100644 --- a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java @@ -2,8 +2,9 @@ package com.simibubi.create.content.equipment.clipboard; import javax.annotation.Nonnull; -import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.recipe.ItemCopyingRecipe.SupportsItemCopying; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -22,7 +23,7 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.items.ItemHandlerHelper; -public class ClipboardBlockItem extends BlockItem { +public class ClipboardBlockItem extends BlockItem implements SupportsItemCopying { public ClipboardBlockItem(Block pBlock, Properties pProperties) { super(pBlock, pProperties); diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEditPacket.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEditPacket.java index c2541f6f37..e4fc47ba7b 100644 --- a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEditPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEditPacket.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.equipment.clipboard; import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.CreateNBTProcessors; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.core.BlockPos; @@ -11,6 +12,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; + import net.minecraftforge.network.NetworkEvent.Context; public class ClipboardEditPacket extends SimplePacketBase { @@ -44,8 +46,11 @@ public class ClipboardEditPacket extends SimplePacketBase { @Override public boolean handle(Context context) { context.enqueueWork(() -> { + // Get rid of any unsafe data + data = CreateNBTProcessors.clipboardProcessor(data); + ServerPlayer sender = context.getSender(); - + if (targetedBlock != null) { Level world = sender.level(); if (world == null || !world.isLoaded(targetedBlock)) @@ -58,14 +63,14 @@ public class ClipboardEditPacket extends SimplePacketBase { } return; } - + ItemStack itemStack = sender.getInventory() .getItem(hotbarSlot); if (!AllBlocks.CLIPBOARD.isIn(itemStack)) return; itemStack.setTag(data.isEmpty() ? null : data); }); - + return true; } diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEntry.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEntry.java index 480d4cdab6..7b092f3e66 100644 --- a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEntry.java +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEntry.java @@ -3,8 +3,7 @@ package com.simibubi.create.content.equipment.clipboard; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.foundation.utility.NBTHelper; - +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; @@ -16,6 +15,7 @@ public class ClipboardEntry { public boolean checked; public MutableComponent text; public ItemStack icon; + public int itemAmount; public ClipboardEntry(boolean checked, MutableComponent text) { this.checked = checked; @@ -23,8 +23,9 @@ public class ClipboardEntry { this.icon = ItemStack.EMPTY; } - public ClipboardEntry displayItem(ItemStack icon) { + public ClipboardEntry displayItem(ItemStack icon, int amount) { this.icon = icon; + this.itemAmount = amount; return this; } @@ -46,7 +47,7 @@ public class ClipboardEntry { List entries = pages.get(page); return entries; } - + public static void saveAll(List> entries, ItemStack clipboardItem) { CompoundTag tag = clipboardItem.getOrCreateTag(); tag.put("Pages", NBTHelper.writeCompoundList(entries, list -> { @@ -63,6 +64,7 @@ public class ClipboardEntry { if (icon.isEmpty()) return nbt; nbt.put("Icon", icon.serializeNBT()); + nbt.putInt("ItemAmount", itemAmount); return nbt; } @@ -70,7 +72,7 @@ public class ClipboardEntry { ClipboardEntry clipboardEntry = new ClipboardEntry(tag.getBoolean("Checked"), Component.Serializer.fromJson(tag.getString("Text"))); if (tag.contains("Icon")) - clipboardEntry.displayItem(ItemStack.of(tag.getCompound("Icon"))); + clipboardEntry.displayItem(ItemStack.of(tag.getCompound("Icon")), tag.getInt("ItemAmount")); return clipboardEntry; } diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java index 20f0e9dfc5..ef375a5833 100644 --- a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java @@ -6,12 +6,6 @@ import java.util.List; import javax.annotation.Nullable; -import com.simibubi.create.AllSoundEvents; - -import net.minecraft.client.Minecraft; - -import net.minecraft.client.resources.sounds.SimpleSoundInstance; - import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableInt; @@ -25,18 +19,19 @@ import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.VertexFormat; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides.ClipboardType; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; +import net.createmod.catnip.gui.AbstractSimiScreen; import net.minecraft.SharedConstants; import net.minecraft.Util; +import net.minecraft.client.Minecraft; import net.minecraft.client.StringSplitter; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; @@ -46,9 +41,11 @@ import net.minecraft.client.gui.screens.inventory.PageButton; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.Rect2i; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; import net.minecraft.util.FormattedCharSequence; import net.minecraft.util.Mth; @@ -103,7 +100,7 @@ public class ClipboardScreen extends AbstractSimiScreen { currentEntries = pages.get(currentPage); boolean startEmpty = currentEntries.isEmpty(); if (startEmpty) - currentEntries.add(new ClipboardEntry(false, Components.empty())); + currentEntries.add(new ClipboardEntry(false, Component.empty())); editingIndex = 0; editContext = new TextFieldHelper(this::getCurrentEntryText, this::setCurrentEntryText, this::getClipboard, this::setClipboard, this::validateTextForEntry); @@ -130,13 +127,13 @@ public class ClipboardScreen extends AbstractSimiScreen { editingIndex = -1; currentEntries.removeIf(ce -> ce.checked); if (currentEntries.isEmpty()) - currentEntries.add(new ClipboardEntry(false, Components.empty())); + currentEntries.add(new ClipboardEntry(false, Component.empty())); sendIfEditingBlock(); }); - clearBtn.setToolTip(Lang.translateDirect("gui.clipboard.erase_checked")); + clearBtn.setToolTip(CreateLang.translateDirect("gui.clipboard.erase_checked")); closeBtn = new IconButton(x + 234, y + 175, AllIcons.I_PRIORITY_VERY_LOW) .withCallback(() -> minecraft.setScreen(null)); - closeBtn.setToolTip(Lang.translateDirect("station.close")); + closeBtn.setToolTip(CreateLang.translateDirect("station.close")); addRenderableWidget(closeBtn); addRenderableWidget(clearBtn); @@ -189,7 +186,7 @@ public class ClipboardScreen extends AbstractSimiScreen { ClipboardEntry clipboardEntry = currentEntries.get(i); String text = clipboardEntry.text.getString(); totalHeight += - Math.max(12, font.split(Components.literal(text), clipboardEntry.icon.isEmpty() ? 150 : 130) + Math.max(12, font.split(Component.literal(text), clipboardEntry.icon.isEmpty() ? 150 : 130) .size() * 9 + 3); if (totalHeight > my) { @@ -206,7 +203,7 @@ public class ClipboardScreen extends AbstractSimiScreen { } private void setCurrentEntryText(String text) { - currentEntries.get(editingIndex).text = Components.literal(text); + currentEntries.get(editingIndex).text = Component.literal(text); sendIfEditingBlock(); } @@ -224,7 +221,7 @@ public class ClipboardScreen extends AbstractSimiScreen { for (int i = 0; i < currentEntries.size(); i++) { ClipboardEntry clipboardEntry = currentEntries.get(i); String text = i == editingIndex ? newText : clipboardEntry.text.getString(); - totalHeight += Math.max(12, font.split(Components.literal(text), 150) + totalHeight += Math.max(12, font.split(Component.literal(text), 150) .size() * 9 + 3); } return totalHeight < 185; @@ -257,7 +254,7 @@ public class ClipboardScreen extends AbstractSimiScreen { } currentEntries = pages.get(currentPage); if (currentEntries.isEmpty()) { - currentEntries.add(new ClipboardEntry(false, Components.empty())); + currentEntries.add(new ClipboardEntry(false, Component.empty())); if (!readonly) { editingIndex = 0; editContext.setCursorToEnd(); @@ -283,19 +280,32 @@ public class ClipboardScreen extends AbstractSimiScreen { int y = guiTop - 8; AllGuiTextures.CLIPBOARD.render(graphics, x, y); - graphics.drawString(font, Components.translatable("book.pageIndicator", currentPage + 1, getNumPages()), x + 150, y + 9, - 0x43ffffff, false); + graphics.drawString(font, Component.translatable("book.pageIndicator", currentPage + 1, getNumPages()), + x + 150, y + 9, 0x43ffffff, false); for (int i = 0; i < currentEntries.size(); i++) { ClipboardEntry clipboardEntry = currentEntries.get(i); boolean checked = clipboardEntry.checked; int iconOffset = clipboardEntry.icon.isEmpty() ? 0 : 16; - graphics.drawString(font, "\u25A1", x + 45, y + 51, checked ? 0x668D7F6B : 0xff8D7F6B, false); - if (checked) - graphics.drawString(font, "\u2714", x + 45, y + 50, 0x31B25D, false); + MutableComponent text = clipboardEntry.text; + String string = text.getString(); + boolean isAddress = string.startsWith("#") && !string.substring(1) + .isBlank(); - List split = font.split(clipboardEntry.text, 150 - iconOffset); + if (isAddress) { + RenderSystem.enableBlend(); + (checked ? AllGuiTextures.CLIPBOARD_ADDRESS_INACTIVE : AllGuiTextures.CLIPBOARD_ADDRESS) + .render(graphics, x + 44, y + 50); + text = Component.literal(string.substring(1) + .stripLeading()); + } else { + graphics.drawString(font, "\u25A1", x + 45, y + 51, checked ? 0x668D7F6B : 0xff8D7F6B, false); + if (checked) + graphics.drawString(font, "\u2714", x + 45, y + 50, 0x31B25D, false); + } + + List split = font.split(text, 150 - iconOffset); if (split.isEmpty()) { y += 12; continue; @@ -306,7 +316,8 @@ public class ClipboardScreen extends AbstractSimiScreen { for (FormattedCharSequence sequence : split) { if (i != editingIndex) - graphics.drawString(font, sequence, x + 58 + iconOffset, y + 50, checked ? 0x31B25D : 0x311A00, false); + graphics.drawString(font, sequence, x + 58 + iconOffset, y + 50, + checked ? isAddress ? 0x668D7F6B : 0x31B25D : 0x311A00, false); y += 9; } y += 3; @@ -315,13 +326,11 @@ public class ClipboardScreen extends AbstractSimiScreen { if (editingIndex == -1) return; - boolean checked = currentEntries.get(editingIndex).checked; - setFocused(null); DisplayCache cache = getDisplayCache(); for (LineInfo line : cache.lines) - graphics.drawString(font, line.asComponent, line.x, line.y, checked ? 0x31B25D : 0x311A00, false); + graphics.drawString(font, line.asComponent, line.x, line.y, 0x311A00, false); renderHighlight(cache.selection); renderCursor(graphics, cache.cursor, cache.cursorAtEnd); @@ -427,7 +436,7 @@ public class ClipboardScreen extends AbstractSimiScreen { if (currentEntries.size() <= editingIndex + 1 || !currentEntries.get(editingIndex + 1).text.getString() .isEmpty()) - currentEntries.add(editingIndex + 1, new ClipboardEntry(false, Components.empty())); + currentEntries.add(editingIndex + 1, new ClipboardEntry(false, Component.empty())); editingIndex += 1; editContext.setCursorToEnd(); if (validateTextForEntry(" ")) @@ -580,14 +589,22 @@ public class ClipboardScreen extends AbstractSimiScreen { return true; if (pButton != 0) return true; - + if (hoveredEntry != -1) { if (hoveredCheck) { editingIndex = -1; if (hoveredEntry < currentEntries.size()) { currentEntries.get(hoveredEntry).checked ^= true; - if (currentEntries.get(hoveredEntry).checked == true) Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(AllSoundEvents.CLIPBOARD_CHECKMARK.getMainEvent(), 0.95f + (float)Math.random() * 0.05f)); - else Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(AllSoundEvents.CLIPBOARD_ERASE.getMainEvent(), 0.90f + (float)Math.random() * 0.2f)); + if (currentEntries.get(hoveredEntry).checked == true) + Minecraft.getInstance() + .getSoundManager() + .play(SimpleSoundInstance.forUI(AllSoundEvents.CLIPBOARD_CHECKMARK.getMainEvent(), + 0.95f + (float) Math.random() * 0.05f)); + else + Minecraft.getInstance() + .getSoundManager() + .play(SimpleSoundInstance.forUI(AllSoundEvents.CLIPBOARD_ERASE.getMainEvent(), + 0.90f + (float) Math.random() * 0.2f)); } sendIfEditingBlock(); return true; @@ -596,7 +613,7 @@ public class ClipboardScreen extends AbstractSimiScreen { if (hoveredEntry != editingIndex && !readonly) { editingIndex = hoveredEntry; if (hoveredEntry >= currentEntries.size()) { - currentEntries.add(new ClipboardEntry(false, Components.empty())); + currentEntries.add(new ClipboardEntry(false, Component.empty())); if (!validateTextForEntry(" ")) { currentEntries.remove(hoveredEntry); editingIndex = -1; @@ -616,7 +633,7 @@ public class ClipboardScreen extends AbstractSimiScreen { editingIndex = -1; return false; } - + long i = Util.getMillis(); DisplayCache cache = getDisplayCache(); int j = cache.getIndexAtPosition(font, convertScreenToLocal(new Pos2i((int) pMouseX, (int) pMouseY))); @@ -676,12 +693,27 @@ public class ClipboardScreen extends AbstractSimiScreen { } private DisplayCache rebuildDisplayCache() { - String s = getCurrentEntryText(); - if (s.isEmpty()) + String current = getCurrentEntryText(); + boolean address = current.startsWith("#") && !current.substring(1) + .isBlank(); + int offset = 0; + + if (address) { + String stripped = current.substring(1) + .stripLeading(); + offset = current.length() - stripped.length(); + current = stripped; + } + + if (current.isEmpty()) return DisplayCache.EMPTY; + String s = current; int i = editContext.getCursorPos(); int j = editContext.getSelectionPos(); + i = Mth.clamp(i - offset, 0, s.length()); + j = Mth.clamp(j - offset, 0, s.length()); + IntList intlist = new IntArrayList(); List list = Lists.newArrayList(); MutableInt mutableint = new MutableInt(); @@ -832,7 +864,7 @@ public class ClipboardScreen extends AbstractSimiScreen { contents = pContents; x = pX; y = pY; - asComponent = Components.literal(pContents) + asComponent = Component.literal(pContents) .setStyle(pStyle); } } diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardValueSettingsHandler.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardValueSettingsHandler.java index 8b35714926..dce68f045b 100644 --- a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardValueSettingsHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardValueSettingsHandler.java @@ -11,14 +11,14 @@ import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides.Clipbo import com.simibubi.create.content.trains.track.TrackBlockOutline; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -55,11 +55,11 @@ public class ClipboardValueSettingsHandler { return; if (!(mc.level.getBlockEntity(pos) instanceof SmartBlockEntity smartBE)) return; - if (!smartBE.getAllBehaviours() + if (!(smartBE instanceof ClipboardBlockEntity) && !smartBE.getAllBehaviours() .stream() .anyMatch(b -> b instanceof ClipboardCloneable cc && cc.writeToClipboard(new CompoundTag(), target.getDirection())) - && !(smartBE instanceof ClipboardCloneable)) + && !(smartBE instanceof ClipboardCloneable)) return; VoxelShape shape = blockstate.getShape(mc.level, pos); @@ -92,6 +92,14 @@ public class ClipboardValueSettingsHandler { if (!(mc.level.getBlockEntity(pos) instanceof SmartBlockEntity smartBE)) return; + if (smartBE instanceof ClipboardBlockEntity) { + List tip = new ArrayList<>(); + tip.add(CreateLang.translateDirect("clipboard.actions")); + tip.add(CreateLang.translateDirect("clipboard.copy_other_clipboard", Component.keybind("key.use"))); + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + return; + } + CompoundTag tagElement = mc.player.getMainHandItem() .getTagElement("CopiedValues"); @@ -113,11 +121,11 @@ public class ClipboardValueSettingsHandler { return; List tip = new ArrayList<>(); - tip.add(Lang.translateDirect("clipboard.actions")); + tip.add(CreateLang.translateDirect("clipboard.actions")); if (canCopy) - tip.add(Lang.translateDirect("clipboard.to_copy", Components.keybind("key.use"))); + tip.add(CreateLang.translateDirect("clipboard.to_copy", Component.keybind("key.use"))); if (canPaste) - tip.add(Lang.translateDirect("clipboard.to_paste", Components.keybind("key.attack"))); + tip.add(CreateLang.translateDirect("clipboard.to_paste", Component.keybind("key.attack"))); CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); } @@ -146,6 +154,55 @@ public class ClipboardValueSettingsHandler { return; if (!(world.getBlockEntity(pos) instanceof SmartBlockEntity smartBE)) return; + + if (smartBE instanceof ClipboardBlockEntity cbe) { + event.setCanceled(true); + event.setCancellationResult(InteractionResult.SUCCESS); + + if (!world.isClientSide()) { + List> listTo = ClipboardEntry.readAll(itemStack); + List> listFrom = ClipboardEntry.readAll(cbe.dataContainer); + List toAdd = new ArrayList<>(); + + for (List page : listFrom) { + Copy: for (ClipboardEntry entry : page) { + String entryToAdd = entry.text.getString(); + for (List pageTo : listTo) + for (ClipboardEntry existing : pageTo) + if (entryToAdd.equals(existing.text.getString())) + continue Copy; + toAdd.add(new ClipboardEntry(entry.checked, entry.text)); + } + } + + for (ClipboardEntry entry : toAdd) { + List page = null; + for (List freePage : listTo) { + if (freePage.size() > 11) + continue; + page = freePage; + break; + } + if (page == null) { + page = new ArrayList<>(); + listTo.add(page); + } + page.add(entry); + ClipboardOverrides.switchTo(ClipboardType.WRITTEN, itemStack); + } + + ClipboardEntry.saveAll(listTo, itemStack); + } + + player.displayClientMessage(CreateLang.translate("clipboard.copied_from_clipboard", world.getBlockState(pos) + .getBlock() + .getName() + .withStyle(ChatFormatting.WHITE)) + .style(ChatFormatting.GREEN) + .component(), true); + return; + } + CompoundTag tag = itemStack.getTagElement("CopiedValues"); if (paste && tag == null) return; @@ -197,7 +254,7 @@ public class ClipboardValueSettingsHandler { if (!anySuccess) return; - player.displayClientMessage(Lang + player.displayClientMessage(CreateLang .translate(paste ? "clipboard.pasted_to" : "clipboard.copied_from", world.getBlockState(pos) .getBlock() .getName() diff --git a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripInteractionPacket.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripInteractionPacket.java index ccaa02f18e..0fe0ea532f 100644 --- a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripInteractionPacket.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.equipment.extendoGrip; import com.simibubi.create.foundation.networking.SimplePacketBase; - import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; diff --git a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItem.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItem.java index abfacd8525..39784615ac 100644 --- a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItem.java @@ -12,9 +12,9 @@ import com.simibubi.create.AllPackets; import com.simibubi.create.content.equipment.armor.BacktankUtil; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.nbt.CompoundTag; @@ -34,6 +34,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult.Type; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.InputEvent; @@ -63,11 +64,11 @@ public class ExtendoGripItem extends Item { AttributeModifier.Operation.ADDITION); private static final Supplier> rangeModifier = Suppliers.memoize(() -> - // Holding an ExtendoGrip - ImmutableMultimap.of(ForgeMod.BLOCK_REACH.get(), singleRangeAttributeModifier)); + // Holding an ExtendoGrip + ImmutableMultimap.of(ForgeMod.BLOCK_REACH.get(), singleRangeAttributeModifier)); private static final Supplier> doubleRangeModifier = Suppliers.memoize(() -> - // Holding two ExtendoGrips o.O - ImmutableMultimap.of(ForgeMod.BLOCK_REACH.get(), doubleRangeAttributeModifier)); + // Holding two ExtendoGrips o.O + ImmutableMultimap.of(ForgeMod.BLOCK_REACH.get(), doubleRangeAttributeModifier)); private static DamageSource lastActiveDamageSource; @@ -80,11 +81,9 @@ public class ExtendoGripItem extends Item { @SubscribeEvent public static void holdingExtendoGripIncreasesRange(LivingTickEvent event) { - if (!(event.getEntity() instanceof Player)) + if (!(event.getEntity() instanceof Player player)) return; - Player player = (Player) event.getEntity(); - CompoundTag persistentData = player.getPersistentData(); boolean inOff = AllItems.EXTENDO_GRIP.isIn(player.getOffhandItem()); boolean inMain = AllItems.EXTENDO_GRIP.isIn(player.getMainHandItem()); @@ -246,9 +245,9 @@ public class ExtendoGripItem extends Item { if (lastActiveDamageSource == null) return; Entity entity = lastActiveDamageSource.getDirectEntity(); - if (!(entity instanceof Player)) + lastActiveDamageSource = null; + if (!(entity instanceof Player player)) return; - Player player = (Player) entity; if (!isHoldingExtendoGrip(player)) return; event.setStrength(event.getStrength() + 2); diff --git a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItemRenderer.java index d1a928e199..7df40ffd41 100644 --- a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItemRenderer.java @@ -6,10 +6,10 @@ import com.simibubi.create.Create; import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemDisplayContext; diff --git a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripRenderHandler.java index 37b8952726..59a223655b 100644 --- a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripRenderHandler.java @@ -4,10 +4,10 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllItems; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.player.LocalPlayer; diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleConfigScreen.java b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleConfigScreen.java index 465420ece8..3538a8698d 100644 --- a/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleConfigScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleConfigScreen.java @@ -4,14 +4,14 @@ import java.util.ArrayList; import java.util.List; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; import net.minecraft.util.Mth; @@ -24,30 +24,30 @@ public class GoggleConfigScreen extends AbstractSimiScreen { private final List tooltip; public GoggleConfigScreen() { - Component componentSpacing = Components.literal(" "); + Component componentSpacing = Component.literal(" "); tooltip = new ArrayList<>(); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay1"))); + .append(CreateLang.translateDirect("gui.config.overlay1"))); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay2") + .append(CreateLang.translateDirect("gui.config.overlay2") .withStyle(ChatFormatting.GRAY))); - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay3"))); + .append(CreateLang.translateDirect("gui.config.overlay3"))); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay4"))); - tooltip.add(Components.immutableEmpty()); + .append(CreateLang.translateDirect("gui.config.overlay4"))); + tooltip.add(CommonComponents.EMPTY); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay5") + .append(CreateLang.translateDirect("gui.config.overlay5") .withStyle(ChatFormatting.GRAY))); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay6") + .append(CreateLang.translateDirect("gui.config.overlay6") .withStyle(ChatFormatting.GRAY))); - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay7"))); + .append(CreateLang.translateDirect("gui.config.overlay7"))); tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("gui.config.overlay8"))); + .append(CreateLang.translateDirect("gui.config.overlay8"))); } @Override @@ -76,7 +76,7 @@ public class GoggleConfigScreen extends AbstractSimiScreen { @Override public boolean mouseDragged(double p_mouseDragged_1_, double p_mouseDragged_3_, int p_mouseDragged_5_, - double p_mouseDragged_6_, double p_mouseDragged_8_) { + double p_mouseDragged_6_, double p_mouseDragged_8_) { updateOffset(p_mouseDragged_1_, p_mouseDragged_3_); return true; diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleOverlayRenderer.java b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleOverlayRenderer.java index 48530f1ce5..ec744ad2de 100644 --- a/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleOverlayRenderer.java @@ -8,7 +8,10 @@ import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.CreateClient; +import com.simibubi.create.api.equipment.goggles.IHaveCustomOverlayIcon; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.api.equipment.goggles.IHaveHoveringInformation; +import com.simibubi.create.api.equipment.goggles.IProxyHoveringInformation; import com.simibubi.create.compat.Mods; import com.simibubi.create.content.contraptions.IDisplayAssemblyExceptions; import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock; @@ -16,24 +19,25 @@ import com.simibubi.create.content.contraptions.piston.PistonExtensionPoleBlock; import com.simibubi.create.content.trains.entity.TrainRelocator; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; import com.simibubi.create.foundation.gui.RemovedGuiUtils; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.mixin.accessor.MouseHandlerAccessor; -import com.simibubi.create.foundation.outliner.Outline; -import com.simibubi.create.foundation.outliner.Outliner.OutlineEntry; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CClient; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.gui.element.BoxElement; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.outliner.Outline; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.outliner.Outliner.OutlineEntry; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.MouseHandler; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; import net.minecraft.util.Mth; @@ -44,6 +48,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; + import net.minecraftforge.client.gui.overlay.ForgeGui; import net.minecraftforge.client.gui.overlay.IGuiOverlay; @@ -51,19 +56,19 @@ public class GoggleOverlayRenderer { public static final IGuiOverlay OVERLAY = GoggleOverlayRenderer::renderOverlay; - private static final Map outlines = CreateClient.OUTLINER.getOutlines(); + private static final Map outlines = Outliner.getInstance().getOutlines(); public static int hoverTicks = 0; public static BlockPos lastHovered = null; public static void renderOverlay(ForgeGui gui, GuiGraphics graphics, float partialTicks, int width, - int height) { + int height) { Minecraft mc = Minecraft.getInstance(); if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) return; HitResult objectMouseOver = mc.hitResult; - if (!(objectMouseOver instanceof BlockHitResult)) { + if (!(objectMouseOver instanceof BlockHitResult result)) { lastHovered = null; hoverTicks = 0; return; @@ -77,7 +82,6 @@ public class GoggleOverlayRenderer { return; } - BlockHitResult result = (BlockHitResult) objectMouseOver; ClientLevel world = mc.level; BlockPos pos = result.getBlockPos(); @@ -90,6 +94,8 @@ public class GoggleOverlayRenderer { BlockEntity be = world.getBlockEntity(pos); boolean wearingGoggles = GogglesItem.isWearingGoggles(mc.player); + boolean isShifting = mc.player.isShiftKeyDown(); + boolean hasGoggleInformation = be instanceof IHaveGoggleInformation; boolean hasHoveringInformation = be instanceof IHaveHoveringInformation; @@ -97,22 +103,21 @@ public class GoggleOverlayRenderer { boolean hoverAddedInformation = false; ItemStack item = AllItems.GOGGLES.asStack(); - List tooltip = new ArrayList<>(); - if (hasGoggleInformation && wearingGoggles) { - boolean isShifting = mc.player.isShiftKeyDown(); + if (be instanceof IHaveCustomOverlayIcon customOverlayIcon) + item = customOverlayIcon.getIcon(isShifting); + if (hasGoggleInformation && wearingGoggles) { IHaveGoggleInformation gte = (IHaveGoggleInformation) be; goggleAddedInformation = gte.addToGoggleTooltip(tooltip, isShifting); - item = gte.getIcon(isShifting); } if (hasHoveringInformation) { if (!tooltip.isEmpty()) - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); IHaveHoveringInformation hte = (IHaveHoveringInformation) be; - hoverAddedInformation = hte.addToTooltip(tooltip, mc.player.isShiftKeyDown()); + hoverAddedInformation = hte.addToTooltip(tooltip, isShifting); if (goggleAddedInformation && !hoverAddedInformation) tooltip.remove(tooltip.size() - 1); @@ -128,7 +133,7 @@ public class GoggleOverlayRenderer { if (!hasHoveringInformation) if (hasHoveringInformation = - hoverAddedInformation = TrainRelocator.addToTooltip(tooltip, mc.player.isShiftKeyDown())) + hoverAddedInformation = TrainRelocator.addToTooltip(tooltip, isShifting)) hoverTicks = prevHoverTicks + 1; // break early if goggle or hover returned false when present @@ -157,9 +162,10 @@ public class GoggleOverlayRenderer { return; } if (!tooltip.isEmpty()) - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); - Lang.translate("gui.goggles.pole_length").text(" " + poles) + CreateLang.translate("gui.goggles.pole_length") + .text(" " + poles) .forGoggles(tooltip); } @@ -194,14 +200,11 @@ public class GoggleOverlayRenderer { float fade = Mth.clamp((hoverTicks + partialTicks) / 24f, 0, 1); Boolean useCustom = cfg.overlayCustomColor.get(); Color colorBackground = useCustom ? new Color(cfg.overlayBackgroundColor.get()) - : Theme.c(Theme.Key.VANILLA_TOOLTIP_BACKGROUND) - .scaleAlpha(.75f); + : BoxElement.COLOR_VANILLA_BACKGROUND.scaleAlpha(.75f); Color colorBorderTop = useCustom ? new Color(cfg.overlayBorderColorTop.get()) - : Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, true) - .copy(); + : BoxElement.COLOR_VANILLA_BORDER.getFirst().copy(); Color colorBorderBot = useCustom ? new Color(cfg.overlayBorderColorBot.get()) - : Theme.c(Theme.Key.VANILLA_TOOLTIP_BORDER, false) - .copy(); + : BoxElement.COLOR_VANILLA_BORDER.getSecond().copy(); if (fade < 1) { poseStack.translate(Math.pow(1 - fade, 3) * Math.signum(cfg.overlayOffsetX.get() + .5f) * 8, 0, 0); diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesModel.java b/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesModel.java index f19986ef34..974da9d6cd 100644 --- a/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesModel.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesModel.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.equipment.goggles; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; - import net.minecraft.client.resources.model.BakedModel; import net.minecraft.world.item.ItemDisplayContext; import net.minecraftforge.client.model.BakedModelWrapper; diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveGoggleInformation.java b/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveGoggleInformation.java deleted file mode 100644 index 7641e467d6..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveGoggleInformation.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.simibubi.create.content.equipment.goggles; - -import java.util.List; -import java.util.Optional; - -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; - -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; - -/* -* Implement this Interface in the BlockEntity class that wants to add info to the screen -* */ -public interface IHaveGoggleInformation { - - /** - * Use Lang.[...].forGoggles(list) - */ - String spacing = " "; - - /** - * Use Lang.[...].forGoggles(list) - */ - @Deprecated - Component componentSpacing = Components.literal(spacing); - - /** - * this method will be called when looking at a BlockEntity that implemented this - * interface - * - * @return {@code true} if the tooltip creation was successful and should be - * displayed, or {@code false} if the overlay should not be displayed - */ - default boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - return false; - } - - /** - * this method will be called when looking at a BlockEntity that implemented this - * interface - *

- * return the item of your choosing after checking for any logic you wish, and the goggle on the goggle - * tooltip will be replaced with the item you have returned - */ - default ItemStack getIcon(boolean isPlayerSneaking) { - return AllItems.GOGGLES.asStack(); - } - - default boolean containedFluidTooltip(List tooltip, boolean isPlayerSneaking, - LazyOptional handler) { - Optional resolve = handler.resolve(); - if (!resolve.isPresent()) - return false; - - IFluidHandler tank = resolve.get(); - if (tank.getTanks() == 0) - return false; - - LangBuilder mb = Lang.translate("generic.unit.millibuckets"); - Lang.translate("gui.goggles.fluid_container") - .forGoggles(tooltip); - - boolean isEmpty = true; - for (int i = 0; i < tank.getTanks(); i++) { - FluidStack fluidStack = tank.getFluidInTank(i); - if (fluidStack.isEmpty()) - continue; - - Lang.fluidName(fluidStack) - .style(ChatFormatting.GRAY) - .forGoggles(tooltip, 1); - - Lang.builder() - .add(Lang.number(fluidStack.getAmount()) - .add(mb) - .style(ChatFormatting.GOLD)) - .text(ChatFormatting.GRAY, " / ") - .add(Lang.number(tank.getTankCapacity(i)) - .add(mb) - .style(ChatFormatting.DARK_GRAY)) - .forGoggles(tooltip, 1); - - isEmpty = false; - } - - if (tank.getTanks() > 1) { - if (isEmpty) - tooltip.remove(tooltip.size() - 1); - return true; - } - - if (!isEmpty) - return true; - - Lang.translate("gui.goggles.fluid_container.capacity") - .add(Lang.number(tank.getTankCapacity(0)) - .add(mb) - .style(ChatFormatting.GOLD)) - .style(ChatFormatting.GRAY) - .forGoggles(tooltip, 1); - - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveHoveringInformation.java b/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveHoveringInformation.java deleted file mode 100644 index ea97e262a5..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveHoveringInformation.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.content.equipment.goggles; - -import java.util.List; - -import net.minecraft.network.chat.Component; - -/* -* Implement this Interface in the BlockEntity class that wants to add info to the screen -* */ -public interface IHaveHoveringInformation { - - default boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/IProxyHoveringInformation.java b/src/main/java/com/simibubi/create/content/equipment/goggles/IProxyHoveringInformation.java deleted file mode 100644 index dad2d3051c..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/goggles/IProxyHoveringInformation.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.simibubi.create.content.equipment.goggles; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; - -public interface IProxyHoveringInformation { - - public BlockPos getInformationSource(Level level, BlockPos pos, BlockState state); - -} diff --git a/src/main/java/com/simibubi/create/content/equipment/hats/CreateHatArmorLayer.java b/src/main/java/com/simibubi/create/content/equipment/hats/CreateHatArmorLayer.java new file mode 100644 index 0000000000..88e1349522 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/hats/CreateHatArmorLayer.java @@ -0,0 +1,122 @@ +package com.simibubi.create.content.equipment.hats; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.trains.schedule.hat.TrainHatInfo; +import com.simibubi.create.content.trains.schedule.hat.TrainHatInfoReloadListener; +import com.simibubi.create.foundation.mixin.accessor.AgeableListModelAccessor; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.minecraft.client.model.AgeableListModel; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.HierarchicalModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.ModelPart.Cube; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.Sheets; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class CreateHatArmorLayer> extends RenderLayer { + + public CreateHatArmorLayer(RenderLayerParent renderer) { + super(renderer); + } + + public void render(PoseStack ms, MultiBufferSource buffer, int light, LivingEntity entity, float limbSwing, float limbSwingAmount, + float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + PartialModel hat = EntityHats.getHatFor(entity); + if (hat == null) + return; + + M entityModel = getParentModel(); + ms.pushPose(); + + var msr = TransformStack.of(ms); + TrainHatInfo info = TrainHatInfoReloadListener.getHatInfoFor(entity.getType()); + List partsToHead = new ArrayList<>(); + + if (entityModel instanceof AgeableListModel model) { + if (model.young) { + if (model.scaleHead) { + float f = 1.5F / model.babyHeadScale; + ms.scale(f, f, f); + } + ms.translate(0.0D, model.babyYHeadOffset / 16.0F, model.babyZHeadOffset / 16.0F); + } + + ModelPart head = getHeadPart(model); + if (head != null) { + partsToHead.addAll(TrainHatInfo.getAdjustedPart(info, head, "")); + } + } else if (entityModel instanceof HierarchicalModel model) { + partsToHead.addAll(TrainHatInfo.getAdjustedPart(info, model.root(), "head")); + } + + if (!partsToHead.isEmpty()) { + partsToHead.forEach(part -> part.translateAndRotate(ms)); + + ModelPart lastChild = partsToHead.get(partsToHead.size() - 1); + if (!lastChild.isEmpty()) { + Cube cube = lastChild.cubes.get(Mth.clamp(info.cubeIndex(), 0, lastChild.cubes.size() - 1)); + ms.translate(info.offset().x() / 16.0F, (cube.minY - cube.maxY + info.offset().y()) / 16.0F, info.offset().z() / 16.0F); + float max = Math.max(cube.maxX - cube.minX, cube.maxZ - cube.minZ) / 8.0F * info.scale(); + ms.scale(max, max, max); + } + + ms.scale(1, -1, -1); + ms.translate(0, -2.25F / 16.0F, 0); + msr.rotateXDegrees(-8.5F); + BlockState air = Blocks.AIR.defaultBlockState(); + CachedBuffers.partial(hat, air) + .disableDiffuse() + .light(light) + .renderInto(ms, buffer.getBuffer(Sheets.cutoutBlockSheet())); + } + + ms.popPose(); + } + + public static void registerOnAll(EntityRenderDispatcher renderManager) { + for (EntityRenderer renderer : renderManager.getSkinMap() + .values()) + registerOn(renderer); + for (EntityRenderer renderer : renderManager.renderers.values()) + registerOn(renderer); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void registerOn(EntityRenderer entityRenderer) { + if (!(entityRenderer instanceof LivingEntityRenderer livingRenderer)) + return; + + EntityModel model = livingRenderer.getModel(); + + if (!(model instanceof HierarchicalModel) && !(model instanceof AgeableListModel)) + return; + + CreateHatArmorLayer layer = new CreateHatArmorLayer<>(livingRenderer); + livingRenderer.addLayer((CreateHatArmorLayer) layer); + } + + private static ModelPart getHeadPart(AgeableListModel model) { + for (ModelPart part : ((AgeableListModelAccessor) model).create$callHeadParts()) + return part; + for (ModelPart part : ((AgeableListModelAccessor) model).create$callBodyParts()) + return part; + return null; + } + + } diff --git a/src/main/java/com/simibubi/create/content/equipment/hats/EntityHats.java b/src/main/java/com/simibubi/create/content/equipment/hats/EntityHats.java new file mode 100644 index 0000000000..65e0203b33 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/hats/EntityHats.java @@ -0,0 +1,91 @@ +package com.simibubi.create.content.equipment.hats; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlock; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +// TODO: Behavioural Registry? +public class EntityHats { + + @Nullable + public static PartialModel getHatFor(LivingEntity entity) { + if (entity == null) + return null; + ItemStack headItem = entity.getItemBySlot(EquipmentSlot.HEAD); + if (!headItem.isEmpty()) + return null; + + if (shouldRenderTrainHat(entity)) + return AllPartialModels.TRAIN_HAT; + + return getLogisticsHatFor(entity); + } + + public static PartialModel getLogisticsHatFor(LivingEntity entity) { + if (!entity.isPassenger()) + return null; + if (!(entity.getVehicle() instanceof SeatEntity cce)) + return null; + + int stations = 0; + Level level = entity.level(); + BlockPos pos = entity.blockPosition(); + PartialModel hat = null; + + for (Direction d : Iterate.horizontalDirections) { + for (int y : Iterate.zeroAndOne) { + if (!(level.getBlockState(pos.relative(d) + .above(y)) + .getBlock() instanceof StockTickerBlock lw)) + continue; + PartialModel hatOfStation = lw.getHat(level, pos, entity); + if (hatOfStation == null) + continue; + hat = hatOfStation; + stations++; + } + } + + if (stations == 1) + return hat; + + return null; + } + + public static boolean shouldRenderTrainHat(LivingEntity entity) { + if (entity.getPersistentData() + .contains("TrainHat")) + return true; + if (!entity.isPassenger()) + return false; + if (!(entity.getVehicle() instanceof CarriageContraptionEntity cce)) + return false; + if (!cce.hasSchedule() && !(entity instanceof Player)) + return false; + Contraption contraption = cce.getContraption(); + if (!(contraption instanceof CarriageContraption cc)) + return false; + BlockPos seatOf = cc.getSeatOf(entity.getUUID()); + if (seatOf == null) + return false; + Couple validSides = cc.conductorSeats.get(seatOf); + return validSides != null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileBlockHitActions.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileBlockHitActions.java new file mode 100644 index 0000000000..cb6045e082 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileBlockHitActions.java @@ -0,0 +1,127 @@ +package com.simibubi.create.content.equipment.potatoCannon; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.Create; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileBlockHitAction; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.foundation.mixin.accessor.FallingBlockEntityAccessor; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +import net.minecraftforge.common.IPlantable; +import net.minecraftforge.registries.ForgeRegistries; + +public class AllPotatoProjectileBlockHitActions { + + static { + register("plant_crop", PlantCrop.CODEC); + register("place_block_on_ground", PlaceBlockOnGround.CODEC); + } + + public static void init() { + } + + private static void register(String name, Codec codec) { + Registry.register(CreateBuiltInRegistries.POTATO_PROJECTILE_BLOCK_HIT_ACTION, Create.asResource(name), codec); + } + + public record PlantCrop(Holder cropBlock) implements PotatoProjectileBlockHitAction { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + BuiltInRegistries.BLOCK.holderByNameCodec().fieldOf("block").forGetter(PlantCrop::cropBlock) + ).apply(instance, PlantCrop::new)); + + public PlantCrop(Block cropBlock) { + this(ForgeRegistries.BLOCKS.getDelegateOrThrow(cropBlock)); + } + + @Override + public boolean execute(LevelAccessor level, ItemStack projectile, BlockHitResult ray) { + if (level.isClientSide()) + return true; + + BlockPos hitPos = ray.getBlockPos(); + if (level instanceof Level l && !l.isLoaded(hitPos)) + return true; + Direction face = ray.getDirection(); + if (face != Direction.UP) + return false; + BlockPos placePos = hitPos.relative(face); + if (!level.getBlockState(placePos) + .canBeReplaced()) + return false; + if (!(cropBlock.get() instanceof IPlantable)) + return false; + BlockState blockState = level.getBlockState(hitPos); + if (!blockState.canSustainPlant(level, hitPos, face, (IPlantable) cropBlock.get())) + return false; + level.setBlock(placePos, cropBlock.get() + .defaultBlockState(), 3); + return true; + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public record PlaceBlockOnGround(Holder block) implements PotatoProjectileBlockHitAction { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + BuiltInRegistries.BLOCK.holderByNameCodec().fieldOf("block").forGetter(PlaceBlockOnGround::block) + ).apply(instance, PlaceBlockOnGround::new)); + + public PlaceBlockOnGround(Block block) { + this(ForgeRegistries.BLOCKS.getDelegateOrThrow(block)); + } + + @Override + public boolean execute(LevelAccessor levelAccessor, ItemStack projectile, BlockHitResult ray) { + if (levelAccessor.isClientSide()) + return true; + + BlockPos hitPos = ray.getBlockPos(); + if (levelAccessor instanceof Level l && !l.isLoaded(hitPos)) + return true; + Direction face = ray.getDirection(); + BlockPos placePos = hitPos.relative(face); + if (!levelAccessor.getBlockState(placePos) + .canBeReplaced()) + return false; + + if (face == Direction.UP) { + levelAccessor.setBlock(placePos, block.value() + .defaultBlockState(), 3); + } else if (levelAccessor instanceof Level level) { + double y = ray.getLocation().y - 0.5; + if (!level.isEmptyBlock(placePos.above())) + y = Math.min(y, placePos.getY()); + if (!level.isEmptyBlock(placePos.below())) + y = Math.max(y, placePos.getY()); + + FallingBlockEntity falling = FallingBlockEntityAccessor.create$callInit(level, placePos.getX() + 0.5, y, + placePos.getZ() + 0.5, block.get().defaultBlockState()); + falling.time = 1; + level.addFreshEntity(falling); + } + + return true; + } + + @Override + public Codec codec() { + return CODEC; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileEntityHitActions.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileEntityHitActions.java new file mode 100644 index 0000000000..de99905446 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileEntityHitActions.java @@ -0,0 +1,249 @@ +package com.simibubi.create.content.equipment.potatoCannon; + +import java.util.UUID; + +import com.mojang.authlib.GameProfile; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.Create; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileEntityHitAction; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.foundation.mixin.accessor.SuspiciousStewItemAccessor; +import com.simibubi.create.foundation.utility.CreateCodecs; + +import net.createmod.catnip.data.WorldAttached; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.monster.ZombieVillager; +import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.food.Foods; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.event.entity.EntityTeleportEvent; + +public class AllPotatoProjectileEntityHitActions { + + static { + register("set_on_fire", SetOnFire.CODEC); + register("potion_effect", PotionEffect.CODEC); + register("food_effects", FoodEffects.CODEC); + register("chorus_teleport", ChorusTeleport.CODEC); + register("cure_zombie_villager", CureZombieVillager.CODEC); + register("suspicious_stew", SuspiciousStew.CODEC); + } + + public static void init() { + } + + private static void register(String name, Codec codec) { + Registry.register(CreateBuiltInRegistries.POTATO_PROJECTILE_ENTITY_HIT_ACTION, Create.asResource(name), codec); + } + + public record SetOnFire(int ticks) implements PotatoProjectileEntityHitAction { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + ExtraCodecs.POSITIVE_INT.fieldOf("ticks").forGetter(SetOnFire::ticks) + ).apply(instance, SetOnFire::new)); + + public static SetOnFire seconds(int seconds) { + return new SetOnFire(seconds * 20); + } + + @Override + public boolean execute(ItemStack projectile, EntityHitResult ray, Type type) { + ray.getEntity() + .setRemainingFireTicks(ticks); + return false; + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public record PotionEffect(MobEffect effect, int level, int ticks, + boolean recoverable) implements PotatoProjectileEntityHitAction { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + BuiltInRegistries.MOB_EFFECT.byNameCodec().fieldOf("effect").forGetter(PotionEffect::effect), + ExtraCodecs.POSITIVE_INT.fieldOf("level").forGetter(PotionEffect::level), + ExtraCodecs.POSITIVE_INT.fieldOf("ticks").forGetter(PotionEffect::ticks), + Codec.BOOL.fieldOf("recoverable").forGetter(PotionEffect::recoverable) + ).apply(instance, PotionEffect::new)); + + @Override + public boolean execute(ItemStack projectile, EntityHitResult ray, Type type) { + Entity entity = ray.getEntity(); + if (entity.level().isClientSide) + return true; + if (entity instanceof LivingEntity) + applyEffect((LivingEntity) entity, new MobEffectInstance(effect, ticks, level - 1)); + return !recoverable; + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public record FoodEffects(FoodProperties foodProperty, + boolean recoverable) implements PotatoProjectileEntityHitAction { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + CreateCodecs.FOOD_PROPERTIES.fieldOf("food_property").forGetter(FoodEffects::foodProperty), + Codec.BOOL.fieldOf("recoverable").forGetter(FoodEffects::recoverable) + ).apply(instance, FoodEffects::new)); + + @Override + public boolean execute(ItemStack projectile, EntityHitResult ray, Type type) { + Entity entity = ray.getEntity(); + if (entity.level().isClientSide) + return true; + + if (entity instanceof LivingEntity livingEntity) { + for (Pair effect : foodProperty.getEffects()) { + if (livingEntity.getRandom().nextFloat() < effect.getSecond()) + applyEffect(livingEntity, new MobEffectInstance(effect.getFirst())); + } + } + return !recoverable; + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public record ChorusTeleport(double teleportDiameter) implements PotatoProjectileEntityHitAction { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + CreateCodecs.POSITIVE_DOUBLE.fieldOf("teleport_diameter").forGetter(ChorusTeleport::teleportDiameter) + ).apply(instance, ChorusTeleport::new)); + + @Override + public boolean execute(ItemStack projectile, EntityHitResult ray, Type type) { + Entity entity = ray.getEntity(); + Level level = entity.getCommandSenderWorld(); + if (level.isClientSide) + return true; + if (!(entity instanceof LivingEntity livingEntity)) + return false; + + double entityX = livingEntity.getX(); + double entityY = livingEntity.getY(); + double entityZ = livingEntity.getZ(); + + for (int teleportTry = 0; teleportTry < 16; ++teleportTry) { + double teleportX = entityX + (livingEntity.getRandom() + .nextDouble() - 0.5D) * teleportDiameter; + double teleportY = Mth.clamp(entityY + (livingEntity.getRandom() + .nextInt((int) teleportDiameter) - (int) (teleportDiameter / 2)), 0.0D, level.getHeight() - 1); + double teleportZ = entityZ + (livingEntity.getRandom() + .nextDouble() - 0.5D) * teleportDiameter; + + EntityTeleportEvent.ChorusFruit event = + ForgeEventFactory.onChorusFruitTeleport(livingEntity, teleportX, teleportY, teleportZ); + if (event.isCanceled()) + return false; + if (livingEntity.randomTeleport(event.getTargetX(), event.getTargetY(), event.getTargetZ(), true)) { + if (livingEntity.isPassenger()) + livingEntity.stopRiding(); + + SoundEvent soundevent = + livingEntity instanceof Fox ? SoundEvents.FOX_TELEPORT : SoundEvents.CHORUS_FRUIT_TELEPORT; + level.playSound(null, entityX, entityY, entityZ, soundevent, SoundSource.PLAYERS, 1.0F, 1.0F); + livingEntity.playSound(soundevent, 1.0F, 1.0F); + livingEntity.setDeltaMovement(Vec3.ZERO); + return true; + } + } + + return false; + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public enum CureZombieVillager implements PotatoProjectileEntityHitAction { + INSTANCE; + + private static final FoodEffects EFFECT = new FoodEffects(Foods.GOLDEN_APPLE, false); + private static final GameProfile ZOMBIE_CONVERTER_NAME = + new GameProfile(UUID.fromString("be12d3dc-27d3-4992-8c97-66be53fd49c5"), "Converter"); + private static final WorldAttached ZOMBIE_CONVERTERS = + new WorldAttached<>(w -> new FakePlayer((ServerLevel) w, ZOMBIE_CONVERTER_NAME)); + + public static final Codec CODEC = Codec.unit(INSTANCE); + + @Override + public boolean execute(ItemStack projectile, EntityHitResult ray, Type type) { + Entity entity = ray.getEntity(); + Level world = entity.level(); + + if (!(entity instanceof ZombieVillager zombieVillager) || !zombieVillager.hasEffect(MobEffects.WEAKNESS)) + return EFFECT.execute(projectile, ray, type); + if (world.isClientSide) + return false; + + FakePlayer dummy = ZOMBIE_CONVERTERS.get(world); + dummy.setItemInHand(InteractionHand.MAIN_HAND, new ItemStack(Items.GOLDEN_APPLE, 1)); + zombieVillager.mobInteract(dummy, InteractionHand.MAIN_HAND); + return true; + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public enum SuspiciousStew implements PotatoProjectileEntityHitAction { + INSTANCE; + + public static final Codec CODEC = Codec.unit(INSTANCE); + + @Override + public boolean execute(ItemStack projectile, EntityHitResult ray, Type type) { + if (ray.getEntity() instanceof LivingEntity livingEntity) + SuspiciousStewItemAccessor.create$listPotionEffects(projectile, livingEntity::addEffect); + + return false; + } + + @Override + public Codec codec() { + return CODEC; + } + } + + private static void applyEffect(LivingEntity entity, MobEffectInstance effect) { + if (effect.getEffect().isInstantenous()) { + effect.getEffect() + .applyInstantenousEffect(null, null, entity, effect.getDuration(), 1.0); + } else { + entity.addEffect(effect); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileRenderModes.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileRenderModes.java new file mode 100644 index 0000000000..2b8a985e20 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileRenderModes.java @@ -0,0 +1,128 @@ +package com.simibubi.create.content.equipment.potatoCannon; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.Create; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileRenderMode; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; + +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.core.Registry; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class AllPotatoProjectileRenderModes { + + static { + register("billboard", Billboard.CODEC); + register("tumble", Tumble.CODEC); + register("toward_motion", TowardMotion.CODEC); + register("stuck_to_entity", StuckToEntity.CODEC); + } + + public static void init() { + } + + private static void register(String name, Codec codec) { + Registry.register(CreateBuiltInRegistries.POTATO_PROJECTILE_RENDER_MODE, Create.asResource(name), codec); + } + + public enum Billboard implements PotatoProjectileRenderMode { + INSTANCE; + + public static final Codec CODEC = Codec.unit(INSTANCE); + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { + Minecraft mc = Minecraft.getInstance(); + Vec3 p1 = mc.getCameraEntity() + .getEyePosition(pt); + Vec3 diff = entity.getBoundingBox() + .getCenter() + .subtract(p1); + + TransformStack.of(ms) + .rotateYDegrees(AngleHelper.deg(Mth.atan2(diff.x, diff.z)) + 180) + .rotateXDegrees(AngleHelper.deg(Mth.atan2(diff.y, Mth.sqrt((float) (diff.x * diff.x + diff.z * diff.z))))); + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public enum Tumble implements PotatoProjectileRenderMode { + INSTANCE; + + public static final Codec CODEC = Codec.unit(INSTANCE); + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { + Billboard.INSTANCE.transform(ms, entity, pt); + TransformStack.of(ms) + .rotateZDegrees((entity.tickCount + pt) * 2 * entityRandom(entity, 16)) + .rotateXDegrees((entity.tickCount + pt) * entityRandom(entity, 32)); + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public record TowardMotion(int spriteAngleOffset, float spin) implements PotatoProjectileRenderMode { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.INT.fieldOf("sprite_angle_offset").forGetter(i -> i.spriteAngleOffset), + Codec.FLOAT.fieldOf("spin").forGetter(i -> i.spin) + ).apply(instance, TowardMotion::new)); + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { + Vec3 diff = entity.getDeltaMovement(); + TransformStack.of(ms) + .rotateYDegrees(AngleHelper.deg(Mth.atan2(diff.x, diff.z))) + .rotateXDegrees(270 + + AngleHelper.deg(Mth.atan2(diff.y, -Mth.sqrt((float) (diff.x * diff.x + diff.z * diff.z))))); + TransformStack.of(ms) + .rotateYDegrees((entity.tickCount + pt) * 20 * spin + entityRandom(entity, 360)) + .rotateZDegrees(-spriteAngleOffset); + } + + @Override + public Codec codec() { + return CODEC; + } + } + + public record StuckToEntity(Vec3 offset) implements PotatoProjectileRenderMode { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Vec3.CODEC.fieldOf("offset").forGetter(i -> i.offset) + ).apply(instance, StuckToEntity::new)); + + @Override + @OnlyIn(Dist.CLIENT) + public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { + TransformStack.of(ms).rotateYDegrees(AngleHelper.deg(Mth.atan2(offset.x, offset.z))); + } + + @Override + public Codec codec() { + return CODEC; + } + } + + private static int entityRandom(Entity entity, int maxValue) { + return (System.identityHashCode(entity) * 31) % maxValue; + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileTypes.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileTypes.java new file mode 100644 index 0000000000..33a9d12ed2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/AllPotatoProjectileTypes.java @@ -0,0 +1,290 @@ +package com.simibubi.create.content.equipment.potatoCannon; + +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileBlockHitActions.PlaceBlockOnGround; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileBlockHitActions.PlantCrop; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileEntityHitActions.ChorusTeleport; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileEntityHitActions.CureZombieVillager; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileEntityHitActions.FoodEffects; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileEntityHitActions.PotionEffect; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileEntityHitActions.SetOnFire; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileEntityHitActions.SuspiciousStew; + +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.food.Foods; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; + +public class AllPotatoProjectileTypes { + public static final ResourceKey FALLBACK = ResourceKey.create(CreateRegistries.POTATO_PROJECTILE_TYPE, Create.asResource("fallback")); + + public static void bootstrap(BootstapContext ctx) { + register(ctx, "fallback", new PotatoCannonProjectileType.Builder() + .damage(0) + .build()); + + register(ctx, "potato", new PotatoCannonProjectileType.Builder() + .damage(5) + .reloadTicks(15) + .velocity(1.25f) + .knockback(1.5f) + .renderTumbling() + .onBlockHit(new PlantCrop(Blocks.POTATOES)) + .addItems(Items.POTATO) + .build()); + + register(ctx, "baked_potato", new PotatoCannonProjectileType.Builder() + .damage(5) + .reloadTicks(15) + .velocity(1.25f) + .knockback(0.5f) + .renderTumbling() + .preEntityHit(SetOnFire.seconds(3)) + .addItems(Items.BAKED_POTATO) + .build()); + + register(ctx, "carrot", new PotatoCannonProjectileType.Builder() + .damage(4) + .reloadTicks(12) + .velocity(1.45f) + .knockback(0.3f) + .renderTowardMotion(140, 1) + .soundPitch(1.5f) + .onBlockHit(new PlantCrop(Blocks.CARROTS)) + .addItems(Items.CARROT) + .build()); + + register(ctx, "golden_carrot", new PotatoCannonProjectileType.Builder() + .damage(12) + .reloadTicks(15) + .velocity(1.45f) + .knockback(0.5f) + .renderTowardMotion(140, 2) + .soundPitch(1.5f) + .addItems(Items.GOLDEN_CARROT) + .build()); + + register(ctx, "sweet_berry", new PotatoCannonProjectileType.Builder() + .damage(3) + .reloadTicks(10) + .knockback(0.1f) + .velocity(1.05f) + .renderTumbling() + .splitInto(3) + .soundPitch(1.25f) + .addItems(Items.SWEET_BERRIES) + .build()); + + register(ctx, "glow_berry", new PotatoCannonProjectileType.Builder() + .damage(2) + .reloadTicks(10) + .knockback(0.05f) + .velocity(1.05f) + .renderTumbling() + .splitInto(2) + .soundPitch(1.2f) + .onEntityHit(new PotionEffect(MobEffects.GLOWING, 1, 200, false)) + .addItems(Items.GLOW_BERRIES) + .build()); + + register(ctx, "chocolate_berry", new PotatoCannonProjectileType.Builder() + .damage(4) + .reloadTicks(10) + .knockback(0.2f) + .velocity(1.05f) + .renderTumbling() + .splitInto(3) + .soundPitch(1.25f) + .addItems(AllItems.CHOCOLATE_BERRIES.get()) + .build()); + + register(ctx, "poison_potato", new PotatoCannonProjectileType.Builder() + .damage(5) + .reloadTicks(15) + .knockback(0.05f) + .velocity(1.25f) + .renderTumbling() + .onEntityHit(new PotionEffect(MobEffects.POISON, 1, 160, true)) + .addItems(Items.POISONOUS_POTATO) + .build()); + + register(ctx, "chorus_fruit", new PotatoCannonProjectileType.Builder() + .damage(3) + .reloadTicks(15) + .velocity(1.20f) + .knockback(0.05f) + .renderTumbling() + .onEntityHit(new ChorusTeleport(20)) + .addItems(Items.CHORUS_FRUIT) + .build()); + + register(ctx, "apple", new PotatoCannonProjectileType.Builder() + .damage(5) + .reloadTicks(10) + .velocity(1.45f) + .knockback(0.5f) + .renderTumbling() + .soundPitch(1.1f) + .addItems(Items.APPLE) + .build()); + + register(ctx, "honeyed_apple", new PotatoCannonProjectileType.Builder() + .damage(6) + .reloadTicks(15) + .velocity(1.35f) + .knockback(0.1f) + .renderTumbling() + .soundPitch(1.1f) + .onEntityHit(new PotionEffect(MobEffects.MOVEMENT_SLOWDOWN, 2, 160, true)) + .addItems(AllItems.HONEYED_APPLE.get()) + .build()); + + register(ctx, "golden_apple", new PotatoCannonProjectileType.Builder() + .damage(1) + .reloadTicks(100) + .velocity(1.45f) + .knockback(0.05f) + .renderTumbling() + .soundPitch(1.1f) + .onEntityHit(CureZombieVillager.INSTANCE) + .addItems(Items.GOLDEN_APPLE) + .build()); + + register(ctx, "enchanted_golden_apple", new PotatoCannonProjectileType.Builder() + .damage(1) + .reloadTicks(100) + .velocity(1.45f) + .knockback(0.05f) + .renderTumbling() + .soundPitch(1.1f) + .onEntityHit(new FoodEffects(Foods.ENCHANTED_GOLDEN_APPLE, false)) + .addItems(Items.ENCHANTED_GOLDEN_APPLE) + .build()); + + register(ctx, "beetroot", new PotatoCannonProjectileType.Builder() + .damage(2) + .reloadTicks(5) + .velocity(1.6f) + .knockback(0.1f) + .renderTowardMotion(140, 2) + .soundPitch(1.6f) + .addItems(Items.BEETROOT) + .build()); + + register(ctx, "melon_slice", new PotatoCannonProjectileType.Builder() + .damage(3) + .reloadTicks(8) + .knockback(0.1f) + .velocity(1.45f) + .renderTumbling() + .soundPitch(1.5f) + .addItems(Items.MELON_SLICE) + .build()); + + register(ctx, "glistering_melon", new PotatoCannonProjectileType.Builder() + .damage(5) + .reloadTicks(8) + .knockback(0.1f) + .velocity(1.45f) + .renderTumbling() + .soundPitch(1.5f) + .onEntityHit(new PotionEffect(MobEffects.GLOWING, 1, 100, true)) + .addItems(Items.GLISTERING_MELON_SLICE) + .build()); + + register(ctx, "melon_block", new PotatoCannonProjectileType.Builder() + .damage(8) + .reloadTicks(20) + .knockback(2.0f) + .velocity(0.95f) + .renderTumbling() + .soundPitch(0.9f) + .onBlockHit(new PlaceBlockOnGround(Blocks.MELON)) + .addItems(Blocks.MELON) + .build()); + + register(ctx, "pumpkin_block", new PotatoCannonProjectileType.Builder() + .damage(6) + .reloadTicks(15) + .knockback(2.0f) + .velocity(0.95f) + .renderTumbling() + .soundPitch(0.9f) + .onBlockHit(new PlaceBlockOnGround(Blocks.PUMPKIN)) + .addItems(Blocks.PUMPKIN) + .build()); + + register(ctx, "pumpkin_pie", new PotatoCannonProjectileType.Builder() + .damage(7) + .reloadTicks(15) + .knockback(0.05f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .soundPitch(1.1f) + .addItems(Items.PUMPKIN_PIE) + .build()); + + register(ctx, "cake", new PotatoCannonProjectileType.Builder() + .damage(8) + .reloadTicks(15) + .knockback(0.1f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .addItems(Items.CAKE) + .build()); + + register(ctx, "blaze_cake", new PotatoCannonProjectileType.Builder() + .damage(15) + .reloadTicks(20) + .knockback(0.3f) + .velocity(1.1f) + .renderTumbling() + .sticky() + .preEntityHit(SetOnFire.seconds(12)) + .addItems(AllItems.BLAZE_CAKE.get()) + .build()); + + register(ctx, "fish", new PotatoCannonProjectileType.Builder() + .damage(4) + .knockback(0.6f) + .velocity(1.3f) + .renderTowardMotion(140, 1) + .sticky() + .soundPitch(1.3f) + .addItems(Items.COD, Items.COOKED_COD, Items.SALMON, Items.COOKED_SALMON, Items.TROPICAL_FISH) + .build()); + + register(ctx, "pufferfish", new PotatoCannonProjectileType.Builder() + .damage(4) + .knockback(0.4f) + .velocity(1.1f) + .renderTowardMotion(140, 1) + .sticky() + .onEntityHit(new FoodEffects(Foods.PUFFERFISH, false)) + .soundPitch(1.1f) + .addItems(Items.PUFFERFISH) + .build()); + + register(ctx, "suspicious_stew", new PotatoCannonProjectileType.Builder() + .damage(3) + .reloadTicks(40) + .knockback(0.2f) + .velocity(0.8f) + .renderTowardMotion(140, 1) + .dropStack(Items.BOWL.getDefaultInstance()) + .onEntityHit(SuspiciousStew.INSTANCE) + .addItems(Items.SUSPICIOUS_STEW) + .build()); + } + + private static void register(BootstapContext ctx, String name, PotatoCannonProjectileType type) { + ctx.register(ResourceKey.create(CreateRegistries.POTATO_PROJECTILE_TYPE, Create.asResource(name)), type); + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/BuiltinPotatoProjectileTypes.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/BuiltinPotatoProjectileTypes.java deleted file mode 100644 index 3a3a70e1cb..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/BuiltinPotatoProjectileTypes.java +++ /dev/null @@ -1,421 +0,0 @@ -package com.simibubi.create.content.equipment.potatoCannon; - -import java.util.UUID; -import java.util.function.BiPredicate; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import com.mojang.authlib.GameProfile; -import com.mojang.datafixers.util.Pair; -import com.simibubi.create.AllItems; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.mixin.accessor.FallingBlockEntityAccessor; -import com.simibubi.create.foundation.utility.WorldAttached; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.Fox; -import net.minecraft.world.entity.item.FallingBlockEntity; -import net.minecraft.world.entity.monster.ZombieVillager; -import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.food.Foods; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.EntityHitResult; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.IPlantable; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.event.ForgeEventFactory; -import net.minecraftforge.event.entity.EntityTeleportEvent; -import net.minecraftforge.registries.ForgeRegistries; - -public class BuiltinPotatoProjectileTypes { - - private static final GameProfile ZOMBIE_CONVERTER_NAME = - new GameProfile(UUID.fromString("be12d3dc-27d3-4992-8c97-66be53fd49c5"), "Converter"); - private static final WorldAttached ZOMBIE_CONVERTERS = - new WorldAttached<>(w -> new FakePlayer((ServerLevel) w, ZOMBIE_CONVERTER_NAME)); - - public static final PotatoCannonProjectileType - - FALLBACK = create("fallback").damage(0) - .register(), - - POTATO = create("potato").damage(5) - .reloadTicks(15) - .velocity(1.25f) - .knockback(1.5f) - .renderTumbling() - .onBlockHit(plantCrop(Blocks.POTATOES)) - .registerAndAssign(Items.POTATO), - - BAKED_POTATO = create("baked_potato").damage(5) - .reloadTicks(15) - .velocity(1.25f) - .knockback(0.5f) - .renderTumbling() - .preEntityHit(setFire(3)) - .registerAndAssign(Items.BAKED_POTATO), - - CARROT = create("carrot").damage(4) - .reloadTicks(12) - .velocity(1.45f) - .knockback(0.3f) - .renderTowardMotion(140, 1) - .soundPitch(1.5f) - .onBlockHit(plantCrop(Blocks.CARROTS)) - .registerAndAssign(Items.CARROT), - - GOLDEN_CARROT = create("golden_carrot").damage(12) - .reloadTicks(15) - .velocity(1.45f) - .knockback(0.5f) - .renderTowardMotion(140, 2) - .soundPitch(1.5f) - .registerAndAssign(Items.GOLDEN_CARROT), - - SWEET_BERRIES = create("sweet_berry").damage(3) - .reloadTicks(10) - .knockback(0.1f) - .velocity(1.05f) - .renderTumbling() - .splitInto(3) - .soundPitch(1.25f) - .registerAndAssign(Items.SWEET_BERRIES), - - GLOW_BERRIES = create("glow_berry").damage(2) - .reloadTicks(10) - .knockback(0.05f) - .velocity(1.05f) - .renderTumbling() - .splitInto(2) - .soundPitch(1.2f) - .onEntityHit(potion(MobEffects.GLOWING, 1, 200, false)) - .registerAndAssign(Items.GLOW_BERRIES), - - CHOCOLATE_BERRIES = create("chocolate_berry").damage(4) - .reloadTicks(10) - .knockback(0.2f) - .velocity(1.05f) - .renderTumbling() - .splitInto(3) - .soundPitch(1.25f) - .registerAndAssign(AllItems.CHOCOLATE_BERRIES.get()), - - POISON_POTATO = create("poison_potato").damage(5) - .reloadTicks(15) - .knockback(0.05f) - .velocity(1.25f) - .renderTumbling() - .onEntityHit(potion(MobEffects.POISON, 1, 160, true)) - .registerAndAssign(Items.POISONOUS_POTATO), - - CHORUS_FRUIT = create("chorus_fruit").damage(3) - .reloadTicks(15) - .velocity(1.20f) - .knockback(0.05f) - .renderTumbling() - .onEntityHit(chorusTeleport(20)) - .registerAndAssign(Items.CHORUS_FRUIT), - - APPLE = create("apple").damage(5) - .reloadTicks(10) - .velocity(1.45f) - .knockback(0.5f) - .renderTumbling() - .soundPitch(1.1f) - .registerAndAssign(Items.APPLE), - - HONEYED_APPLE = create("honeyed_apple").damage(6) - .reloadTicks(15) - .velocity(1.35f) - .knockback(0.1f) - .renderTumbling() - .soundPitch(1.1f) - .onEntityHit(potion(MobEffects.MOVEMENT_SLOWDOWN, 2, 160, true)) - .registerAndAssign(AllItems.HONEYED_APPLE.get()), - - GOLDEN_APPLE = create("golden_apple").damage(1) - .reloadTicks(100) - .velocity(1.45f) - .knockback(0.05f) - .renderTumbling() - .soundPitch(1.1f) - .onEntityHit(ray -> { - Entity entity = ray.getEntity(); - Level world = entity.level(); - - if (!(entity instanceof ZombieVillager) || !((ZombieVillager) entity).hasEffect(MobEffects.WEAKNESS)) - return foodEffects(Foods.GOLDEN_APPLE, false).test(ray); - if (world.isClientSide) - return false; - - FakePlayer dummy = ZOMBIE_CONVERTERS.get(world); - dummy.setItemInHand(InteractionHand.MAIN_HAND, new ItemStack(Items.GOLDEN_APPLE, 1)); - ((ZombieVillager) entity).mobInteract(dummy, InteractionHand.MAIN_HAND); - return true; - }) - .registerAndAssign(Items.GOLDEN_APPLE), - - ENCHANTED_GOLDEN_APPLE = create("enchanted_golden_apple").damage(1) - .reloadTicks(100) - .velocity(1.45f) - .knockback(0.05f) - .renderTumbling() - .soundPitch(1.1f) - .onEntityHit(foodEffects(Foods.ENCHANTED_GOLDEN_APPLE, false)) - .registerAndAssign(Items.ENCHANTED_GOLDEN_APPLE), - - BEETROOT = create("beetroot").damage(2) - .reloadTicks(5) - .velocity(1.6f) - .knockback(0.1f) - .renderTowardMotion(140, 2) - .soundPitch(1.6f) - .registerAndAssign(Items.BEETROOT), - - MELON_SLICE = create("melon_slice").damage(3) - .reloadTicks(8) - .knockback(0.1f) - .velocity(1.45f) - .renderTumbling() - .soundPitch(1.5f) - .registerAndAssign(Items.MELON_SLICE), - - GLISTERING_MELON = create("glistering_melon").damage(5) - .reloadTicks(8) - .knockback(0.1f) - .velocity(1.45f) - .renderTumbling() - .soundPitch(1.5f) - .onEntityHit(potion(MobEffects.GLOWING, 1, 100, true)) - .registerAndAssign(Items.GLISTERING_MELON_SLICE), - - MELON_BLOCK = create("melon_block").damage(8) - .reloadTicks(20) - .knockback(2.0f) - .velocity(0.95f) - .renderTumbling() - .soundPitch(0.9f) - .onBlockHit(placeBlockOnGround(Blocks.MELON)) - .registerAndAssign(Blocks.MELON), - - PUMPKIN_BLOCK = create("pumpkin_block").damage(6) - .reloadTicks(15) - .knockback(2.0f) - .velocity(0.95f) - .renderTumbling() - .soundPitch(0.9f) - .onBlockHit(placeBlockOnGround(Blocks.PUMPKIN)) - .registerAndAssign(Blocks.PUMPKIN), - - PUMPKIN_PIE = create("pumpkin_pie").damage(7) - .reloadTicks(15) - .knockback(0.05f) - .velocity(1.1f) - .renderTumbling() - .sticky() - .soundPitch(1.1f) - .registerAndAssign(Items.PUMPKIN_PIE), - - CAKE = create("cake").damage(8) - .reloadTicks(15) - .knockback(0.1f) - .velocity(1.1f) - .renderTumbling() - .sticky() - .soundPitch(1.0f) - .registerAndAssign(Items.CAKE), - - BLAZE_CAKE = create("blaze_cake").damage(15) - .reloadTicks(20) - .knockback(0.3f) - .velocity(1.1f) - .renderTumbling() - .sticky() - .preEntityHit(setFire(12)) - .soundPitch(1.0f) - .registerAndAssign(AllItems.BLAZE_CAKE.get()) - - ; - - private static PotatoCannonProjectileType.Builder create(String name) { - return new PotatoCannonProjectileType.Builder(Create.asResource(name)); - } - - private static Predicate setFire(int seconds) { - return ray -> { - ray.getEntity() - .setSecondsOnFire(seconds); - return false; - }; - } - - private static Predicate potion(MobEffect effect, int level, int ticks, boolean recoverable) { - return ray -> { - Entity entity = ray.getEntity(); - if (entity.level().isClientSide) - return true; - if (entity instanceof LivingEntity) - applyEffect((LivingEntity) entity, new MobEffectInstance(effect, ticks, level - 1)); - return !recoverable; - }; - } - - private static Predicate foodEffects(FoodProperties food, boolean recoverable) { - return ray -> { - Entity entity = ray.getEntity(); - if (entity.level().isClientSide) - return true; - - if (entity instanceof LivingEntity) { - for (Pair effect : food.getEffects()) { - if (Create.RANDOM.nextFloat() < effect.getSecond()) - applyEffect((LivingEntity) entity, new MobEffectInstance(effect.getFirst())); - } - } - return !recoverable; - }; - } - - private static void applyEffect(LivingEntity entity, MobEffectInstance effect) { - if (effect.getEffect() - .isInstantenous()) - effect.getEffect() - .applyInstantenousEffect(null, null, entity, effect.getDuration(), 1.0); - else - entity.addEffect(effect); - } - - private static BiPredicate plantCrop(Supplier cropBlock) { - return (world, ray) -> { - if (world.isClientSide()) - return true; - - BlockPos hitPos = ray.getBlockPos(); - if (world instanceof Level l && !l.isLoaded(hitPos)) - return true; - Direction face = ray.getDirection(); - if (face != Direction.UP) - return false; - BlockPos placePos = hitPos.relative(face); - if (!world.getBlockState(placePos) - .canBeReplaced()) - return false; - if (!(cropBlock.get() instanceof IPlantable)) - return false; - BlockState blockState = world.getBlockState(hitPos); - if (!blockState.canSustainPlant(world, hitPos, face, (IPlantable) cropBlock.get())) - return false; - world.setBlock(placePos, cropBlock.get() - .defaultBlockState(), 3); - return true; - }; - } - - private static BiPredicate plantCrop(Block cropBlock) { - return plantCrop(ForgeRegistries.BLOCKS.getDelegateOrThrow(cropBlock)); - } - - private static BiPredicate placeBlockOnGround( - Supplier block) { - return (world, ray) -> { - if (world.isClientSide()) - return true; - - BlockPos hitPos = ray.getBlockPos(); - if (world instanceof Level l && !l.isLoaded(hitPos)) - return true; - Direction face = ray.getDirection(); - BlockPos placePos = hitPos.relative(face); - if (!world.getBlockState(placePos) - .canBeReplaced()) - return false; - - if (face == Direction.UP) { - world.setBlock(placePos, block.get() - .defaultBlockState(), 3); - } else if (world instanceof Level level) { - double y = ray.getLocation().y - 0.5; - if (!world.isEmptyBlock(placePos.above())) - y = Math.min(y, placePos.getY()); - if (!world.isEmptyBlock(placePos.below())) - y = Math.max(y, placePos.getY()); - - FallingBlockEntity falling = FallingBlockEntityAccessor.create$callInit(level, placePos.getX() + 0.5, y, - placePos.getZ() + 0.5, block.get().defaultBlockState()); - falling.time = 1; - world.addFreshEntity(falling); - } - - return true; - }; - } - - private static BiPredicate placeBlockOnGround(Block block) { - return placeBlockOnGround(ForgeRegistries.BLOCKS.getDelegateOrThrow(block)); - } - - private static Predicate chorusTeleport(double teleportDiameter) { - return ray -> { - Entity entity = ray.getEntity(); - Level world = entity.getCommandSenderWorld(); - if (world.isClientSide) - return true; - if (!(entity instanceof LivingEntity)) - return false; - LivingEntity livingEntity = (LivingEntity) entity; - - double entityX = livingEntity.getX(); - double entityY = livingEntity.getY(); - double entityZ = livingEntity.getZ(); - - for (int teleportTry = 0; teleportTry < 16; ++teleportTry) { - double teleportX = entityX + (livingEntity.getRandom() - .nextDouble() - 0.5D) * teleportDiameter; - double teleportY = Mth.clamp(entityY + (livingEntity.getRandom() - .nextInt((int) teleportDiameter) - (int) (teleportDiameter / 2)), 0.0D, world.getHeight() - 1); - double teleportZ = entityZ + (livingEntity.getRandom() - .nextDouble() - 0.5D) * teleportDiameter; - - EntityTeleportEvent.ChorusFruit event = - ForgeEventFactory.onChorusFruitTeleport(livingEntity, teleportX, teleportY, teleportZ); - if (event.isCanceled()) - return false; - if (livingEntity.randomTeleport(event.getTargetX(), event.getTargetY(), event.getTargetZ(), true)) { - if (livingEntity.isPassenger()) - livingEntity.stopRiding(); - - SoundEvent soundevent = - livingEntity instanceof Fox ? SoundEvents.FOX_TELEPORT : SoundEvents.CHORUS_FRUIT_TELEPORT; - world.playSound(null, entityX, entityY, entityZ, soundevent, SoundSource.PLAYERS, 1.0F, 1.0F); - livingEntity.playSound(soundevent, 1.0F, 1.0F); - livingEntity.setDeltaMovement(Vec3.ZERO); - return true; - } - } - - return false; - }; - } - - public static void register() {} - -} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItem.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItem.java index 1e56bfae67..312c717f39 100644 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItem.java @@ -9,18 +9,17 @@ import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllEnchantments; import com.simibubi.create.AllEntityTypes; -import com.simibubi.create.Create; import com.simibubi.create.CreateClient; +import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType; import com.simibubi.create.content.equipment.armor.BacktankUtil; import com.simibubi.create.content.equipment.zapper.ShootableGadgetItemMethods; import com.simibubi.create.foundation.item.CustomArmPoseItem; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import com.simibubi.create.foundation.utility.GlobalRegistryAccess; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.model.HumanoidModel.ArmPose; @@ -28,6 +27,8 @@ import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Holder; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; @@ -46,24 +47,192 @@ import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientItemExtensions; public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmPoseItem { - public static ItemStack CLIENT_CURRENT_AMMO = ItemStack.EMPTY; public static final int MAX_DAMAGE = 100; public PotatoCannonItem(Properties properties) { super(properties.defaultDurability(MAX_DAMAGE)); } + @Nullable + public static Ammo getAmmo(Player player, ItemStack heldStack) { + ItemStack ammoStack = player.getProjectile(heldStack); + if (ammoStack.isEmpty()) { + return null; + } + + Optional> optionalType = PotatoCannonProjectileType.getTypeForItem(player.level().registryAccess(), ammoStack.getItem()); + if (optionalType.isEmpty()) { + return null; + } + + return new Ammo(ammoStack, optionalType.get().get()); + } + + @Override + public InteractionResult useOn(UseOnContext context) { + return use(context.getLevel(), context.getPlayer(), context.getHand()).getResult(); + } + + @Override + public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { + ItemStack heldStack = player.getItemInHand(hand); + if (ShootableGadgetItemMethods.shouldSwap(player, heldStack, hand, s -> s.getItem() instanceof PotatoCannonItem)) { + return InteractionResultHolder.fail(heldStack); + } + + Ammo ammo = getAmmo(player, heldStack); + if (ammo == null) { + return InteractionResultHolder.pass(heldStack); + } + ItemStack ammoStack = ammo.stack(); + PotatoCannonProjectileType projectileType = ammo.type(); + + if (level.isClientSide) { + CreateClient.POTATO_CANNON_RENDER_HANDLER.dontAnimateItem(hand); + return InteractionResultHolder.success(heldStack); + } + + Vec3 barrelPos = ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND, + new Vec3(.75f, -0.15f, 1.5f)); + Vec3 correction = + ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND, new Vec3(-.05f, 0, 0)) + .subtract(player.position() + .add(0, player.getEyeHeight(), 0)); + + Vec3 lookVec = player.getLookAngle(); + Vec3 motion = lookVec.add(correction) + .normalize() + .scale(2) + .scale(projectileType.velocityMultiplier()); + + float soundPitch = projectileType.soundPitch() + (level.getRandom().nextFloat() - .5f) / 4f; + + boolean spray = projectileType.split() > 1; + Vec3 sprayBase = VecHelper.rotate(new Vec3(0, 0.1, 0), 360 * level.getRandom().nextFloat(), Axis.Z); + float sprayChange = 360f / projectileType.split(); + + ItemStack ammoStackCopy = ammoStack.copy(); + + for (int i = 0; i < projectileType.split(); i++) { + PotatoProjectileEntity projectile = AllEntityTypes.POTATO_PROJECTILE.create(level); + projectile.setItem(ammoStackCopy); + projectile.setEnchantmentEffectsFromCannon(heldStack); + + Vec3 splitMotion = motion; + if (spray) { + float imperfection = 40 * (level.getRandom().nextFloat() - 0.5f); + Vec3 sprayOffset = VecHelper.rotate(sprayBase, i * sprayChange + imperfection, Axis.Z); + splitMotion = splitMotion.add(VecHelper.lookAt(sprayOffset, motion)); + } + + if (i != 0) + projectile.recoveryChance = 0; + + projectile.setPos(barrelPos.x, barrelPos.y, barrelPos.z); + projectile.setDeltaMovement(splitMotion); + projectile.setOwner(player); + level.addFreshEntity(projectile); + } + + if (!player.isCreative()) { + ammoStack.shrink(1); + if (ammoStack.isEmpty()) + player.getInventory().removeItem(ammoStack); + } + + if (!BacktankUtil.canAbsorbDamage(player, maxUses())) + heldStack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); + + ShootableGadgetItemMethods.applyCooldown(player, heldStack, hand, s -> s.getItem() instanceof PotatoCannonItem, projectileType.reloadTicks()); + ShootableGadgetItemMethods.sendPackets(player, + b -> new PotatoCannonPacket(barrelPos, lookVec.normalize(), ammoStack, hand, soundPitch, b)); + return InteractionResultHolder.success(heldStack); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) { + super.appendHoverText(stack, level, tooltip, flag); + return; + } + + Ammo ammo = getAmmo(player, stack); + if (ammo == null) { + super.appendHoverText(stack, level, tooltip, flag); + return; + } + ItemStack ammoStack = ammo.stack(); + PotatoCannonProjectileType type = ammo.type(); + + int power = stack.getEnchantmentLevel(Enchantments.POWER_ARROWS); + int punch = stack.getEnchantmentLevel(Enchantments.PUNCH_ARROWS); + final float additionalDamageMult = 1 + power * .2f; + final float additionalKnockback = punch * .5f; + + String _attack = "potato_cannon.ammo.attack_damage"; + String _reload = "potato_cannon.ammo.reload_ticks"; + String _knockback = "potato_cannon.ammo.knockback"; + + tooltip.add(CommonComponents.EMPTY); + tooltip.add(Component.translatable(ammoStack.getDescriptionId()).append(Component.literal(":")) + .withStyle(ChatFormatting.GRAY)); + MutableComponent spacing = CommonComponents.space(); + ChatFormatting green = ChatFormatting.GREEN; + ChatFormatting darkGreen = ChatFormatting.DARK_GREEN; + + float damageF = type.damage() * additionalDamageMult; + MutableComponent damage = Component.literal(damageF == Mth.floor(damageF) ? "" + Mth.floor(damageF) : "" + damageF); + MutableComponent reloadTicks = Component.literal("" + type.reloadTicks()); + MutableComponent knockback = + Component.literal("" + (type.knockback() + additionalKnockback)); + + damage = damage.withStyle(additionalDamageMult > 1 ? green : darkGreen); + knockback = knockback.withStyle(additionalKnockback > 0 ? green : darkGreen); + reloadTicks = reloadTicks.withStyle(darkGreen); + + tooltip.add(spacing.plainCopy() + .append(CreateLang.translateDirect(_attack, damage) + .withStyle(darkGreen))); + tooltip.add(spacing.plainCopy() + .append(CreateLang.translateDirect(_reload, reloadTicks) + .withStyle(darkGreen))); + tooltip.add(spacing.plainCopy() + .append(CreateLang.translateDirect(_knockback, knockback) + .withStyle(darkGreen))); + + super.appendHoverText(stack, level, tooltip, flag); + } + @Override public boolean canAttackBlock(BlockState state, Level world, BlockPos pos, Player player) { return false; } + @Override + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { + return slotChanged || newStack.getItem() != oldStack.getItem(); + } + + @Override + public Predicate getAllSupportedProjectiles() { + return stack -> PotatoCannonProjectileType.getTypeForItem(GlobalRegistryAccess.getOrThrow(), stack.getItem()) + .isPresent(); + } + + @Override + public int getDefaultProjectileRange() { + return 15; + } + @Override public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { if (enchantment == Enchantments.POWER_ARROWS) @@ -79,11 +248,6 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP return super.canApplyAtEnchantingTable(stack, enchantment); } - @Override - public InteractionResult useOn(UseOnContext context) { - return use(context.getLevel(), context.getPlayer(), context.getHand()).getResult(); - } - @Override public boolean isBarVisible(ItemStack stack) { return BacktankUtil.isBarVisible(stack, maxUses()); @@ -99,171 +263,10 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP return BacktankUtil.getBarColor(stack, maxUses()); } - private int maxUses() { + private static int maxUses() { return AllConfigs.server().equipment.maxPotatoCannonShots.get(); } - public boolean isCannon(ItemStack stack) { - return stack.getItem() instanceof PotatoCannonItem; - } - - @Override - public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { - ItemStack stack = player.getItemInHand(hand); - return findAmmoInInventory(world, player, stack).map(itemStack -> { - - if (ShootableGadgetItemMethods.shouldSwap(player, stack, hand, this::isCannon)) - return InteractionResultHolder.fail(stack); - - if (world.isClientSide) { - CreateClient.POTATO_CANNON_RENDER_HANDLER.dontAnimateItem(hand); - return InteractionResultHolder.success(stack); - } - - Vec3 barrelPos = ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND, - new Vec3(.75f, -0.15f, 1.5f)); - Vec3 correction = - ShootableGadgetItemMethods.getGunBarrelVec(player, hand == InteractionHand.MAIN_HAND, new Vec3(-.05f, 0, 0)) - .subtract(player.position() - .add(0, player.getEyeHeight(), 0)); - - PotatoCannonProjectileType projectileType = PotatoProjectileTypeManager.getTypeForStack(itemStack) - .orElse(BuiltinPotatoProjectileTypes.FALLBACK); - Vec3 lookVec = player.getLookAngle(); - Vec3 motion = lookVec.add(correction) - .normalize() - .scale(2) - .scale(projectileType.getVelocityMultiplier()); - - float soundPitch = projectileType.getSoundPitch() + (Create.RANDOM.nextFloat() - .5f) / 4f; - - boolean spray = projectileType.getSplit() > 1; - Vec3 sprayBase = VecHelper.rotate(new Vec3(0, 0.1, 0), 360 * Create.RANDOM.nextFloat(), Axis.Z); - float sprayChange = 360f / projectileType.getSplit(); - - for (int i = 0; i < projectileType.getSplit(); i++) { - PotatoProjectileEntity projectile = AllEntityTypes.POTATO_PROJECTILE.create(world); - projectile.setItem(itemStack); - projectile.setEnchantmentEffectsFromCannon(stack); - - Vec3 splitMotion = motion; - if (spray) { - float imperfection = 40 * (Create.RANDOM.nextFloat() - 0.5f); - Vec3 sprayOffset = VecHelper.rotate(sprayBase, i * sprayChange + imperfection, Axis.Z); - splitMotion = splitMotion.add(VecHelper.lookAt(sprayOffset, motion)); - } - - if (i != 0) - projectile.recoveryChance = 0; - - projectile.setPos(barrelPos.x, barrelPos.y, barrelPos.z); - projectile.setDeltaMovement(splitMotion); - projectile.setOwner(player); - world.addFreshEntity(projectile); - } - - if (!player.isCreative()) { - itemStack.shrink(1); - if (itemStack.isEmpty()) - player.getInventory().removeItem(itemStack); - } - - if (!BacktankUtil.canAbsorbDamage(player, maxUses())) - stack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); - - Integer cooldown = - findAmmoInInventory(world, player, stack).flatMap(PotatoProjectileTypeManager::getTypeForStack) - .map(PotatoCannonProjectileType::getReloadTicks) - .orElse(10); - - ShootableGadgetItemMethods.applyCooldown(player, stack, hand, this::isCannon, cooldown); - ShootableGadgetItemMethods.sendPackets(player, - b -> new PotatoCannonPacket(barrelPos, lookVec.normalize(), itemStack, hand, soundPitch, b)); - return InteractionResultHolder.success(stack); - }) - .orElse(InteractionResultHolder.pass(stack)); - } - - @Override - public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { - return slotChanged || newStack.getItem() != oldStack.getItem(); - } - - private Optional findAmmoInInventory(Level world, Player player, ItemStack held) { - ItemStack findAmmo = player.getProjectile(held); - return PotatoProjectileTypeManager.getTypeForStack(findAmmo) - .map($ -> findAmmo); - } - - @OnlyIn(Dist.CLIENT) - public static Optional getAmmoforPreview(ItemStack cannon) { - if (AnimationTickHolder.getTicks() % 3 != 0) - return Optional.of(CLIENT_CURRENT_AMMO) - .filter(stack -> !stack.isEmpty()); - - LocalPlayer player = Minecraft.getInstance().player; - CLIENT_CURRENT_AMMO = ItemStack.EMPTY; - if (player == null) - return Optional.empty(); - ItemStack findAmmo = player.getProjectile(cannon); - Optional found = PotatoProjectileTypeManager.getTypeForStack(findAmmo) - .map($ -> findAmmo); - found.ifPresent(stack -> CLIENT_CURRENT_AMMO = stack); - return found; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, Level world, List tooltip, TooltipFlag flag) { - int power = stack.getEnchantmentLevel(Enchantments.POWER_ARROWS); - int punch = stack.getEnchantmentLevel(Enchantments.PUNCH_ARROWS); - final float additionalDamageMult = 1 + power * .2f; - final float additionalKnockback = punch * .5f; - - getAmmoforPreview(stack).ifPresent(ammo -> { - String _attack = "potato_cannon.ammo.attack_damage"; - String _reload = "potato_cannon.ammo.reload_ticks"; - String _knockback = "potato_cannon.ammo.knockback"; - - tooltip.add(Components.immutableEmpty()); - tooltip.add(Components.translatable(ammo.getDescriptionId()).append(Components.literal(":")) - .withStyle(ChatFormatting.GRAY)); - PotatoCannonProjectileType type = PotatoProjectileTypeManager.getTypeForStack(ammo) - .get(); - MutableComponent spacing = Components.literal(" "); - ChatFormatting green = ChatFormatting.GREEN; - ChatFormatting darkGreen = ChatFormatting.DARK_GREEN; - - float damageF = type.getDamage() * additionalDamageMult; - MutableComponent damage = Components.literal( - damageF == Mth.floor(damageF) ? "" + Mth.floor(damageF) : "" + damageF); - MutableComponent reloadTicks = Components.literal("" + type.getReloadTicks()); - MutableComponent knockback = - Components.literal("" + (type.getKnockback() + additionalKnockback)); - - damage = damage.withStyle(additionalDamageMult > 1 ? green : darkGreen); - knockback = knockback.withStyle(additionalKnockback > 0 ? green : darkGreen); - reloadTicks = reloadTicks.withStyle(darkGreen); - - tooltip.add(spacing.plainCopy() - .append(Lang.translateDirect(_attack, damage) - .withStyle(darkGreen))); - tooltip.add(spacing.plainCopy() - .append(Lang.translateDirect(_reload, reloadTicks) - .withStyle(darkGreen))); - tooltip.add(spacing.plainCopy() - .append(Lang.translateDirect(_knockback, knockback) - .withStyle(darkGreen))); - }); - super.appendHoverText(stack, world, tooltip, flag); - } - - @Override - public Predicate getAllSupportedProjectiles() { - return stack -> PotatoProjectileTypeManager.getTypeForStack(stack) - .isPresent(); - } - @Override public boolean onEntitySwing(ItemStack stack, LivingEntity entity) { return true; @@ -283,15 +286,12 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP return null; } - @Override - public int getDefaultProjectileRange() { - return 15; - } - @Override @OnlyIn(Dist.CLIENT) public void initializeClient(Consumer consumer) { consumer.accept(SimpleCustomRenderer.create(this, new PotatoCannonItemRenderer())); } + public record Ammo(ItemStack stack, PotatoCannonProjectileType type) { + } } diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItemRenderer.java index 22983f9366..37b0897f19 100644 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItemRenderer.java @@ -2,49 +2,72 @@ package com.simibubi.create.content.equipment.potatoCannon; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; +import com.simibubi.create.AllItems; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; +import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItem.Ammo; import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; -import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.util.Mth; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.client.IItemDecorator; + public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer { + public static final IItemDecorator DECORATOR = (guiGraphics, font, stack, xOffset, yOffset) -> { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) { + return false; + } + + Ammo ammo = PotatoCannonItem.getAmmo(player, stack); + if (ammo == null || AllItems.POTATO_CANNON.is(ammo.stack())) { + return false; + } + + PoseStack poseStack = guiGraphics.pose(); + poseStack.pushPose(); + poseStack.translate(xOffset, yOffset + 8, 100); + poseStack.scale(.5f, .5f, .5f); + guiGraphics.renderItem(ammo.stack(), 0, 0); + poseStack.popPose(); + return false; + }; protected static final PartialModel COG = PartialModel.of(Create.asResource("item/potato_cannon/cog")); @Override protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, - ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - Minecraft mc = Minecraft.getInstance(); - ItemRenderer itemRenderer = mc.getItemRenderer(); + ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { renderer.render(model.getOriginalModel(), light); + Minecraft mc = Minecraft.getInstance(); LocalPlayer player = mc.player; - boolean mainHand = player.getMainHandItem() == stack; - boolean offHand = player.getOffhandItem() == stack; - boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT; - float offset = .5f / 16; - float worldTime = AnimationTickHolder.getRenderTime() / 10; - float angle = worldTime * -25; - float speed = CreateClient.POTATO_CANNON_RENDER_HANDLER.getAnimation(mainHand ^ leftHanded, - AnimationTickHolder.getPartialTicks()); + float angle = AnimationTickHolder.getRenderTime() * -2.5f; + + if (player != null) { + boolean inMainHand = player.getMainHandItem() == stack; + boolean inOffHand = player.getOffhandItem() == stack; + + if (inMainHand || inOffHand) { + boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT; + float speed = CreateClient.POTATO_CANNON_RENDER_HANDLER.getAnimation(inMainHand ^ leftHanded, + AnimationTickHolder.getPartialTicks()); + angle += 360 * Mth.clamp(speed * 5, 0, 1); + } + } - if (mainHand || offHand) - angle += 360 * Mth.clamp(speed * 5, 0, 1); angle %= 360; + float offset = .5f / 16; ms.pushPose(); ms.translate(0, offset, 0); @@ -52,20 +75,5 @@ public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer { ms.translate(0, -offset, 0); renderer.render(COG.get(), light); ms.popPose(); - - if (transformType == ItemDisplayContext.GUI) { - PotatoCannonItem.getAmmoforPreview(stack) - .ifPresent(ammo -> { - PoseStack localMs = new PoseStack(); - localMs.translate(-1 / 4f, -1 / 4f, 1); - localMs.scale(.5f, .5f, .5f); - TransformStack.of(localMs) - .rotateYDegrees(-34); - itemRenderer.renderStatic(ammo, ItemDisplayContext.GUI, light, OverlayTexture.NO_OVERLAY, localMs, - buffer, mc.level, 0); - }); - } - } - } diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonProjectileType.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonProjectileType.java deleted file mode 100644 index fbbd7f1f96..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonProjectileType.java +++ /dev/null @@ -1,298 +0,0 @@ -package com.simibubi.create.content.equipment.potatoCannon; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.BiPredicate; -import java.util.function.Consumer; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.simibubi.create.foundation.utility.RegisteredObjects; - -import net.minecraft.ResourceLocationException; -import net.minecraft.core.Holder; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.EntityHitResult; -import net.minecraftforge.registries.ForgeRegistries; - -public class PotatoCannonProjectileType { - - private List> items = new ArrayList<>(); - - private int reloadTicks = 10; - private int damage = 1; - private int split = 1; - private float knockback = 1; - private float drag = 0.99f; - private float velocityMultiplier = 1; - private float gravityMultiplier = 1; - private float soundPitch = 1; - private boolean sticky = false; - private PotatoProjectileRenderMode renderMode = PotatoProjectileRenderMode.Billboard.INSTANCE; - - private Predicate preEntityHit = e -> false; // True if hit should be canceled - private Predicate onEntityHit = e -> false; // True if shouldn't recover projectile - private BiPredicate onBlockHit = (w, ray) -> false; - - protected PotatoCannonProjectileType() { - } - - public List> getItems() { - return items; - } - - public int getReloadTicks() { - return reloadTicks; - } - - public int getDamage() { - return damage; - } - - public int getSplit() { - return split; - } - - public float getKnockback() { - return knockback; - } - - public float getDrag() { - return drag; - } - - public float getVelocityMultiplier() { - return velocityMultiplier; - } - - public float getGravityMultiplier() { - return gravityMultiplier; - } - - public float getSoundPitch() { - return soundPitch; - } - - public boolean isSticky() { - return sticky; - } - - public PotatoProjectileRenderMode getRenderMode() { - return renderMode; - } - - public boolean preEntityHit(EntityHitResult ray) { - return preEntityHit.test(ray); - } - - public boolean onEntityHit(EntityHitResult ray) { - return onEntityHit.test(ray); - } - - public boolean onBlockHit(LevelAccessor world, BlockHitResult ray) { - return onBlockHit.test(world, ray); - } - - public static PotatoCannonProjectileType fromJson(JsonObject object) { - PotatoCannonProjectileType type = new PotatoCannonProjectileType(); - try { - JsonElement itemsElement = object.get("items"); - if (itemsElement != null && itemsElement.isJsonArray()) { - for (JsonElement element : itemsElement.getAsJsonArray()) { - if (element.isJsonPrimitive()) { - JsonPrimitive primitive = element.getAsJsonPrimitive(); - if (primitive.isString()) { - try { - Optional> reference = ForgeRegistries.ITEMS.getDelegate(new ResourceLocation(primitive.getAsString())); - if (reference.isPresent()) { - type.items.add(reference.get()); - } - } catch (ResourceLocationException e) { - // - } - } - } - } - } - - parseJsonPrimitive(object, "reload_ticks", JsonPrimitive::isNumber, primitive -> type.reloadTicks = primitive.getAsInt()); - parseJsonPrimitive(object, "damage", JsonPrimitive::isNumber, primitive -> type.damage = primitive.getAsInt()); - parseJsonPrimitive(object, "split", JsonPrimitive::isNumber, primitive -> type.split = primitive.getAsInt()); - parseJsonPrimitive(object, "knockback", JsonPrimitive::isNumber, primitive -> type.knockback = primitive.getAsFloat()); - parseJsonPrimitive(object, "drag", JsonPrimitive::isNumber, primitive -> type.drag = primitive.getAsFloat()); - parseJsonPrimitive(object, "velocity_multiplier", JsonPrimitive::isNumber, primitive -> type.velocityMultiplier = primitive.getAsFloat()); - parseJsonPrimitive(object, "gravity_multiplier", JsonPrimitive::isNumber, primitive -> type.gravityMultiplier = primitive.getAsFloat()); - parseJsonPrimitive(object, "sound_pitch", JsonPrimitive::isNumber, primitive -> type.soundPitch = primitive.getAsFloat()); - parseJsonPrimitive(object, "sticky", JsonPrimitive::isBoolean, primitive -> type.sticky = primitive.getAsBoolean()); - } catch (Exception e) { - // - } - return type; - } - - private static void parseJsonPrimitive(JsonObject object, String key, Predicate predicate, Consumer consumer) { - JsonElement element = object.get(key); - if (element != null && element.isJsonPrimitive()) { - JsonPrimitive primitive = element.getAsJsonPrimitive(); - if (predicate.test(primitive)) { - consumer.accept(primitive); - } - } - } - - public static void toBuffer(PotatoCannonProjectileType type, FriendlyByteBuf buffer) { - buffer.writeVarInt(type.items.size()); - for (Supplier delegate : type.items) { - buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow(delegate.get())); - } - buffer.writeInt(type.reloadTicks); - buffer.writeInt(type.damage); - buffer.writeInt(type.split); - buffer.writeFloat(type.knockback); - buffer.writeFloat(type.drag); - buffer.writeFloat(type.velocityMultiplier); - buffer.writeFloat(type.gravityMultiplier); - buffer.writeFloat(type.soundPitch); - buffer.writeBoolean(type.sticky); - } - - public static PotatoCannonProjectileType fromBuffer(FriendlyByteBuf buffer) { - PotatoCannonProjectileType type = new PotatoCannonProjectileType(); - int size = buffer.readVarInt(); - for (int i = 0; i < size; i++) { - Optional> reference = ForgeRegistries.ITEMS.getDelegate(buffer.readResourceLocation()); - if (reference.isPresent()) { - type.items.add(reference.get()); - } - } - type.reloadTicks = buffer.readInt(); - type.damage = buffer.readInt(); - type.split = buffer.readInt(); - type.knockback = buffer.readFloat(); - type.drag = buffer.readFloat(); - type.velocityMultiplier = buffer.readFloat(); - type.gravityMultiplier = buffer.readFloat(); - type.soundPitch = buffer.readFloat(); - type.sticky = buffer.readBoolean(); - return type; - } - - public static class Builder { - - protected ResourceLocation id; - protected PotatoCannonProjectileType result; - - public Builder(ResourceLocation id) { - this.id = id; - this.result = new PotatoCannonProjectileType(); - } - - public Builder reloadTicks(int reload) { - result.reloadTicks = reload; - return this; - } - - public Builder damage(int damage) { - result.damage = damage; - return this; - } - - public Builder splitInto(int split) { - result.split = split; - return this; - } - - public Builder knockback(float knockback) { - result.knockback = knockback; - return this; - } - - public Builder drag(float drag) { - result.drag = drag; - return this; - } - - public Builder velocity(float velocity) { - result.velocityMultiplier = velocity; - return this; - } - - public Builder gravity(float modifier) { - result.gravityMultiplier = modifier; - return this; - } - - public Builder soundPitch(float pitch) { - result.soundPitch = pitch; - return this; - } - - public Builder sticky() { - result.sticky = true; - return this; - } - - public Builder renderMode(PotatoProjectileRenderMode renderMode) { - result.renderMode = renderMode; - return this; - } - - public Builder renderBillboard() { - renderMode(PotatoProjectileRenderMode.Billboard.INSTANCE); - return this; - } - - public Builder renderTumbling() { - renderMode(PotatoProjectileRenderMode.Tumble.INSTANCE); - return this; - } - - public Builder renderTowardMotion(int spriteAngle, float spin) { - renderMode(new PotatoProjectileRenderMode.TowardMotion(spriteAngle, spin)); - return this; - } - - public Builder preEntityHit(Predicate callback) { - result.preEntityHit = callback; - return this; - } - - public Builder onEntityHit(Predicate callback) { - result.onEntityHit = callback; - return this; - } - - public Builder onBlockHit(BiPredicate callback) { - result.onBlockHit = callback; - return this; - } - - public Builder addItems(ItemLike... items) { - for (ItemLike provider : items) - result.items.add(ForgeRegistries.ITEMS.getDelegateOrThrow(provider.asItem())); - return this; - } - - public PotatoCannonProjectileType register() { - PotatoProjectileTypeManager.registerBuiltinType(id, result); - return result; - } - - public PotatoCannonProjectileType registerAndAssign(ItemLike... items) { - addItems(items); - register(); - return result; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonRenderHandler.java index 34821232fc..f5c6633952 100644 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonRenderHandler.java @@ -1,12 +1,11 @@ package com.simibubi.create.content.equipment.potatoCannon; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllItems; import com.simibubi.create.content.equipment.zapper.ShootableGadgetRenderHandler; import com.simibubi.create.foundation.particle.AirParticleData; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.particles.ItemParticleOption; @@ -26,8 +25,7 @@ public class PotatoCannonRenderHandler extends ShootableGadgetRenderHandler { @Override protected boolean appliesTo(ItemStack stack) { - return AllItems.POTATO_CANNON.get() - .isCannon(stack); + return stack.getItem() instanceof PotatoCannonItem; } public void beforeShoot(float nextPitch, Vec3 location, Vec3 motion, ItemStack stack) { diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileEntity.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileEntity.java index f7cebe591e..20deae8385 100644 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileEntity.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileEntity.java @@ -1,14 +1,19 @@ package com.simibubi.create.content.equipment.potatoCannon; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllEnchantments; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.equipment.potatoCannon.PotatoCannonProjectileType; +import com.simibubi.create.api.equipment.potatoCannon.PotatoProjectileRenderMode; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.content.equipment.potatoCannon.AllPotatoProjectileRenderModes.StuckToEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; import com.simibubi.create.foundation.particle.AirParticleData; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ItemParticleOption; import net.minecraft.core.particles.ParticleOptions; @@ -35,6 +40,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.entity.IEntityAdditionalSpawnData; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.network.NetworkHooks; @@ -53,23 +59,17 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements protected float additionalKnockback = 0; protected float recoveryChance = 0; - public PotatoProjectileEntity(EntityType type, Level world) { - super(type, world); - } - - public ItemStack getItem() { - return stack; + public PotatoProjectileEntity(EntityType type, Level level) { + super(type, level); } public void setItem(ItemStack stack) { this.stack = stack; - } - - public PotatoCannonProjectileType getProjectileType() { - if (type == null) - type = PotatoProjectileTypeManager.getTypeForStack(stack) - .orElse(BuiltinPotatoProjectileTypes.FALLBACK); - return type; + type = PotatoCannonProjectileType.getTypeForItem(level().registryAccess(), stack.getItem()) + .orElseGet(() -> level().registryAccess() + .registryOrThrow(CreateRegistries.POTATO_PROJECTILE_TYPE) + .getHolderOrThrow(AllPotatoProjectileTypes.FALLBACK)) + .value(); } public void setEnchantmentEffectsFromCannon(ItemStack cannon) { @@ -88,9 +88,18 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements recoveryChance = .125f + recovery * .125f; } + public ItemStack getItem() { + return stack; + } + + @Nullable + public PotatoCannonProjectileType getProjectileType() { + return type; + } + @Override public void readAdditionalSaveData(CompoundTag nbt) { - stack = ItemStack.of(nbt.getCompound("Item")); + setItem(ItemStack.of(nbt.getCompound("Item"))); additionalDamageMult = nbt.getFloat("AdditionalDamage"); additionalKnockback = nbt.getFloat("AdditionalKnockback"); recoveryChance = nbt.getFloat("Recovery"); @@ -106,6 +115,7 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements super.addAdditionalSaveData(nbt); } + @Nullable public Entity getStuckEntity() { if (stuckEntity == null) return null; @@ -117,7 +127,7 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements public void setStuckEntity(Entity stuckEntity) { this.stuckEntity = stuckEntity; this.stuckOffset = position().subtract(stuckEntity.position()); - this.stuckRenderer = new PotatoProjectileRenderMode.StuckToEntity(stuckOffset); + this.stuckRenderer = new StuckToEntity(stuckOffset); this.stuckFallSpeed = 0.0; setDeltaMovement(Vec3.ZERO); } @@ -126,27 +136,26 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements if (getStuckEntity() != null) return stuckRenderer; - return getProjectileType().getRenderMode(); + return type.renderMode(); } + @Override public void tick() { - PotatoCannonProjectileType projectileType = getProjectileType(); - Entity stuckEntity = getStuckEntity(); if (stuckEntity != null) { if (getY() < stuckEntity.getY() - 0.1) { pop(position()); kill(); } else { - stuckFallSpeed += 0.007 * projectileType.getGravityMultiplier(); + stuckFallSpeed += 0.007 * type.gravityMultiplier(); stuckOffset = stuckOffset.add(0, -stuckFallSpeed, 0); Vec3 pos = stuckEntity.position() .add(stuckOffset); setPos(pos.x, pos.y, pos.z); } } else { - setDeltaMovement(getDeltaMovement().add(0, -0.05 * projectileType.getGravityMultiplier(), 0) - .scale(projectileType.getDrag())); + setDeltaMovement(getDeltaMovement().add(0, -0.05 * type.gravityMultiplier(), 0) + .scale(type.drag())); } super.tick(); @@ -176,9 +185,8 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements Vec3 hit = ray.getLocation(); Entity target = ray.getEntity(); - PotatoCannonProjectileType projectileType = getProjectileType(); - float damage = projectileType.getDamage() * additionalDamageMult; - float knockback = projectileType.getKnockback() + additionalKnockback; + float damage = type.damage() * additionalDamageMult; + float knockback = type.knockback() + additionalKnockback; Entity owner = this.getOwner(); if (!target.isAlive()) @@ -201,7 +209,7 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements if (target instanceof WitherBoss && ((WitherBoss) target).isPowered()) return; - if (projectileType.preEntityHit(ray)) + if (type.preEntityHit(stack, ray)) return; boolean targetIsEnderman = target.getType() == EntityType.ENDERMAN; @@ -219,20 +227,22 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements if (targetIsEnderman) return; - if (!projectileType.onEntityHit(ray) && onServer) - if (random.nextDouble() <= recoveryChance) + if (!type.onEntityHit(stack, ray) && onServer) { + if (random.nextDouble() <= recoveryChance) { recoverItem(); + } else { + spawnAtLocation(type.dropStack()); + } + } - if (!(target instanceof LivingEntity)) { + if (!(target instanceof LivingEntity livingentity)) { playHitSound(level(), position()); kill(); return; } - LivingEntity livingentity = (LivingEntity) target; - - if (type.getReloadTicks() < 10) - livingentity.invulnerableTime = type.getReloadTicks() + 10; + if (type.reloadTicks() < 10) + livingentity.invulnerableTime = type.reloadTicks() + 10; if (onServer && knockback > 0) { Vec3 appliedMotion = this.getDeltaMovement() @@ -254,14 +264,13 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements .send(new ClientboundGameEventPacket(ClientboundGameEventPacket.ARROW_HIT_PLAYER, 0.0F)); } - if (onServer && owner instanceof ServerPlayer) { - ServerPlayer serverplayerentity = (ServerPlayer) owner; + if (onServer && owner instanceof ServerPlayer serverplayerentity) { if (!target.isAlive() && target.getType() .getCategory() == MobCategory.MONSTER || (target instanceof Player && target != owner)) AllAdvancements.POTATO_CANNON.awardTo(serverplayerentity); } - if (type.isSticky() && target.isAlive()) { + if (type.sticky() && target.isAlive()) { setStuckEntity(target); } else { kill(); @@ -286,9 +295,14 @@ public class PotatoProjectileEntity extends AbstractHurtingProjectile implements protected void onHitBlock(BlockHitResult ray) { Vec3 hit = ray.getLocation(); pop(hit); - if (!getProjectileType().onBlockHit(level(), ray) && !level().isClientSide) - if (random.nextDouble() <= recoveryChance) + if (!type.onBlockHit(level(), stack, ray) && !level().isClientSide) { + if (random.nextDouble() <= recoveryChance) { recoverItem(); + } else { + spawnAtLocation(getProjectileType().dropStack()); + } + } + super.onHitBlock(ray); kill(); } diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileRenderMode.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileRenderMode.java deleted file mode 100644 index a71ff17bd6..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileRenderMode.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.simibubi.create.content.equipment.potatoCannon; - -import static com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileRenderMode.entityRandom; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.utility.AngleHelper; - -import dev.engine_room.flywheel.lib.transform.TransformStack; -import net.minecraft.client.Minecraft; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public interface PotatoProjectileRenderMode { - - @OnlyIn(Dist.CLIENT) - void transform(PoseStack ms, PotatoProjectileEntity entity, float pt); - - public static class Billboard implements PotatoProjectileRenderMode { - - public static final Billboard INSTANCE = new Billboard(); - - @Override - @OnlyIn(Dist.CLIENT) - public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { - Minecraft mc = Minecraft.getInstance(); - Vec3 p1 = mc.getCameraEntity() - .getEyePosition(pt); - Vec3 diff = entity.getBoundingBox() - .getCenter() - .subtract(p1); - - TransformStack.of(ms) - .rotateYDegrees(AngleHelper.deg(Mth.atan2(diff.x, diff.z)) + 180) - .rotateXDegrees(AngleHelper.deg(Mth.atan2(diff.y, Mth.sqrt((float) (diff.x * diff.x + diff.z * diff.z))))); - } - - } - - public static class Tumble extends Billboard { - - public static final Tumble INSTANCE = new Tumble(); - - @Override - @OnlyIn(Dist.CLIENT) - public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { - super.transform(ms, entity, pt); - TransformStack.of(ms) - .rotateZDegrees((entity.tickCount + pt) * 2 * entityRandom(entity, 16)) - .rotateXDegrees((entity.tickCount + pt) * entityRandom(entity, 32)); - } - - } - - public static class TowardMotion implements PotatoProjectileRenderMode { - - private int spriteAngleOffset; - private float spin; - - public TowardMotion(int spriteAngleOffset, float spin) { - this.spriteAngleOffset = spriteAngleOffset; - this.spin = spin; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { - Vec3 diff = entity.getDeltaMovement(); - TransformStack.of(ms) - .rotateYDegrees(AngleHelper.deg(Mth.atan2(diff.x, diff.z))) - .rotateXDegrees(270 - + AngleHelper.deg(Mth.atan2(diff.y, -Mth.sqrt((float) (diff.x * diff.x + diff.z * diff.z))))); - TransformStack.of(ms) - .rotateYDegrees((entity.tickCount + pt) * 20 * spin + entityRandom(entity, 360)) - .rotateZDegrees(-spriteAngleOffset); - } - - } - - public static class StuckToEntity implements PotatoProjectileRenderMode { - - private Vec3 offset; - - public StuckToEntity(Vec3 offset) { - this.offset = offset; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void transform(PoseStack ms, PotatoProjectileEntity entity, float pt) { - TransformStack.of(ms).rotateYDegrees(AngleHelper.deg(Mth.atan2(offset.x, offset.z))); - } - - } - - public static int entityRandom(Entity entity, int maxValue) { - return (System.identityHashCode(entity) * 31) % maxValue; - } - -} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileTypeManager.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileTypeManager.java deleted file mode 100644 index 09d8674bc0..0000000000 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoProjectileTypeManager.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.simibubi.create.content.equipment.potatoCannon; - -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Optional; -import java.util.function.Supplier; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; -import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent.Context; -import net.minecraftforge.network.PacketDistributor; - -public class PotatoProjectileTypeManager { - - private static final Map BUILTIN_TYPE_MAP = new HashMap<>(); - private static final Map CUSTOM_TYPE_MAP = new HashMap<>(); - private static final Map ITEM_TO_TYPE_MAP = new IdentityHashMap<>(); - - public static void registerBuiltinType(ResourceLocation id, PotatoCannonProjectileType type) { - synchronized (BUILTIN_TYPE_MAP) { - BUILTIN_TYPE_MAP.put(id, type); - } - } - - public static PotatoCannonProjectileType getBuiltinType(ResourceLocation id) { - return BUILTIN_TYPE_MAP.get(id); - } - - public static PotatoCannonProjectileType getCustomType(ResourceLocation id) { - return CUSTOM_TYPE_MAP.get(id); - } - - public static PotatoCannonProjectileType getTypeForItem(Item item) { - return ITEM_TO_TYPE_MAP.get(item); - } - - public static Optional getTypeForStack(ItemStack item) { - if (item.isEmpty()) - return Optional.empty(); - return Optional.ofNullable(getTypeForItem(item.getItem())); - } - - public static void clear() { - CUSTOM_TYPE_MAP.clear(); - ITEM_TO_TYPE_MAP.clear(); - } - - public static void fillItemMap() { - for (Map.Entry entry : BUILTIN_TYPE_MAP.entrySet()) { - PotatoCannonProjectileType type = entry.getValue(); - for (Supplier delegate : type.getItems()) { - ITEM_TO_TYPE_MAP.put(delegate.get(), type); - } - } - for (Map.Entry entry : CUSTOM_TYPE_MAP.entrySet()) { - PotatoCannonProjectileType type = entry.getValue(); - for (Supplier delegate : type.getItems()) { - ITEM_TO_TYPE_MAP.put(delegate.get(), type); - } - } - ITEM_TO_TYPE_MAP.remove(AllItems.POTATO_CANNON.get()); - } - - public static void toBuffer(FriendlyByteBuf buffer) { - buffer.writeVarInt(CUSTOM_TYPE_MAP.size()); - for (Map.Entry entry : CUSTOM_TYPE_MAP.entrySet()) { - buffer.writeResourceLocation(entry.getKey()); - PotatoCannonProjectileType.toBuffer(entry.getValue(), buffer); - } - } - - public static void fromBuffer(FriendlyByteBuf buffer) { - clear(); - - int size = buffer.readVarInt(); - for (int i = 0; i < size; i++) { - CUSTOM_TYPE_MAP.put(buffer.readResourceLocation(), PotatoCannonProjectileType.fromBuffer(buffer)); - } - - fillItemMap(); - } - - public static void syncTo(ServerPlayer player) { - AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> player), new SyncPacket()); - } - - public static void syncToAll() { - AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new SyncPacket()); - } - - public static class ReloadListener extends SimpleJsonResourceReloadListener { - - private static final Gson GSON = new Gson(); - - public static final ReloadListener INSTANCE = new ReloadListener(); - - protected ReloadListener() { - super(GSON, "potato_cannon_projectile_types"); - } - - @Override - protected void apply(Map map, ResourceManager resourceManager, ProfilerFiller profiler) { - clear(); - - for (Map.Entry entry : map.entrySet()) { - JsonElement element = entry.getValue(); - if (element.isJsonObject()) { - ResourceLocation id = entry.getKey(); - JsonObject object = element.getAsJsonObject(); - PotatoCannonProjectileType type = PotatoCannonProjectileType.fromJson(object); - CUSTOM_TYPE_MAP.put(id, type); - } - } - - fillItemMap(); - } - - } - - public static class SyncPacket extends SimplePacketBase { - - private FriendlyByteBuf buffer; - - public SyncPacket() { - } - - public SyncPacket(FriendlyByteBuf buffer) { - this.buffer = buffer; - } - - @Override - public void write(FriendlyByteBuf buffer) { - toBuffer(buffer); - } - - @Override - public boolean handle(Context context) { - context.enqueueWork(() -> { - fromBuffer(buffer); - }); - return true; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoRecoveryEnchantment.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoRecoveryEnchantment.java index 47e767ffff..88263a5473 100644 --- a/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoRecoveryEnchantment.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoRecoveryEnchantment.java @@ -6,19 +6,17 @@ import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentCategory; public class PotatoRecoveryEnchantment extends Enchantment { - - public PotatoRecoveryEnchantment(Rarity p_i46731_1_, EnchantmentCategory p_i46731_2_, EquipmentSlot[] p_i46731_3_) { - super(p_i46731_1_, p_i46731_2_, p_i46731_3_); + public PotatoRecoveryEnchantment(Rarity rarity, EnchantmentCategory category, EquipmentSlot[] slots) { + super(rarity, category, slots); } @Override public int getMaxLevel() { return 3; } - + @Override public boolean canApplyAtEnchantingTable(ItemStack stack) { return stack.getItem() instanceof PotatoCannonItem; } - } diff --git a/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItem.java b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItem.java index df54f3b293..73b2eb02da 100644 --- a/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItem.java @@ -8,8 +8,9 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.foundation.item.CustomUseEffectsItem; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; import com.simibubi.create.foundation.mixin.accessor.LivingEntityAccessor; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.TriState; +import net.createmod.catnip.math.VecHelper; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ItemParticleOption; @@ -34,6 +35,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientItemExtensions; @@ -74,9 +76,8 @@ public class SandPaperItem extends Item implements CustomUseEffectsItem { } HitResult raytraceresult = getPlayerPOVHitResult(worldIn, playerIn, ClipContext.Fluid.NONE); - if (!(raytraceresult instanceof BlockHitResult)) + if (!(raytraceresult instanceof BlockHitResult ray)) return FAIL; - BlockHitResult ray = (BlockHitResult) raytraceresult; Vec3 hitVec = ray.getLocation(); AABB bb = new AABB(hitVec, hitVec).inflate(1f); @@ -117,9 +118,8 @@ public class SandPaperItem extends Item implements CustomUseEffectsItem { @Override public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving) { - if (!(entityLiving instanceof Player)) + if (!(entityLiving instanceof Player player)) return stack; - Player player = (Player) entityLiving; CompoundTag tag = stack.getOrCreateTag(); if (tag.contains("Polishing")) { ItemStack toPolish = ItemStack.of(tag.getCompound("Polishing")); @@ -128,8 +128,8 @@ public class SandPaperItem extends Item implements CustomUseEffectsItem { if (worldIn.isClientSide) { spawnParticles(entityLiving.getEyePosition(1) - .add(entityLiving.getLookAngle() - .scale(.5f)), + .add(entityLiving.getLookAngle() + .scale(.5f)), toPolish, worldIn); return stack; } @@ -159,9 +159,8 @@ public class SandPaperItem extends Item implements CustomUseEffectsItem { @Override public void releaseUsing(ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) { - if (!(entityLiving instanceof Player)) + if (!(entityLiving instanceof Player player)) return; - Player player = (Player) entityLiving; CompoundTag tag = stack.getOrCreateTag(); if (tag.contains("Polishing")) { ItemStack toPolish = ItemStack.of(tag.getCompound("Polishing")); @@ -208,9 +207,9 @@ public class SandPaperItem extends Item implements CustomUseEffectsItem { } @Override - public Boolean shouldTriggerUseEffects(ItemStack stack, LivingEntity entity) { + public TriState shouldTriggerUseEffects(ItemStack stack, LivingEntity entity) { // Trigger every tick so that we have more fine grain control over the animation - return true; + return TriState.TRUE; } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItemRenderer.java index 278a925810..85c6734ae2 100644 --- a/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItemRenderer.java @@ -5,8 +5,8 @@ import com.mojang.math.Axis; import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryHandler.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryHandler.java index 116235545c..b8f443e8dc 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryHandler.java @@ -9,8 +9,8 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllItems; import com.simibubi.create.content.equipment.symmetryWand.mirror.EmptyMirror; import com.simibubi.create.content.equipment.symmetryWand.mirror.SymmetryMirror; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -79,7 +79,7 @@ public class SymmetryHandler { public static void onRenderWorld(RenderLevelStageEvent event) { if (event.getStage() != Stage.AFTER_PARTICLES) return; - + Minecraft mc = Minecraft.getInstance(); LocalPlayer player = mc.player; RandomSource random = RandomSource.create(); diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItem.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItem.java index c203e7976d..0d22ed7c6a 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItem.java @@ -16,12 +16,12 @@ import com.simibubi.create.content.equipment.symmetryWand.mirror.CrossPlaneMirro import com.simibubi.create.content.equipment.symmetryWand.mirror.EmptyMirror; import com.simibubi.create.content.equipment.symmetryWand.mirror.PlaneMirror; import com.simibubi.create.content.equipment.symmetryWand.mirror.SymmetryMirror; -import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -42,6 +42,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientItemExtensions; @@ -149,13 +150,13 @@ public class SymmetryWandItem extends Item { playerIn.getCooldowns() .addCooldown(this, 5); } - return new InteractionResultHolder(InteractionResult.SUCCESS, wand); + return new InteractionResultHolder<>(InteractionResult.SUCCESS, wand); } // No Shift -> Clear Mirror wand.getTag() .putBoolean(ENABLE, false); - return new InteractionResultHolder(InteractionResult.SUCCESS, wand); + return new InteractionResultHolder<>(InteractionResult.SUCCESS, wand); } @OnlyIn(Dist.CLIENT) @@ -330,7 +331,7 @@ public class SymmetryWandItem extends Item { public void initializeClient(Consumer consumer) { consumer.accept(SimpleCustomRenderer.create(this, new SymmetryWandItemRenderer())); } - + public static boolean presentInHotbar(Player player) { Inventory inv = player.getInventory(); for (int i = 0; i < Inventory.getSelectionSize(); i++) diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItemRenderer.java index 90b3a321da..eb04c0b9e5 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItemRenderer.java @@ -6,9 +6,9 @@ import com.simibubi.create.Create; import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandScreen.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandScreen.java index f18263f50a..99daca5446 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandScreen.java @@ -10,18 +10,18 @@ import com.simibubi.create.content.equipment.symmetryWand.mirror.EmptyMirror; import com.simibubi.create.content.equipment.symmetryWand.mirror.PlaneMirror; import com.simibubi.create.content.equipment.symmetryWand.mirror.SymmetryMirror; import com.simibubi.create.content.equipment.symmetryWand.mirror.TriplePlaneMirror; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; @@ -37,8 +37,8 @@ public class SymmetryWandScreen extends AbstractSimiScreen { private Label labelAlign; private IconButton confirmButton; - private final Component mirrorType = Lang.translateDirect("gui.symmetryWand.mirrorType"); - private final Component orientation = Lang.translateDirect("gui.symmetryWand.orientation"); + private final Component mirrorType = CreateLang.translateDirect("gui.symmetryWand.mirrorType"); + private final Component orientation = CreateLang.translateDirect("gui.symmetryWand.orientation"); private SymmetryMirror currentElement; private ItemStack wand; @@ -57,16 +57,16 @@ public class SymmetryWandScreen extends AbstractSimiScreen { @Override public void init() { - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); setWindowOffset(-20, 0); super.init(); int x = guiLeft; int y = guiTop; - labelType = new Label(x + 49, y + 28, Components.immutableEmpty()).colored(0xFFFFFFFF) + labelType = new Label(x + 51, y + 28, CommonComponents.EMPTY).colored(0xFFFFFFFF) .withShadow(); - labelAlign = new Label(x + 49, y + 50, Components.immutableEmpty()).colored(0xFFFFFFFF) + labelAlign = new Label(x + 51, y + 50, CommonComponents.EMPTY).colored(0xFFFFFFFF) .withShadow(); int state = @@ -78,17 +78,17 @@ public class SymmetryWandScreen extends AbstractSimiScreen { areaType.calling(position -> { switch (position) { - case 0: - currentElement = new PlaneMirror(currentElement.getPosition()); - break; - case 1: - currentElement = new CrossPlaneMirror(currentElement.getPosition()); - break; - case 2: - currentElement = new TriplePlaneMirror(currentElement.getPosition()); - break; - default: - break; + case 0: + currentElement = new PlaneMirror(currentElement.getPosition()); + break; + case 1: + currentElement = new CrossPlaneMirror(currentElement.getPosition()); + break; + case 2: + currentElement = new TriplePlaneMirror(currentElement.getPosition()); + break; + default: + break; } initAlign(currentElement, x, y); }); @@ -99,7 +99,7 @@ public class SymmetryWandScreen extends AbstractSimiScreen { addRenderableWidget(areaType); addRenderableWidget(labelType); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { onClose(); }); @@ -125,19 +125,20 @@ public class SymmetryWandScreen extends AbstractSimiScreen { int y = guiTop; background.render(graphics, x, y); - graphics.drawString(font, wand.getHoverName(), x + 11, y + 4, 0x592424, false); + graphics.drawString(font, wand.getHoverName(), + x + (background.getWidth() - font.width(wand.getHoverName())) / 2, y + 4, 0x592424, false); renderBlock(graphics, x, y); GuiGameElement.of(wand) - .scale(4) - .rotate(-70, 20, 20) - .at(x + 178, y + 448, -150) - .render(graphics); + .scale(4) + .rotate(-70, 20, 20) + .at(x + 178, y + 448, -150) + .render(graphics); } protected void renderBlock(GuiGraphics graphics, int x, int y) { PoseStack ms = graphics.pose(); - + ms.pushPose(); ms.translate(x + 26, y + 39, 20); ms.scale(16, 16, 16); diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/CrossPlaneMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/CrossPlaneMirror.java index 96fce78468..4363f2d843 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/CrossPlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/CrossPlaneMirror.java @@ -7,7 +7,7 @@ import java.util.Map; import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; @@ -105,7 +105,7 @@ public class CrossPlaneMirror extends SymmetryMirror { @Override public List getAlignToolTips() { - return ImmutableList.of(Lang.translateDirect("orientation.orthogonal"), Lang.translateDirect("orientation.diagonal")); + return ImmutableList.of(CreateLang.translateDirect("orientation.orthogonal"), CreateLang.translateDirect("orientation.diagonal")); } } diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/PlaneMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/PlaneMirror.java index 84589b5261..ffd1133d32 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/PlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/PlaneMirror.java @@ -7,7 +7,7 @@ import java.util.Map; import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; @@ -101,7 +101,7 @@ public class PlaneMirror extends SymmetryMirror { @Override public List getAlignToolTips() { - return ImmutableList.of(Lang.translateDirect("orientation.alongZ"), Lang.translateDirect("orientation.alongX")); + return ImmutableList.of(CreateLang.translateDirect("orientation.alongZ"), CreateLang.translateDirect("orientation.alongX")); } } diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/SymmetryMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/SymmetryMirror.java index a90fb724ca..a67ba5dcff 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/SymmetryMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/SymmetryMirror.java @@ -6,7 +6,7 @@ import java.util.Map; import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import net.minecraft.core.BlockPos; @@ -45,8 +45,8 @@ public abstract class SymmetryMirror { } public static List getMirrors() { - return ImmutableList.of(Lang.translateDirect("symmetry.mirror.plane"), Lang.translateDirect("symmetry.mirror.doublePlane"), - Lang.translateDirect("symmetry.mirror.triplePlane")); + return ImmutableList.of(CreateLang.translateDirect("symmetry.mirror.plane"), CreateLang.translateDirect("symmetry.mirror.doublePlane"), + CreateLang.translateDirect("symmetry.mirror.triplePlane")); } public StringRepresentable getOrientation() { diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/TriplePlaneMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/TriplePlaneMirror.java index 3dd228eadd..9c8a814380 100644 --- a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/TriplePlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/TriplePlaneMirror.java @@ -6,7 +6,7 @@ import java.util.Map; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import net.minecraft.core.BlockPos; @@ -66,7 +66,7 @@ public class TriplePlaneMirror extends SymmetryMirror { @Override public List getAlignToolTips() { - return ImmutableList.of(Lang.translateDirect("orientation.horizontal")); + return ImmutableList.of(CreateLang.translateDirect("orientation.horizontal")); } } diff --git a/src/main/java/com/simibubi/create/content/equipment/tool/AllToolMaterials.java b/src/main/java/com/simibubi/create/content/equipment/tool/AllToolMaterials.java new file mode 100644 index 0000000000..17bff6c5af --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/tool/AllToolMaterials.java @@ -0,0 +1,64 @@ +package com.simibubi.create.content.equipment.tool; + +import java.util.function.Supplier; + +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; + +import net.minecraft.world.item.Tier; +import net.minecraft.world.item.crafting.Ingredient; + +public enum AllToolMaterials implements Tier { + + CARDBOARD(Create.asResource("cardboard") + .toString(), 0, 1, 2, 1, () -> Ingredient.of(AllItems.CARDBOARD.asItem())); + + public String name; + + private int uses; + private float speed; + private float damageBonus; + private int enchantValue; + private Supplier repairMaterial; + + private AllToolMaterials(String name, int uses, float speed, float damageBonus, int enchantValue, + Supplier repairMaterial) { + this.name = name; + this.uses = uses; + this.speed = speed; + this.damageBonus = damageBonus; + this.enchantValue = enchantValue; + this.repairMaterial = repairMaterial; + } + + @Override + public int getUses() { + return uses; + } + + @Override + public float getSpeed() { + return speed; + } + + @Override + public float getAttackDamageBonus() { + return damageBonus; + } + + @Override + public int getLevel() { + return 0; + } + + @Override + public int getEnchantmentValue() { + return enchantValue; + } + + @Override + public Ingredient getRepairIngredient() { + return repairMaterial.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/tool/CardboardSwordItem.java b/src/main/java/com/simibubi/create/content/equipment/tool/CardboardSwordItem.java new file mode 100644 index 0000000000..fcb47d7464 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/tool/CardboardSwordItem.java @@ -0,0 +1,133 @@ +package com.simibubi.create.content.equipment.tool; + +import java.util.function.Consumer; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.monster.Spider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemStack.TooltipPart; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.SwordItem; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.extensions.common.IClientItemExtensions; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock; +import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock.Action; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.network.PacketDistributor; + +@EventBusSubscriber +public class CardboardSwordItem extends SwordItem { + + public CardboardSwordItem(Properties pProperties) { + super(AllToolMaterials.CARDBOARD, 3, 1f, pProperties); + } + + @Override + public int getBurnTime(ItemStack itemStack, @Nullable RecipeType recipeType) { + return 1000; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + return enchantment == Enchantments.KNOCKBACK; + } + + @Override + public int getDefaultTooltipHideFlags(@NotNull ItemStack stack) { + return TooltipPart.MODIFIERS.getMask(); + } + + @SubscribeEvent + public static void cardboardSwordsMakeNoiseOnClick(LeftClickBlock event) { + ItemStack itemStack = event.getItemStack(); + if (!AllItems.CARDBOARD_SWORD.isIn(itemStack)) + return; + if (event.getAction() != Action.START) + return; + if (event.getSide() == LogicalSide.CLIENT) + AllSoundEvents.CARDBOARD_SWORD.playAt(event.getLevel(), event.getPos(), 0.5f, 1.85f, false); + else + AllSoundEvents.CARDBOARD_SWORD.play(event.getLevel(), event.getEntity(), event.getPos(), 0.5f, 1.85f); + } + + @SubscribeEvent + public static void cardboardSwordsCannotHurtYou(LivingAttackEvent event) { + Entity attacker = event.getSource() + .getEntity(); + LivingEntity target = event.getEntity(); + if (target == null || target instanceof Spider) + return; + if (!(attacker instanceof LivingEntity livingAttacker + && AllItems.CARDBOARD_SWORD.isIn(livingAttacker.getItemInHand(InteractionHand.MAIN_HAND)))) + return; + + AllSoundEvents.CARDBOARD_SWORD.playFrom(attacker, 0.75f, 1.85f); + + event.setCanceled(true); + + // Reference player.attack() + // This section replicates knockback behaviour without hurting the target + + double knockbackStrength = livingAttacker.getAttributeValue(Attributes.ATTACK_KNOCKBACK) + 2; + knockbackStrength += EnchantmentHelper.getKnockbackBonus(livingAttacker); + if (livingAttacker.isSprinting() + && (!(livingAttacker instanceof Player p) || p.getAttackStrengthScale(0.5f) > 0.9f)) + ++knockbackStrength; + + if (knockbackStrength <= 0) + return; + + float yRot = livingAttacker.getYRot(); + knockback(target, knockbackStrength, yRot); + + boolean targetIsPlayer = target instanceof Player; + MobCategory targetType = target.getClassification(false); + + if (target instanceof ServerPlayer sp) + AllPackets.getChannel() + .send(PacketDistributor.PLAYER.with(() -> sp), new KnockbackPacket(yRot, (float) knockbackStrength)); + + if ((targetType == MobCategory.MISC || targetType == MobCategory.CREATURE) && !targetIsPlayer) + target.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 60, 9, true, false, false)); + + livingAttacker.setDeltaMovement(livingAttacker.getDeltaMovement() + .multiply(0.6D, 1.0D, 0.6D)); + livingAttacker.setSprinting(false); + } + + public static void knockback(LivingEntity target, double knockbackStrength, float yRot) { + target.stopRiding(); + target.knockback(knockbackStrength * 0.5F, Mth.sin(yRot * Mth.DEG_TO_RAD), -Mth.cos(yRot * Mth.DEG_TO_RAD)); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void initializeClient(Consumer consumer) { + consumer.accept(SimpleCustomRenderer.create(this, new CardboardSwordItemRenderer())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/tool/CardboardSwordItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/tool/CardboardSwordItemRenderer.java new file mode 100644 index 0000000000..85ab0fba12 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/tool/CardboardSwordItemRenderer.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.equipment.tool; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; + +public class CardboardSwordItemRenderer extends CustomRenderedItemModelRenderer { + + protected static final PartialModel HELD = PartialModel.of(Create.asResource("item/cardboard_sword/item_in_hand")); + + @Override + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, + ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + renderer.render(transformType == ItemDisplayContext.GUI ? model.getOriginalModel() : HELD.get(), light); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/tool/KnockbackPacket.java b/src/main/java/com/simibubi/create/content/equipment/tool/KnockbackPacket.java new file mode 100644 index 0000000000..733df927f1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/tool/KnockbackPacket.java @@ -0,0 +1,43 @@ +package com.simibubi.create.content.equipment.tool; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkEvent.Context; + +public class KnockbackPacket extends SimplePacketBase { + + private float yRot; + private float strength; + + public KnockbackPacket(float yRot, float strength) { + this.yRot = yRot; + this.strength = strength; + } + + public KnockbackPacket(FriendlyByteBuf buffer) { + strength = buffer.readFloat(); + yRot = buffer.readFloat(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeFloat(strength); + buffer.writeFloat(yRot); + } + + @Override + @OnlyIn(Dist.CLIENT) + public boolean handle(Context context) { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) + return true; + CardboardSwordItem.knockback(player, strength, yRot); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/RadialToolboxMenu.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/RadialToolboxMenu.java index cccb3b102d..e04438c9c0 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/RadialToolboxMenu.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/RadialToolboxMenu.java @@ -13,15 +13,16 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllKeys; import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.ChatFormatting; import net.minecraft.client.KeyMapping; import net.minecraft.client.gui.GuiGraphics; @@ -83,7 +84,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen { if (state == State.DETACH) { - tip = Lang.translateDirect("toolbox.outOfRange"); + tip = CreateLang.translateDirect("toolbox.outOfRange"); if (hoveredX > -20 && hoveredX < 20 && hoveredY > -80 && hoveredY < -20) hoveredSlot = UNEQUIP; @@ -101,7 +102,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen { ms.translate(0.5, -0.5, 0); if (!scrollMode && hoveredSlot == UNEQUIP) { AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.render(graphics, -13, -13); - tip = Lang.translateDirect("toolbox.detach") + tip = CreateLang.translateDirect("toolbox.detach") .withStyle(ChatFormatting.GOLD); } ms.popPose(); @@ -119,7 +120,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen { ms.translate(0.5, -0.5, 0); if (!scrollMode && hoveredSlot == DEPOSIT) { AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.render(graphics, -13, -13); - tip = Lang.translateDirect(state == State.SELECT_BOX ? "toolbox.depositAll" : "toolbox.depositBox") + tip = CreateLang.translateDirect(state == State.SELECT_BOX ? "toolbox.depositAll" : "toolbox.depositBox") .withStyle(ChatFormatting.GOLD); } ms.popPose(); @@ -181,7 +182,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen { (scrollMode ? AllIcons.I_REFRESH : AllIcons.I_FLIP).render(graphics, -9, -9); if (!scrollMode && UNEQUIP == hoveredSlot) { AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.render(graphics, -13, -13); - tip = Lang.translateDirect("toolbox.unequip", minecraft.player.getMainHandItem() + tip = CreateLang.translateDirect("toolbox.unequip", minecraft.player.getMainHandItem() .getHoverName()) .withStyle(ChatFormatting.GOLD); } @@ -213,8 +214,10 @@ public class RadialToolboxMenu extends AbstractSimiScreen { @Override public void renderBackground(GuiGraphics graphics) { - int a = ((int) (0x50 * Math.min(1, (ticksOpen + AnimationTickHolder.getPartialTicks()) / 20f))) << 24; - graphics.fillGradient(0, 0, this.width, this.height, 0x101010 | a, 0x101010 | a); + Color color = BACKGROUND_COLOR + .scaleAlpha(Math.min(1, (ticksOpen + AnimationTickHolder.getPartialTicks()) / 20f)); + + graphics.fillGradient(0, 0, this.width, this.height, color.getRGB(), color.getRGB()); } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolBoxVisual.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolBoxVisual.java index f7bcd204f8..75efd8229b 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolBoxVisual.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolBoxVisual.java @@ -3,7 +3,6 @@ package com.simibubi.create.content.equipment.toolbox; import java.util.function.Consumer; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.Instancer; @@ -14,6 +13,7 @@ import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction; public class ToolBoxVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { @@ -22,6 +22,9 @@ public class ToolBoxVisual extends AbstractBlockEntityVisual private final TransformedInstance lid; private final TransformedInstance[] drawers; + private float lastLidAngle = Float.NaN; + private float lastDrawerOffset = Float.NaN; + public ToolBoxVisual(VisualizationContext context, ToolboxBlockEntity blockEntity, float partialTick) { super(context, blockEntity, partialTick); @@ -33,6 +36,8 @@ public class ToolBoxVisual extends AbstractBlockEntityVisual drawers = new TransformedInstance[]{drawerModel.createInstance(), drawerModel.createInstance()}; lid = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.TOOLBOX_LIDS.get(blockEntity.getColor()))) .createInstance(); + + animate(partialTick); } @Override @@ -46,30 +51,39 @@ public class ToolBoxVisual extends AbstractBlockEntityVisual @Override public void beginFrame(DynamicVisual.Context ctx) { - float partialTicks = ctx.partialTick(); + animate(ctx.partialTick()); + } + private void animate(float partialTicks) { float lidAngle = blockEntity.lid.getValue(partialTicks); float drawerOffset = blockEntity.drawers.getValue(partialTicks); - lid.setIdentityTransform() - .translate(getVisualPosition()) - .center() - .rotateYDegrees(-facing.toYRot()) - .uncenter() - .translate(0, 6 / 16f, 12 / 16f) - .rotateXDegrees(135 * lidAngle) - .translateBack(0, 6 / 16f, 12 / 16f) - .setChanged(); - - for (int offset : Iterate.zeroAndOne) { - drawers[offset].setIdentityTransform() + if (lidAngle != lastLidAngle) { + lid.setIdentityTransform() .translate(getVisualPosition()) .center() .rotateYDegrees(-facing.toYRot()) .uncenter() - .translate(0, offset * 1 / 8f, -drawerOffset * .175f * (2 - offset)) + .translate(0, 6 / 16f, 12 / 16f) + .rotateXDegrees(135 * lidAngle) + .translateBack(0, 6 / 16f, 12 / 16f) .setChanged(); } + + if (drawerOffset != lastDrawerOffset) { + for (int offset : Iterate.zeroAndOne) { + drawers[offset].setIdentityTransform() + .translate(getVisualPosition()) + .center() + .rotateYDegrees(-facing.toYRot()) + .uncenter() + .translate(0, offset * 1 / 8f, -drawerOffset * .175f * (2 - offset)) + .setChanged(); + } + } + + lastLidAngle = lidAngle; + lastDrawerOffset = drawerOffset; } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlock.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlock.java index 7afa382f60..bd181780e5 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlock.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlock.java @@ -38,7 +38,7 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.common.capabilities.ForgeCapabilities; + import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.network.NetworkHooks; @@ -120,7 +120,7 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa @Override public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, LevelAccessor world, - BlockPos pos, BlockPos neighbourPos) { + BlockPos pos, BlockPos neighbourPos) { if (state.getValue(WATERLOGGED)) world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); return state; @@ -133,7 +133,7 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult ray) { + BlockHitResult ray) { if (player == null || player.isCrouching()) return InteractionResult.PASS; @@ -164,7 +164,7 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa FluidState ifluidstate = context.getLevel() .getFluidState(context.getClickedPos()); return super.getStateForPlacement(context).setValue(FACING, context.getHorizontalDirection() - .getOpposite()) + .getOpposite()) .setValue(WATERLOGGED, Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)); } diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlockEntity.java index ee397eea1e..f82dc087ac 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlockEntity.java @@ -13,11 +13,12 @@ import java.util.WeakHashMap; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.animatedContainer.AnimatedContainerBehaviour; import com.simibubi.create.foundation.utility.ResetableLazy; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -34,8 +35,8 @@ import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; @@ -53,12 +54,13 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider ToolboxInventory inventory; LazyOptional inventoryProvider; ResetableLazy colorProvider; - protected int openCount; Map> connectedPlayers; private Component customName; + private AnimatedContainerBehaviour openTracker; + public ToolboxBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); connectedPlayers = new HashMap<>(); @@ -78,7 +80,9 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider } @Override - public void addBehaviours(List behaviours) {} + public void addBehaviours(List behaviours) { + behaviours.add(openTracker = new AnimatedContainerBehaviour<>(this, ToolboxMenu.class)); + } @Override public void initialize() { @@ -101,8 +105,8 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider if (!level.isClientSide) tickPlayers(); - lid.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.LINEAR); - drawers.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.EXP); + lid.chase(openTracker.openCount > 0 ? 1 : 0, 0.2f, Chaser.LINEAR); + drawers.chase(openTracker.openCount > 0 ? 1 : 0, 0.2f, Chaser.EXP); lid.tickChaser(); drawers.tickChaser(); } @@ -111,7 +115,7 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider boolean update = false; for (Iterator>> toolboxSlots = connectedPlayers.entrySet() - .iterator(); toolboxSlots.hasNext();) { + .iterator(); toolboxSlots.hasNext(); ) { Entry> toolboxSlotEntry = toolboxSlots.next(); WeakHashMap set = toolboxSlotEntry.getValue(); @@ -121,7 +125,7 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider boolean clear = referenceItem.isEmpty(); for (Iterator> playerEntries = set.entrySet() - .iterator(); playerEntries.hasNext();) { + .iterator(); playerEntries.hasNext(); ) { Entry playerEntry = playerEntries.next(); Player player = playerEntry.getKey(); @@ -213,16 +217,11 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider Set affected = new HashSet<>(); - for (Iterator>> toolboxSlots = connectedPlayers.entrySet() - .iterator(); toolboxSlots.hasNext();) { + for (Entry> toolboxSlotEntry : connectedPlayers.entrySet()) { - Entry> toolboxSlotEntry = toolboxSlots.next(); WeakHashMap set = toolboxSlotEntry.getValue(); - for (Iterator> playerEntries = set.entrySet() - .iterator(); playerEntries.hasNext();) { - Entry playerEntry = playerEntries.next(); - + for (Entry playerEntry : set.entrySet()) { Player player = playerEntry.getKey(); int hotbarSlot = playerEntry.getValue(); @@ -257,17 +256,17 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider private void tickAudio() { Vec3 vec = VecHelper.getCenterOf(worldPosition); if (lid.settled()) { - if (openCount > 0 && lid.getChaseTarget() == 0) { + if (openTracker.openCount > 0 && lid.getChaseTarget() == 0) { level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_OPEN, SoundSource.BLOCKS, 0.25F, level.random.nextFloat() * 0.1F + 1.2F, true); level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_OPEN, SoundSource.BLOCKS, 0.1F, level.random.nextFloat() * 0.1F + 1.1F, true); } - if (openCount == 0 && lid.getChaseTarget() == 1) + if (openTracker.openCount == 0 && lid.getChaseTarget() == 1) level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_CLOSE, SoundSource.BLOCKS, 0.1F, level.random.nextFloat() * 0.1F + 1.1F, true); - } else if (openCount == 0 && lid.getChaseTarget() == 0 && lid.getValue(0) > 1 / 16f + } else if (openTracker.openCount == 0 && lid.getChaseTarget() == 0 && lid.getValue(0) > 1 / 16f && lid.getValue(1) < 1 / 16f) level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, 0.25F, level.random.nextFloat() * 0.1F + 1.2F, true); @@ -288,8 +287,6 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider this.uniqueId = compound.getUUID("UniqueId"); if (compound.contains("CustomName", 8)) this.customName = Component.Serializer.fromJson(compound.getString("CustomName")); - if (clientPacket) - openCount = compound.getInt("OpenCount"); } @Override @@ -303,8 +300,6 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider if (customName != null) compound.putString("CustomName", Component.Serializer.toJson(customName)); super.write(compound, clientPacket); - if (clientPacket) - compound.putInt("OpenCount", openCount); } @Override @@ -314,46 +309,11 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider @Override public void lazyTick() { - updateOpenCount(); // keep re-advertising active TEs ToolboxHandler.onLoad(this); super.lazyTick(); } - void updateOpenCount() { - if (level.isClientSide) - return; - if (openCount == 0) - return; - - int prevOpenCount = openCount; - openCount = 0; - - for (Player playerentity : level.getEntitiesOfClass(Player.class, new AABB(worldPosition).inflate(8))) - if (playerentity.containerMenu instanceof ToolboxMenu - && ((ToolboxMenu) playerentity.containerMenu).contentHolder == this) - openCount++; - - if (prevOpenCount != openCount) - sendData(); - } - - public void startOpen(Player player) { - if (player.isSpectator()) - return; - if (openCount < 0) - openCount = 0; - openCount++; - sendData(); - } - - public void stopOpen(Player player) { - if (player.isSpectator()) - return; - openCount--; - sendData(); - } - public void connectPlayer(int slot, Player player, int hotbarSlot) { if (level.isClientSide) return; @@ -392,8 +352,8 @@ public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider public Component getDisplayName() { return customName != null ? customName : AllBlocks.TOOLBOXES.get(getColor()) - .get() - .getName(); + .get() + .getName(); } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDisposeAllPacket.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDisposeAllPacket.java index 1890dadb04..924a61054b 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDisposeAllPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDisposeAllPacket.java @@ -12,6 +12,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.network.NetworkEvent.Context; @@ -43,9 +44,8 @@ public class ToolboxDisposeAllPacket extends SimplePacketBase { if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange * maxRange) return; - if (!(blockEntity instanceof ToolboxBlockEntity)) + if (!(blockEntity instanceof ToolboxBlockEntity toolbox)) return; - ToolboxBlockEntity toolbox = (ToolboxBlockEntity) blockEntity; CompoundTag compound = player.getPersistentData() .getCompound("CreateToolboxData"); @@ -55,19 +55,19 @@ public class ToolboxDisposeAllPacket extends SimplePacketBase { for (int i = 0; i < 36; i++) { String key = String.valueOf(i); if (compound.contains(key) && NbtUtils.readBlockPos(compound.getCompound(key) - .getCompound("Pos")) + .getCompound("Pos")) .equals(toolboxPos)) { ToolboxHandler.unequip(player, i, true); sendData.setTrue(); } - + ItemStack itemStack = player.getInventory().getItem(i); ItemStack remainder = ItemHandlerHelper.insertItemStacked(toolbox.inventory, itemStack, false); if (remainder.getCount() != itemStack.getCount()) player.getInventory().setItem(i, remainder); } }); - + if (sendData.booleanValue()) ToolboxHandler.syncData(player); }); diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxEquipPacket.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxEquipPacket.java index a63c4befaf..4352c4c567 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxEquipPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxEquipPacket.java @@ -10,6 +10,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.network.NetworkEvent.Context; @@ -59,7 +60,7 @@ public class ToolboxEquipPacket extends SimplePacketBase { if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange * maxRange) return; - if (!(blockEntity instanceof ToolboxBlockEntity)) + if (!(blockEntity instanceof ToolboxBlockEntity toolboxBlockEntity)) return; ToolboxHandler.unequip(player, hotbarSlot, false); @@ -69,8 +70,6 @@ public class ToolboxEquipPacket extends SimplePacketBase { return; } - ToolboxBlockEntity toolboxBlockEntity = (ToolboxBlockEntity) blockEntity; - ItemStack playerStack = player.getInventory().getItem(hotbarSlot); if (!playerStack.isEmpty() && !ToolboxInventory.canItemsShareCompartment(playerStack, toolboxBlockEntity.inventory.filters.get(slot))) { diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandler.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandler.java index 31a5666bff..f2718a0458 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandler.java @@ -6,9 +6,9 @@ import java.util.stream.Collectors; import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.networking.ISyncPersistentData.PersistentDataPacket; -import com.simibubi.create.foundation.utility.WorldAttached; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.WorldAttached; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; @@ -20,6 +20,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.network.PacketDistributor; public class ToolboxHandler { @@ -44,12 +45,11 @@ public class ToolboxHandler { return; if (!(world instanceof ServerLevel)) return; - if (!(entity instanceof ServerPlayer)) + if (!(entity instanceof ServerPlayer player)) return; if (entity.tickCount % validationTimer != 0) return; - ServerPlayer player = (ServerPlayer) entity; if (!player.getPersistentData() .contains("CreateToolboxData")) return; @@ -90,8 +90,8 @@ public class ToolboxHandler { if (player.getPersistentData() .contains("CreateToolboxData") && !player.getPersistentData() - .getCompound("CreateToolboxData") - .isEmpty()) { + .getCompound("CreateToolboxData") + .isEmpty()) { syncData(player); } } @@ -128,8 +128,7 @@ public class ToolboxHandler { int prevSlot = prevData.getInt("Slot"); BlockEntity prevBlockEntity = world.getBlockEntity(prevPos); - if (prevBlockEntity instanceof ToolboxBlockEntity) { - ToolboxBlockEntity toolbox = (ToolboxBlockEntity) prevBlockEntity; + if (prevBlockEntity instanceof ToolboxBlockEntity toolbox) { toolbox.unequip(prevSlot, player, hotbarSlot, keepItems || !ToolboxHandler.withinRange(player, toolbox)); } compound.remove(key); diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandlerClient.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandlerClient.java index 7e8e668d5c..8a42bbb9f2 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandlerClient.java @@ -14,8 +14,8 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllKeys; import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.ScreenOpener; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.player.LocalPlayer; diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java index bb16f4feb9..0c042c0c8c 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java @@ -6,9 +6,12 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.item.ItemSlots; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; @@ -16,6 +19,10 @@ import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; public class ToolboxInventory extends ItemStackHandler { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + ItemSlots.maxSizeCodec(8).fieldOf("items").forGetter(ItemSlots::fromHandler), + ItemStack.CODEC.listOf().fieldOf("filters").forGetter(toolbox -> toolbox.filters) + ).apply(instance, ToolboxInventory::deserialize)); public static final int STACKS_PER_COMPARTMENT = 4; List filters; @@ -212,4 +219,11 @@ public class ToolboxInventory extends ItemStackHandler { blockEntity.notifyUpdate(); } + private static ToolboxInventory deserialize(ItemSlots slots, List filters) { + ToolboxInventory inventory = new ToolboxInventory(null); + slots.forEach(inventory::setStackInSlot); + inventory.filters = filters; + return inventory; + } + } diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMenu.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMenu.java index 8dca8ec499..d7ca5fd995 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMenu.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMenu.java @@ -3,6 +3,8 @@ package com.simibubi.create.content.equipment.toolbox; import static com.simibubi.create.content.equipment.toolbox.ToolboxInventory.STACKS_PER_COMPARTMENT; import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.animatedContainer.AnimatedContainerBehaviour; import com.simibubi.create.foundation.gui.menu.MenuBase; import net.minecraft.client.Minecraft; @@ -17,6 +19,7 @@ import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraftforge.items.SlotItemHandler; public class ToolboxMenu extends MenuBase { @@ -27,7 +30,8 @@ public class ToolboxMenu extends MenuBase { public ToolboxMenu(MenuType type, int id, Inventory inv, ToolboxBlockEntity be) { super(type, id, inv, be); - be.startOpen(player); + BlockEntityBehaviour.get(be, AnimatedContainerBehaviour.TYPE) + .startOpen(player); } public static ToolboxMenu create(int id, Inventory inv, ToolboxBlockEntity be) { @@ -41,8 +45,7 @@ public class ToolboxMenu extends MenuBase { ClientLevel world = Minecraft.getInstance().level; BlockEntity blockEntity = world.getBlockEntity(readBlockPos); - if (blockEntity instanceof ToolboxBlockEntity) { - ToolboxBlockEntity toolbox = (ToolboxBlockEntity) blockEntity; + if (blockEntity instanceof ToolboxBlockEntity toolbox) { toolbox.readClient(readNbt); return toolbox; } @@ -127,8 +130,8 @@ public class ToolboxMenu extends MenuBase { int x = 79; int y = 37; - int[] xOffsets = { x, x + 33, x + 66, x + 66 + 6, x + 66, x + 33, x, x - 6 }; - int[] yOffsets = { y, y - 6, y, y + 33, y + 66, y + 66 + 6, y + 66, y + 33 }; + int[] xOffsets = {x, x + 33, x + 66, x + 66 + 6, x + 66, x + 33, x, x - 6}; + int[] yOffsets = {y, y - 6, y, y + 33, y + 66, y + 66 + 6, y + 66, y + 33}; for (int compartment = 0; compartment < 8; compartment++) { int baseIndex = compartment * STACKS_PER_COMPARTMENT; @@ -153,7 +156,8 @@ public class ToolboxMenu extends MenuBase { public void removed(Player playerIn) { super.removed(playerIn); if (!playerIn.level().isClientSide) - contentHolder.stopOpen(playerIn); + BlockEntityBehaviour.get(contentHolder, AnimatedContainerBehaviour.TYPE) + .stopOpen(playerIn); } } diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorage.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorage.java new file mode 100644 index 0000000000..b984915c0f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorage.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.equipment.toolbox; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.WrapperMountedItemStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.item.ItemHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +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 net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +public class ToolboxMountedStorage extends WrapperMountedItemStorage { + public static final Codec CODEC = ToolboxInventory.CODEC.xmap( + ToolboxMountedStorage::new, storage -> storage.wrapped + ); + + protected ToolboxMountedStorage(MountedItemStorageType type, ToolboxInventory wrapped) { + super(type, wrapped); + } + + protected ToolboxMountedStorage(ToolboxInventory wrapped) { + this(AllMountedStorageTypes.TOOLBOX.get(), wrapped); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof ToolboxBlockEntity toolbox) { + ItemHelper.copyContents(this, toolbox.inventory); + } + } + + @Override + public boolean handleInteraction(ServerPlayer player, Contraption contraption, StructureBlockInfo info) { + // The default impl will fail anyway, might as well cancel trying + return false; + } + + public static ToolboxMountedStorage fromToolbox(ToolboxBlockEntity toolbox) { + // the inventory will send updates to the block entity, make an isolated copy to avoid that + ToolboxInventory copy = new ToolboxInventory(null); + ItemHelper.copyContents(toolbox.inventory, copy); + copy.filters = toolbox.inventory.filters.stream().map(ItemStack::copy).toList(); + return new ToolboxMountedStorage(copy); + } + + public static ToolboxMountedStorage fromLegacy(CompoundTag nbt) { + ToolboxInventory inv = new ToolboxInventory(null); + inv.deserializeNBT(nbt); + return new ToolboxMountedStorage(inv); + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorageType.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorageType.java new file mode 100644 index 0000000000..7ff776e95a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorageType.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.equipment.toolbox; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class ToolboxMountedStorageType extends MountedItemStorageType { + public ToolboxMountedStorageType() { + super(ToolboxMountedStorage.CODEC); + } + + @Override + @Nullable + public ToolboxMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + return be instanceof ToolboxBlockEntity toolbox ? ToolboxMountedStorage.fromToolbox(toolbox) : null; + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxRenderer.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxRenderer.java index 01f64202fb..1a61d5bade 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxRenderer.java @@ -4,10 +4,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -28,8 +28,8 @@ public class ToolboxRenderer extends SmartBlockEntityRenderer { @Override protected void init() { - setWindowSize(30 + BG.width, BG.height + PLAYER.height - 24); + setWindowSize(30 + BG.getWidth(), BG.getHeight() + PLAYER.getHeight() - 24); setWindowOffset(-11, 0); super.init(); clearWidgets(); color = menu.contentHolder.getColor(); - confirmButton = new IconButton(leftPos + 30 + BG.width - 33, topPos + BG.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(leftPos + 30 + BG.getWidth() - 33, topPos + BG.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { minecraft.player.closeContainer(); }); @@ -62,11 +62,11 @@ public class ToolboxScreen extends AbstractSimiContainerScreen { disposeButton.withCallback(() -> { AllPackets.getChannel().sendToServer(new ToolboxDisposeAllPacket(menu.contentHolder.getBlockPos())); }); - disposeButton.setToolTip(Lang.translateDirect("toolbox.depositBox")); + disposeButton.setToolTip(CreateLang.translateDirect("toolbox.depositBox")); addRenderableWidget(disposeButton); extraAreas = ImmutableList.of( - new Rect2i(leftPos + 30 + BG.width, topPos + BG.height - 15 - 34 - 6, 72, 68) + new Rect2i(leftPos + 30 + BG.getWidth(), topPos + BG.getHeight() - 15 - 34 - 6, 72, 68) ); } @@ -79,17 +79,17 @@ public class ToolboxScreen extends AbstractSimiContainerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - int x = leftPos + imageWidth - BG.width; + int x = leftPos + imageWidth - BG.getWidth(); int y = topPos; BG.render(graphics, x, y); graphics.drawString(font, title, x + 15, y + 4, 0x592424, false); int invX = leftPos; - int invY = topPos + imageHeight - PLAYER.height; + int invY = topPos + imageHeight - PLAYER.getHeight(); renderPlayerInventory(graphics, invX, invY); - renderToolbox(graphics, x + BG.width + 50, y + BG.height + 12, partialTicks); + renderToolbox(graphics, x + BG.getWidth() + 50, y + BG.getHeight() + 12, partialTicks); PoseStack ms = graphics.pose(); diff --git a/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchable.java b/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchable.java index 876d99baa7..551645d5bf 100644 --- a/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchable.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchable.java @@ -4,13 +4,12 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; -import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; -import com.simibubi.create.foundation.utility.VoxelShaper; +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -20,7 +19,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.level.BlockEvent; @@ -28,21 +26,16 @@ import net.minecraftforge.event.level.BlockEvent; public interface IWrenchable { default InteractionResult onWrenched(BlockState state, UseOnContext context) { - Level world = context.getLevel(); + Level level = context.getLevel(); + BlockPos pos = context.getClickedPos(); BlockState rotated = getRotatedBlockState(state, context.getClickedFace()); - if (!rotated.canSurvive(world, context.getClickedPos())) + if (!rotated.canSurvive(level, context.getClickedPos())) return InteractionResult.PASS; - KineticBlockEntity.switchToBlockState(world, context.getClickedPos(), updateAfterWrenched(rotated, context)); + KineticBlockEntity.switchToBlockState(level, pos, updateAfterWrenched(rotated, context)); - BlockEntity be = context.getLevel() - .getBlockEntity(context.getClickedPos()); - if (be instanceof GeneratingKineticBlockEntity) { - ((GeneratingKineticBlockEntity) be).reActivateSource = true; - } - - if (world.getBlockState(context.getClickedPos()) != state) - playRotateSound(world, context.getClickedPos()); + if (level.getBlockState(pos) != state) + playRotateSound(level, pos); return InteractionResult.SUCCESS; } @@ -79,12 +72,12 @@ public interface IWrenchable { return InteractionResult.SUCCESS; } - default void playRemoveSound(Level world, BlockPos pos) { - AllSoundEvents.WRENCH_REMOVE.playOnServer(world, pos, 1, Create.RANDOM.nextFloat() * .5f + .5f); + static void playRemoveSound(Level level, BlockPos pos) { + AllSoundEvents.WRENCH_REMOVE.playOnServer(level, pos, 1, Create.RANDOM.nextFloat() * .5f + .5f); } - default void playRotateSound(Level world, BlockPos pos) { - AllSoundEvents.WRENCH_ROTATE.playOnServer(world, pos, 1, Create.RANDOM.nextFloat() + .5f); + static void playRotateSound(Level level, BlockPos pos) { + AllSoundEvents.WRENCH_ROTATE.playOnServer(level, pos, 1, Create.RANDOM.nextFloat() + .5f); } default BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { diff --git a/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchEventHandler.java b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchEventHandler.java index b9d6bb3bbe..72f66f9ca4 100644 --- a/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchEventHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchEventHandler.java @@ -10,6 +10,7 @@ import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; + import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -40,12 +41,11 @@ public class WrenchEventHandler { .getBlockState(event.getPos()); Block block = state.getBlock(); - if (!(block instanceof IWrenchable)) + if (!(block instanceof IWrenchable actor)) return; BlockHitResult hitVec = event.getHitVec(); UseOnContext context = new UseOnContext(player, event.getHand(), hitVec); - IWrenchable actor = (IWrenchable) block; InteractionResult result = player.isShiftKeyDown() ? actor.onSneakWrenched(state, context) : actor.onWrenched(state, context); diff --git a/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItem.java b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItem.java index cfdf6b45c4..9dfc92e907 100644 --- a/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItem.java @@ -22,6 +22,7 @@ import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientItemExtensions; @@ -44,13 +45,12 @@ public class WrenchItem extends Item { .getBlockState(context.getClickedPos()); Block block = state.getBlock(); - if (!(block instanceof IWrenchable)) { + if (!(block instanceof IWrenchable actor)) { if (player.isShiftKeyDown() && canWrenchPickup(state)) return onItemUseOnOther(context); return super.useOn(context); } - IWrenchable actor = (IWrenchable) block; if (player.isShiftKeyDown()) return actor.onSneakWrenched(state, context); return actor.onWrenched(state, context); @@ -78,7 +78,7 @@ public class WrenchItem extends Item { public static void wrenchInstaKillsMinecarts(AttackEntityEvent event) { Entity target = event.getTarget(); - if (!(target instanceof AbstractMinecart)) + if (!(target instanceof AbstractMinecart minecart)) return; Player player = event.getEntity(); ItemStack heldItem = player.getMainHandItem(); @@ -86,7 +86,6 @@ public class WrenchItem extends Item { return; if (player.isCreative()) return; - AbstractMinecart minecart = (AbstractMinecart) target; minecart.hurt(minecart.damageSources().playerAttack(player), 100); } diff --git a/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItemRenderer.java index f5863190e3..93561881fa 100644 --- a/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItemRenderer.java @@ -7,9 +7,9 @@ import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollVa import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/PlacementPatterns.java b/src/main/java/com/simibubi/create/content/equipment/zapper/PlacementPatterns.java index 4391b0769e..c4d1e6b70f 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/PlacementPatterns.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/PlacementPatterns.java @@ -6,8 +6,8 @@ import java.util.function.Predicate; import com.google.common.base.Predicates; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; @@ -35,7 +35,7 @@ public enum PlacementPatterns { !tag.contains("Pattern") ? Solid : valueOf(tag.getString("Pattern")); Random r = new Random(); Predicate filter = Predicates.alwaysFalse(); - + switch (pattern) { case Chance25: filter = pos -> r.nextBoolean() || r.nextBoolean(); @@ -56,7 +56,7 @@ public enum PlacementPatterns { default: break; } - + blocksIn.removeIf(filter); } diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItem.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItem.java index 45bd8d4903..fc91256633 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItem.java @@ -11,10 +11,10 @@ import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.item.CustomArmPoseItem; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.NBTProcessors; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.nbt.NBTProcessors; import net.minecraft.ChatFormatting; import net.minecraft.client.model.HumanoidModel.ArmPose; import net.minecraft.client.player.AbstractClientPlayer; @@ -64,7 +64,7 @@ public abstract class ZapperItem extends Item implements CustomArmPoseItem { .getCompound("BlockUsed")) .getBlock() .getName(); - tooltip.add(Lang.translateDirect("terrainzapper.usingBlock", + tooltip.add(CreateLang.translateDirect("terrainzapper.usingBlock", usedBlock.withStyle(ChatFormatting.GRAY)) .withStyle(ChatFormatting.DARK_GRAY)); } @@ -186,7 +186,7 @@ public abstract class ZapperItem extends Item implements CustomArmPoseItem { public Component validateUsage(ItemStack item) { CompoundTag tag = item.getOrCreateTag(); if (!canActivateWithoutSelectedBlock(item) && !tag.contains("BlockUsed")) - return Lang.translateDirect("terrainzapper.leftClickToSet"); + return CreateLang.translateDirect("terrainzapper.leftClickToSet"); return null; } diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperRenderHandler.java index cd32e71c63..43af3b4ff5 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperRenderHandler.java @@ -8,8 +8,8 @@ import java.util.function.Supplier; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.CreateClient; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.particles.ParticleTypes; @@ -38,7 +38,7 @@ public class ZapperRenderHandler extends ShootableGadgetRenderHandler { return; cachedBeams.forEach(beam -> { - CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity, false) + Outliner.getInstance().endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity, false) .disableLineNormals() .colored(0xffffff) .lineWidth(beam.itensity * 1 / 8f); diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperScreen.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperScreen.java index d4e740d990..3dd8cfbb8e 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperScreen.java @@ -5,19 +5,19 @@ import java.util.Vector; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; @@ -26,7 +26,7 @@ import net.minecraft.world.level.block.state.BlockState; public abstract class ZapperScreen extends AbstractSimiScreen { - protected final Component patternSection = Lang.translateDirect("gui.terrainzapper.patternSection"); + protected final Component patternSection = CreateLang.translateDirect("gui.terrainzapper.patternSection"); protected AllGuiTextures background; protected ItemStack zapper; @@ -46,7 +46,7 @@ public abstract class ZapperScreen extends AbstractSimiScreen { this.background = background; this.zapper = zapper; this.hand = hand; - title = Components.immutableEmpty(); + title = CommonComponents.EMPTY; brightColor = 0xFEFEFE; fontColor = AllGuiTextures.FONT_COLOR; @@ -56,7 +56,7 @@ public abstract class ZapperScreen extends AbstractSimiScreen { @Override protected void init() { - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); setWindowOffset(-10, 0); super.init(); @@ -66,7 +66,7 @@ public abstract class ZapperScreen extends AbstractSimiScreen { int y = guiTop; confirmButton = - new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { onClose(); }); @@ -77,18 +77,18 @@ public abstract class ZapperScreen extends AbstractSimiScreen { for (int col = 0; col <= 2; col++) { int id = patternButtons.size(); PlacementPatterns pattern = PlacementPatterns.values()[id]; - IconButton patternButton = new IconButton(x + background.width - 76 + col * 18, y + 21 + row * 18, pattern.icon); + IconButton patternButton = new IconButton(x + background.getWidth() - 76 + col * 18, y + 21 + row * 18, pattern.icon); patternButton.withCallback(() -> { - patternButtons.forEach(b -> b.active = true); - patternButton.active = false; + patternButtons.forEach(b -> b.green = false); + patternButton.green = true; currentPattern = pattern; }); - patternButton.setToolTip(Lang.translateDirect("gui.terrainzapper.pattern." + pattern.translationKey)); + patternButton.setToolTip(CreateLang.translateDirect("gui.terrainzapper.pattern." + pattern.translationKey)); patternButtons.add(patternButton); } } - patternButtons.get(currentPattern.ordinal()).active = false; + patternButtons.get(currentPattern.ordinal()).green = true; addRenderableWidgets(patternButtons); } @@ -106,7 +106,7 @@ public abstract class ZapperScreen extends AbstractSimiScreen { } protected void drawOnBackground(GuiGraphics graphics, int x, int y) { - graphics.drawString(font, title, x + 11, y + 4, 0x54214F, false); + graphics.drawString(font, title, x + (background.getWidth() - font.width(title)) / 2, y + 4, 0x54214F, false); } @Override @@ -124,9 +124,9 @@ public abstract class ZapperScreen extends AbstractSimiScreen { protected void renderZapper(GuiGraphics graphics, int x, int y) { GuiGameElement.of(zapper) - .scale(4) - .at(x + background.width, y + background.height - 48, -200) - .render(graphics); + .scale(4) + .at(x + background.getWidth(), y + background.getHeight() - 48, -200) + .render(graphics); } @SuppressWarnings("deprecation") diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/Brush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/Brush.java index a015a02b55..577fcba0e8 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/Brush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/Brush.java @@ -2,7 +2,7 @@ package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.Collection; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -30,7 +30,7 @@ public abstract class Brush { public TerrainTools[] getSupportedTools() { return TerrainTools.values(); } - + public TerrainTools redirectTool(TerrainTools tool) { return tool; } @@ -52,7 +52,7 @@ public abstract class Brush { } Component getParamLabel(int paramIndex) { - return Lang + return CreateLang .translateDirect(paramIndex == 0 ? "generic.width" : paramIndex == 1 ? "generic.height" : "generic.length"); } diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CylinderBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CylinderBrush.java index 8afb01d7a6..8dfec4faf6 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CylinderBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CylinderBrush.java @@ -8,9 +8,9 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.AxisDirection; @@ -74,7 +74,7 @@ public class CylinderBrush extends ShapedBrush { @Override Component getParamLabel(int paramIndex) { - return paramIndex == 0 ? Lang.translateDirect("generic.radius") : super.getParamLabel(paramIndex); + return paramIndex == 0 ? CreateLang.translateDirect("generic.radius") : super.getParamLabel(paramIndex); } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/DynamicBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/DynamicBrush.java index a7aacdef3a..9d355df59b 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/DynamicBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/DynamicBrush.java @@ -7,7 +7,7 @@ import java.util.List; import java.util.Set; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -27,7 +27,7 @@ public class DynamicBrush extends Brush { } Component getParamLabel(int paramIndex) { - return Lang.translateDirect("generic.range"); + return CreateLang.translateDirect("generic.range"); } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/PlacementOptions.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/PlacementOptions.java index 840327a951..ec37d6b707 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/PlacementOptions.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/PlacementOptions.java @@ -1,7 +1,8 @@ package com.simibubi.create.content.equipment.zapper.terrainzapper; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; + +import net.createmod.catnip.lang.Lang; public enum PlacementOptions { diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/SphereBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/SphereBrush.java index 91b859a16a..560deb3278 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/SphereBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/SphereBrush.java @@ -5,9 +5,9 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; @@ -51,7 +51,7 @@ public class SphereBrush extends ShapedBrush { @Override Component getParamLabel(int paramIndex) { - return Lang.translateDirect("generic.radius"); + return CreateLang.translateDirect("generic.radius"); } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainTools.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainTools.java index c56212938d..930754e438 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainTools.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainTools.java @@ -6,8 +6,8 @@ import javax.annotation.Nullable; import com.simibubi.create.content.equipment.zapper.ZapperItem; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -26,7 +26,7 @@ public enum TerrainTools { Flatten(AllIcons.I_FLATTEN), ; - + public String translationKey; public AllIcons icon; diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItem.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItem.java index 57442b3fec..acd5b6204f 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItem.java @@ -6,11 +6,11 @@ import java.util.function.Consumer; import com.simibubi.create.content.equipment.zapper.PlacementPatterns; import com.simibubi.create.content.equipment.zapper.ZapperItem; -import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.ScreenOpener; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; @@ -51,7 +51,7 @@ public class WorldshaperItem extends ZapperItem { public Component validateUsage(ItemStack item) { if (!item.getOrCreateTag() .contains("BrushParams")) - return Lang.translateDirect("terrainzapper.shiftRightClickToSet"); + return CreateLang.translateDirect("terrainzapper.shiftRightClickToSet"); return super.validateUsage(item); } diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItemRenderer.java index 3074f12773..336a3b71c3 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItemRenderer.java @@ -8,9 +8,9 @@ import com.simibubi.create.Create; import com.simibubi.create.content.equipment.zapper.ZapperItemRenderer; import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.LightTexture; diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperRenderHandler.java index 48c5d2358a..230d28d28d 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperRenderHandler.java @@ -6,9 +6,9 @@ import java.util.function.Supplier; import com.simibubi.create.AllItems; import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -31,7 +31,7 @@ public class WorldshaperRenderHandler { if (renderedPositions == null) return; - CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get()) + Outliner.getInstance().showCluster("terrainZapper", renderedPositions.get()) .colored(0xbfbfbf) .disableLineNormals() .lineWidth(1 / 32f) diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperScreen.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperScreen.java index ac6d029577..0d0094800a 100644 --- a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperScreen.java @@ -13,25 +13,25 @@ import com.simibubi.create.foundation.gui.widget.Indicator.State; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; public class WorldshaperScreen extends ZapperScreen { - protected final Component placementSection = Lang.translateDirect("gui.terrainzapper.placement"); - protected final Component toolSection = Lang.translateDirect("gui.terrainzapper.tool"); + protected final Component placementSection = CreateLang.translateDirect("gui.terrainzapper.placement"); + protected final Component toolSection = CreateLang.translateDirect("gui.terrainzapper.tool"); protected final List brushOptions = - Lang.translatedOptions("gui.terrainzapper.brush", "cuboid", "sphere", "cylinder", "surface", "cluster"); + CreateLang.translatedOptions("gui.terrainzapper.brush", "cuboid", "sphere", "cylinder", "surface", "cluster"); protected Vector toolButtons; protected Vector placementButtons; @@ -46,7 +46,7 @@ public class WorldshaperScreen extends ZapperScreen { protected Indicator acrossMaterialsIndicator; protected TerrainBrushes currentBrush; - protected int[] currentBrushParams = new int[] { 1, 1, 1 }; + protected int[] currentBrushParams = new int[]{1, 1, 1}; protected boolean currentFollowDiagonals; protected boolean currentAcrossMaterials; protected TerrainTools currentTool; @@ -82,9 +82,9 @@ public class WorldshaperScreen extends ZapperScreen { int x = guiLeft; int y = guiTop; - brushLabel = new Label(x + 61, y + 25, Components.immutableEmpty()).withShadow(); + brushLabel = new Label(x + 61, y + 25, CommonComponents.EMPTY).withShadow(); brushInput = new SelectionScrollInput(x + 56, y + 20, 77, 18).forOptions(brushOptions) - .titled(Lang.translateDirect("gui.terrainzapper.brush")) + .titled(CreateLang.translateDirect("gui.terrainzapper.brush")) .writingTo(brushLabel) .calling(brushIndex -> { currentBrush = TerrainBrushes.values()[brushIndex]; @@ -111,7 +111,7 @@ public class WorldshaperScreen extends ZapperScreen { brushParams.clear(); for (int index = 0; index < 3; index++) { - Label label = new Label(x + 65 + 20 * index, y + 45, Components.immutableEmpty()).withShadow(); + Label label = new Label(x + 65 + 20 * index, y + 45, CommonComponents.EMPTY).withShadow(); final int finalIndex = index; ScrollInput input = new ScrollInput(x + 56 + 20 * index, y + 40, 18, 18) @@ -155,22 +155,22 @@ public class WorldshaperScreen extends ZapperScreen { if (currentBrush.hasConnectivityOptions()) { int x1 = x + 7 + 4 * 18; int y1 = y + 79; - followDiagonalsIndicator = new Indicator(x1, y1 - 6, Components.immutableEmpty()); + followDiagonalsIndicator = new Indicator(x1, y1 - 6, CommonComponents.EMPTY); followDiagonals = new IconButton(x1, y1, AllIcons.I_FOLLOW_DIAGONAL); x1 += 18; - acrossMaterialsIndicator = new Indicator(x1, y1 - 6, Components.immutableEmpty()); + acrossMaterialsIndicator = new Indicator(x1, y1 - 6, CommonComponents.EMPTY); acrossMaterials = new IconButton(x1, y1, AllIcons.I_FOLLOW_MATERIAL); followDiagonals.withCallback(() -> { followDiagonalsIndicator.state = followDiagonalsIndicator.state == State.OFF ? State.ON : State.OFF; currentFollowDiagonals = !currentFollowDiagonals; }); - followDiagonals.setToolTip(Lang.translateDirect("gui.terrainzapper.searchDiagonal")); + followDiagonals.setToolTip(CreateLang.translateDirect("gui.terrainzapper.searchDiagonal")); acrossMaterials.withCallback(() -> { acrossMaterialsIndicator.state = acrossMaterialsIndicator.state == State.OFF ? State.ON : State.OFF; currentAcrossMaterials = !currentAcrossMaterials; }); - acrossMaterials.setToolTip(Lang.translateDirect("gui.terrainzapper.searchFuzzy")); + acrossMaterials.setToolTip(CreateLang.translateDirect("gui.terrainzapper.searchFuzzy")); addRenderableWidget(followDiagonals); addRenderableWidget(followDiagonalsIndicator); addRenderableWidget(acrossMaterials); @@ -192,11 +192,11 @@ public class WorldshaperScreen extends ZapperScreen { TerrainTools tool = toolValues[id]; IconButton toolButton = new IconButton(x + 7 + id * 18, y + 79, tool.icon); toolButton.withCallback(() -> { - toolButtons.forEach(b -> b.active = true); - toolButton.active = false; + toolButtons.forEach(b -> b.green = false); + toolButton.green = true; currentTool = tool; }); - toolButton.setToolTip(Lang.translateDirect("gui.terrainzapper.tool." + tool.translationKey)); + toolButton.setToolTip(CreateLang.translateDirect("gui.terrainzapper.tool." + tool.translationKey)); toolButtons.add(toolButton); } @@ -208,7 +208,7 @@ public class WorldshaperScreen extends ZapperScreen { currentTool = toolValues[0]; toolIndex = 0; } - toolButtons.get(toolIndex).active = false; + toolButtons.get(toolIndex).green = true; addRenderableWidgets(toolButtons); @@ -224,15 +224,15 @@ public class WorldshaperScreen extends ZapperScreen { PlacementOptions option = placementValues[id]; IconButton placementButton = new IconButton(x + 136 + id * 18, y + 79, option.icon); placementButton.withCallback(() -> { - placementButtons.forEach(b -> b.active = true); - placementButton.active = false; + placementButtons.forEach(b -> b.green = false); + placementButton.green = true; currentPlacement = option; }); - placementButton.setToolTip(Lang.translateDirect("gui.terrainzapper.placement." + option.translationKey)); + placementButton.setToolTip(CreateLang.translateDirect("gui.terrainzapper.placement." + option.translationKey)); placementButtons.add(placementButton); } - placementButtons.get(currentPlacement.ordinal()).active = false; + placementButtons.get(currentPlacement.ordinal()).green = true; addRenderableWidgets(placementButtons); } diff --git a/src/main/java/com/simibubi/create/content/fluids/FlowSource.java b/src/main/java/com/simibubi/create/content/fluids/FlowSource.java index 93f37122b0..8afe52a46d 100644 --- a/src/main/java/com/simibubi/create/content/fluids/FlowSource.java +++ b/src/main/java/com/simibubi/create/content/fluids/FlowSource.java @@ -4,8 +4,8 @@ import java.lang.ref.WeakReference; import java.util.function.Predicate; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; +import net.createmod.catnip.math.BlockFace; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.common.capabilities.ForgeCapabilities; diff --git a/src/main/java/com/simibubi/create/content/fluids/FluidBottleItemHook.java b/src/main/java/com/simibubi/create/content/fluids/FluidBottleItemHook.java index c6074eccd1..017125bce5 100644 --- a/src/main/java/com/simibubi/create/content/fluids/FluidBottleItemHook.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidBottleItemHook.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.fluids; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.core.BlockPos; import net.minecraft.tags.FluidTags; import net.minecraft.world.InteractionResult; @@ -44,7 +44,7 @@ public class FluidBottleItemHook extends Item { return; FluidState fluidState = world.getFluidState(blockpos); - if (fluidState.is(FluidTags.WATER) && RegisteredObjects.getKeyOrThrow(fluidState.getType()) + if (fluidState.is(FluidTags.WATER) && CatnipServices.REGISTRIES.getKeyOrThrow(fluidState.getType()) .getNamespace() .equals(Create.ID)) { event.setCancellationResult(InteractionResult.PASS); diff --git a/src/main/java/com/simibubi/create/content/fluids/FluidFX.java b/src/main/java/com/simibubi/create/content/fluids/FluidFX.java index f91f54b14e..6ca828353d 100644 --- a/src/main/java/com/simibubi/create/content/fluids/FluidFX.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidFX.java @@ -3,8 +3,8 @@ package com.simibubi.create.content.fluids; import com.simibubi.create.AllParticleTypes; import com.simibubi.create.content.fluids.particle.FluidParticleData; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/fluids/FluidNetwork.java b/src/main/java/com/simibubi/create/content/fluids/FluidNetwork.java index e012b8119c..810fc5721a 100644 --- a/src/main/java/com/simibubi/create/content/fluids/FluidNetwork.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidNetwork.java @@ -17,10 +17,10 @@ import com.simibubi.create.content.contraptions.actors.psi.PortableFluidInterfac import com.simibubi.create.content.fluids.PipeConnection.Flow; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.math.BlockFace; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; @@ -185,7 +185,7 @@ public class FluidNetwork { int flowSpeed = transferSpeed; Map accumulatedFill = new IdentityHashMap<>(); - + for (boolean simulate : Iterate.trueAndFalse) { FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE; @@ -214,9 +214,9 @@ public class FluidNetwork { return; if (simulate) flowSpeed = transfer.getAmount(); - + List>> availableOutputs = new ArrayList<>(targets); - + while (!availableOutputs.isEmpty() && transfer.getAmount() > 0) { int dividedTransfer = transfer.getAmount() / availableOutputs.size(); int remainder = transfer.getAmount() % availableOutputs.size(); @@ -238,20 +238,20 @@ public class FluidNetwork { iterator.remove(); continue; } - + int simulatedTransfer = toTransfer; if (simulate) simulatedTransfer += accumulatedFill.getOrDefault(targetHandler, 0); - + FluidStack divided = transfer.copy(); divided.setAmount(simulatedTransfer); int fill = targetHandler.fill(divided, action); - + if (simulate) { accumulatedFill.put(targetHandler, Integer.valueOf(fill)); fill -= simulatedTransfer - toTransfer; } - + transfer.setAmount(transfer.getAmount() - fill); if (fill < simulatedTransfer) iterator.remove(); diff --git a/src/main/java/com/simibubi/create/content/fluids/FluidPropagator.java b/src/main/java/com/simibubi/create/content/fluids/FluidPropagator.java index ef5000bf2d..874a985fff 100644 --- a/src/main/java/com/simibubi/create/content/fluids/FluidPropagator.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidPropagator.java @@ -19,10 +19,10 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.CreateAdvancement; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/fluids/FluidTransportBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/FluidTransportBehaviour.java index bcd2f64dfc..b2ee5fac40 100644 --- a/src/main/java/com/simibubi/create/content/fluids/FluidTransportBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidTransportBehaviour.java @@ -14,9 +14,9 @@ import com.simibubi.create.content.fluids.pump.PumpBlock; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.WorldAttached; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.WorldAttached; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -260,6 +260,7 @@ public abstract class FluidTransportBehaviour extends BlockEntityBehaviour { public enum AttachmentTypes { NONE, CONNECTION(ComponentPartials.CONNECTION), + DETAILED_CONNECTION(ComponentPartials.RIM_CONNECTOR), RIM(ComponentPartials.RIM_CONNECTOR, ComponentPartials.RIM), PARTIAL_RIM(ComponentPartials.RIM), DRAIN(ComponentPartials.RIM_CONNECTOR, ComponentPartials.DRAIN), diff --git a/src/main/java/com/simibubi/create/content/fluids/OpenEndedPipe.java b/src/main/java/com/simibubi/create/content/fluids/OpenEndedPipe.java index f4b633d10a..fe72d43da2 100644 --- a/src/main/java/com/simibubi/create/content/fluids/OpenEndedPipe.java +++ b/src/main/java/com/simibubi/create/content/fluids/OpenEndedPipe.java @@ -2,38 +2,25 @@ package com.simibubi.create.content.fluids; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; -import java.util.ArrayList; -import java.util.List; - import javax.annotation.Nullable; import com.simibubi.create.AllFluids; +import com.simibubi.create.api.effect.OpenPipeEffectHandler; import com.simibubi.create.content.fluids.pipes.VanillaFluidTargets; -import com.simibubi.create.content.fluids.potion.PotionFluidHandler; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.BlockFace; +import com.simibubi.create.foundation.mixin.accessor.FlowingFluidAccessor; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.BlockFace; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.BlockTags; import net.minecraft.tags.FluidTags; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.alchemy.PotionUtils; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.AbstractCandleBlock; -import net.minecraft.world.level.block.CampfireBlock; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; @@ -41,7 +28,7 @@ import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.AABB; -import net.minecraftforge.common.Tags; + import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -49,16 +36,6 @@ import net.minecraftforge.fluids.capability.templates.FluidTank; public class OpenEndedPipe extends FlowSource { - private static final List EFFECT_HANDLERS = new ArrayList<>(); - - static { - registerEffectHandler(new PotionEffectHandler()); - registerEffectHandler(new MilkEffectHandler()); - registerEffectHandler(new WaterEffectHandler()); - registerEffectHandler(new LavaEffectHandler()); - registerEffectHandler(new TeaEffectHandler()); - } - private Level world; private BlockPos pos; private AABB aoe; @@ -67,9 +44,6 @@ public class OpenEndedPipe extends FlowSource { private BlockPos outputPos; private boolean wasPulling; - private FluidStack cachedFluid; - private List cachedEffects; - public OpenEndedPipe(BlockFace face) { super(face); fluidHandler = new OpenEndFluidHandler(); @@ -80,10 +54,6 @@ public class OpenEndedPipe extends FlowSource { aoe = aoe.expandTowards(0, -1, 0); } - public static void registerEffectHandler(IEffectHandler handler) { - EFFECT_HANDLERS.add(handler); - } - public Level getWorld() { return world; } @@ -166,10 +136,25 @@ public class OpenEndedPipe extends FlowSource { if (waterlog) { world.setBlock(outputPos, state.setValue(WATERLOGGED, false), 3); world.scheduleTick(outputPos, Fluids.WATER, 1); - return stack; + } else { + var newState = fluidState.createLegacyBlock() + .setValue(LiquidBlock.LEVEL, 14); + + var newFluidState = newState.getFluidState(); + + if (newFluidState.getType() instanceof FlowingFluidAccessor flowing) { + var potentiallyFilled = flowing.create$getNewLiquid(world, outputPos, newState); + + // Check if we'd immediately become the same fluid again. + if (potentiallyFilled.equals(fluidState)) { + // If so, no need to update the block state. + return stack; + } + } + + world.setBlock(outputPos, newState, 3); } - world.setBlock(outputPos, fluidState.createLegacyBlock() - .setValue(LiquidBlock.LEVEL, 14), 3); + return stack; } @@ -229,23 +214,6 @@ public class OpenEndedPipe extends FlowSource { return true; } - private boolean canApplyEffects(FluidStack fluid) { - for (IEffectHandler handler : EFFECT_HANDLERS) { - if (handler.canApplyEffects(this, fluid)) { - return true; - } - } - return false; - } - - private void applyEffects(FluidStack fluid) { - for (IEffectHandler handler : EFFECT_HANDLERS) { - if (handler.canApplyEffects(this, fluid)) { - handler.applyEffects(this, fluid); - } - } - } - private class OpenEndFluidHandler extends FluidTank { public OpenEndFluidHandler() { @@ -271,14 +239,22 @@ public class OpenEndedPipe extends FlowSource { setFluid(FluidStack.EMPTY); if (wasPulling) wasPulling = false; - if (canApplyEffects(resource) && !hasBlockState) + + OpenPipeEffectHandler effectHandler = OpenPipeEffectHandler.REGISTRY.get(resource.getFluid()); + if (effectHandler != null && !hasBlockState) resource = FluidHelper.copyStackWithAmount(resource, 1); int fill = super.fill(resource, action); if (action.simulate()) return fill; - if (!resource.isEmpty()) - applyEffects(resource); + + if (effectHandler != null && !resource.isEmpty()) { + // resource should be copied before giving it to the handler. + // if hasBlockState is false, it was already copied above. + FluidStack exposed = hasBlockState ? resource.copy() : resource; + effectHandler.apply(world, aoe, exposed); + } + if (getFluidAmount() == 1000 || !hasBlockState) if (provideFluidToSpace(containedFluidStack, false)) setFluid(FluidStack.EMPTY); @@ -336,133 +312,4 @@ public class OpenEndedPipe extends FlowSource { } } - - public interface IEffectHandler { - boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid); - - void applyEffects(OpenEndedPipe pipe, FluidStack fluid); - } - - public static class PotionEffectHandler implements IEffectHandler { - @Override - public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { - return fluid.getFluid() - .isSame(AllFluids.POTION.get()); - } - - @Override - public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { - if (pipe.cachedFluid == null || pipe.cachedEffects == null || !fluid.isFluidEqual(pipe.cachedFluid)) { - FluidStack copy = fluid.copy(); - copy.setAmount(250); - ItemStack bottle = PotionFluidHandler.fillBottle(new ItemStack(Items.GLASS_BOTTLE), fluid); - pipe.cachedEffects = PotionUtils.getMobEffects(bottle); - } - - if (pipe.cachedEffects.isEmpty()) - return; - - List entities = pipe.getWorld() - .getEntitiesOfClass(LivingEntity.class, pipe.getAOE(), LivingEntity::isAffectedByPotions); - for (LivingEntity entity : entities) { - for (MobEffectInstance effectInstance : pipe.cachedEffects) { - MobEffect effect = effectInstance.getEffect(); - if (effect.isInstantenous()) { - effect.applyInstantenousEffect(null, null, entity, effectInstance.getAmplifier(), 0.5D); - } else { - entity.addEffect(new MobEffectInstance(effectInstance)); - } - } - } - } - } - - public static class MilkEffectHandler implements IEffectHandler { - @Override - public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { - return FluidHelper.isTag(fluid, Tags.Fluids.MILK); - } - - @Override - public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { - Level world = pipe.getWorld(); - if (world.getGameTime() % 5 != 0) - return; - List entities = - world.getEntitiesOfClass(LivingEntity.class, pipe.getAOE(), LivingEntity::isAffectedByPotions); - ItemStack curativeItem = new ItemStack(Items.MILK_BUCKET); - for (LivingEntity entity : entities) - entity.curePotionEffects(curativeItem); - } - } - - public static class WaterEffectHandler implements IEffectHandler { - @Override - public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { - return FluidHelper.isTag(fluid, FluidTags.WATER); - } - - @Override - public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { - Level world = pipe.getWorld(); - if (world.getGameTime() % 5 != 0) - return; - List entities = world.getEntities((Entity) null, pipe.getAOE(), Entity::isOnFire); - for (Entity entity : entities) - entity.clearFire(); - BlockPos.betweenClosedStream(pipe.getAOE()) - .forEach(pos -> dowseFire(world, pos)); - } - - // Adapted from ThrownPotion - private static void dowseFire(Level level, BlockPos pos) { - BlockState state = level.getBlockState(pos); - if (state.is(BlockTags.FIRE)) { - level.removeBlock(pos, false); - } else if (AbstractCandleBlock.isLit(state)) { - AbstractCandleBlock.extinguish(null, state, level, pos); - } else if (CampfireBlock.isLitCampfire(state)) { - level.levelEvent(null, 1009, pos, 0); - CampfireBlock.dowse(null, level, pos, state); - level.setBlockAndUpdate(pos, state.setValue(CampfireBlock.LIT, false)); - } - } - } - - public static class LavaEffectHandler implements IEffectHandler { - @Override - public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { - return FluidHelper.isTag(fluid, FluidTags.LAVA); - } - - @Override - public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { - Level world = pipe.getWorld(); - if (world.getGameTime() % 5 != 0) - return; - List entities = world.getEntities((Entity) null, pipe.getAOE(), entity -> !entity.fireImmune()); - for (Entity entity : entities) - entity.setSecondsOnFire(3); - } - } - - public static class TeaEffectHandler implements IEffectHandler { - @Override - public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { - return fluid.getFluid().isSame(AllFluids.TEA.get()); - } - - @Override - public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { - Level world = pipe.getWorld(); - if (world.getGameTime() % 5 != 0) - return; - List entities = world - .getEntitiesOfClass(LivingEntity.class, pipe.getAOE(), LivingEntity::isAffectedByPotions); - for (LivingEntity entity : entities) { - entity.addEffect(new MobEffectInstance(MobEffects.DIG_SPEED, 21, 0, false, false, false)); - } - } - } - } diff --git a/src/main/java/com/simibubi/create/content/fluids/PipeAttachmentModel.java b/src/main/java/com/simibubi/create/content/fluids/PipeAttachmentModel.java index c030955dca..055e593322 100644 --- a/src/main/java/com/simibubi/create/content/fluids/PipeAttachmentModel.java +++ b/src/main/java/com/simibubi/create/content/fluids/PipeAttachmentModel.java @@ -13,10 +13,9 @@ import com.simibubi.create.content.fluids.FluidTransportBehaviour.AttachmentType import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.model.BakedModelWrapperWithData; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; @@ -25,6 +24,7 @@ import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.client.ChunkRenderTypeSet; import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.client.model.data.ModelData.Builder; @@ -33,14 +33,24 @@ import net.minecraftforge.client.model.data.ModelProperty; public class PipeAttachmentModel extends BakedModelWrapperWithData { private static final ModelProperty PIPE_PROPERTY = new ModelProperty<>(); + private boolean ao; - public PipeAttachmentModel(BakedModel template) { + public static PipeAttachmentModel withAO(BakedModel template) { + return new PipeAttachmentModel(template, true); + } + + public static PipeAttachmentModel withoutAO(BakedModel template) { + return new PipeAttachmentModel(template, false); + } + + public PipeAttachmentModel(BakedModel template, boolean ao) { super(template); + this.ao = ao; } @Override protected ModelData.Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, - ModelData blockEntityData) { + ModelData blockEntityData) { PipeModelData data = new PipeModelData(); FluidTransportBehaviour transport = BlockEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); BracketedBlockEntityBehaviour bracket = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); @@ -55,14 +65,26 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData { return builder.with(PIPE_PROPERTY, data); } - // TODO: Update once MinecraftForge#9163 is merged @Override public ChunkRenderTypeSet getRenderTypes(@NotNull BlockState state, @NotNull RandomSource rand, @NotNull ModelData data) { - ChunkRenderTypeSet set = super.getRenderTypes(state, rand, data); - if (set.isEmpty()) { - return ItemBlockRenderTypes.getRenderLayers(state); + List set = new ArrayList<>(); + + set.add(super.getRenderTypes(state, rand, data)); + set.add(AllPartialModels.FLUID_PIPE_CASING.get().getRenderTypes(state, rand, data)); + + if (data.has(PIPE_PROPERTY)) { + PipeModelData pipeData = data.get(PIPE_PROPERTY); + for (Direction d : Iterate.directions) { + AttachmentTypes type = pipeData.getAttachment(d); + for (ComponentPartials partial : type.partials) { + ChunkRenderTypeSet attachmentRenderTypeSet = AllPartialModels.PIPE_ATTACHMENTS.get(partial).get(d) + .get().getRenderTypes(state, rand, data); + set.add(attachmentRenderTypeSet); + } + } } - return set; + + return ChunkRenderTypeSet.union(set); } @Override @@ -76,8 +98,23 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData { return quads; } + @Override + public boolean useAmbientOcclusion(BlockState state, RenderType renderType) { + return ao; + } + + @Override + public boolean useAmbientOcclusion(BlockState state) { + return ao; + } + + @Override + public boolean useAmbientOcclusion() { + return ao; + } + private void addQuads(List quads, BlockState state, Direction side, RandomSource rand, ModelData data, - PipeModelData pipeData, RenderType renderType) { + PipeModelData pipeData, RenderType renderType) { BakedModel bracket = pipeData.getBracket(); if (bracket != null) quads.addAll(bracket.getQuads(state, side, rand, data, renderType)); diff --git a/src/main/java/com/simibubi/create/content/fluids/PipeConnection.java b/src/main/java/com/simibubi/create/content/fluids/PipeConnection.java index 309547aa08..c89023e3bf 100644 --- a/src/main/java/com/simibubi/create/content/fluids/PipeConnection.java +++ b/src/main/java/com/simibubi/create/content/fluids/PipeConnection.java @@ -5,12 +5,12 @@ import java.util.Random; import java.util.function.Predicate; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import net.createmod.catnip.math.BlockFace; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.animation.LerpedFloat; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -203,7 +203,7 @@ public class PipeConnection { float flowSpeed = 1 / 32f + Mth.clamp(pressure.get(flow.inbound) / 128f, 0, 1) * 31 / 32f; flow.progress.setValue(Math.min(flow.progress.getValue() + flowSpeed, 1)); - if (flow.progress.getValue() >= 1) + if (flow.progress.getValue() >= 1) flow.complete = true; } diff --git a/src/main/java/com/simibubi/create/content/fluids/VirtualFluid.java b/src/main/java/com/simibubi/create/content/fluids/VirtualFluid.java index af4c358f11..abb637d12e 100644 --- a/src/main/java/com/simibubi/create/content/fluids/VirtualFluid.java +++ b/src/main/java/com/simibubi/create/content/fluids/VirtualFluid.java @@ -1,13 +1,12 @@ package com.simibubi.create.content.fluids; -import com.simibubi.create.content.fluids.potion.PotionFluid; - import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; + import net.minecraftforge.fluids.ForgeFlowingFluid; public class VirtualFluid extends ForgeFlowingFluid { diff --git a/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlock.java b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlock.java index 5cd049aa30..e45de5ed8d 100644 --- a/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlock.java @@ -32,6 +32,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.common.capabilities.ForgeCapabilities; public class ItemDrainBlock extends Block implements IWrenchable, IBE { @@ -42,12 +43,12 @@ public class ItemDrainBlock extends Block implements IWrenchable, IBE { @@ -73,14 +74,13 @@ public class ItemDrainBlock extends Block implements IWrenchable, IBE getBlockEntityClass() { return HosePulleyBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.HOSE_PULLEY.get(); diff --git a/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyBlockEntity.java index d0cf6fffdf..671093d761 100644 --- a/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyBlockEntity.java @@ -10,8 +10,8 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.fluid.SmartFluidTank; import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.utility.ServerSpeedProvider; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -178,7 +178,7 @@ public class HosePulleyBlockEntity extends KineticBlockEntity { } public float getInterpolatedOffset(float pt) { - return offset.getValue(pt); + return Math.max(offset.getValue(pt), 3 / 16f); } @Override diff --git a/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyRenderer.java b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyRenderer.java index 2344690c5d..e0fe91c6a5 100644 --- a/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyRenderer.java @@ -1,11 +1,13 @@ package com.simibubi.create.content.fluids.hosePulley; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.contraptions.pulley.AbstractPulleyRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.core.Direction.Axis; @@ -30,18 +32,23 @@ public class HosePulleyRenderer extends AbstractPulleyRenderer type; private FluidStack fluid; - public FluidParticleData() {} + public FluidParticleData() { + } @SuppressWarnings("unchecked") public FluidParticleData(ParticleType type, FluidStack fluid) { @@ -49,7 +51,7 @@ public class FluidParticleData implements ParticleOptions, ICustomParticleData CODEC = RecordCodecBuilder.create(i -> i @@ -68,7 +70,7 @@ public class FluidParticleData implements ParticleOptions, ICustomParticleData new FluidParticleData(AllParticleTypes.FLUID_DRIP.get(), fs))); public static final ParticleOptions.Deserializer DESERIALIZER = - new ParticleOptions.Deserializer() { + new ParticleOptions.Deserializer<>() { // TODO Fluid particles on command public FluidParticleData fromCommand(ParticleType particleTypeIn, StringReader reader) diff --git a/src/main/java/com/simibubi/create/content/fluids/particle/FluidStackParticle.java b/src/main/java/com/simibubi/create/content/fluids/particle/FluidStackParticle.java index cd9de2d490..96aa117295 100644 --- a/src/main/java/com/simibubi/create/content/fluids/particle/FluidStackParticle.java +++ b/src/main/java/com/simibubi/create/content/fluids/particle/FluidStackParticle.java @@ -2,8 +2,8 @@ package com.simibubi.create.content.fluids.particle; import com.simibubi.create.AllParticleTypes; import com.simibubi.create.content.fluids.potion.PotionFluid; -import com.simibubi.create.foundation.utility.Color; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.ParticleRenderType; diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/AxisPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/AxisPipeBlock.java index c98ad13d01..62924f5f30 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/AxisPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/AxisPipeBlock.java @@ -11,8 +11,8 @@ import com.simibubi.create.content.fluids.FluidPropagator; import com.simibubi.create.content.fluids.FluidTransportBehaviour; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -76,7 +76,7 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWith super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); } - + @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean isMoving) { if (world.isClientSide) diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/EncasedPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/EncasedPipeBlock.java index acf2991bd7..8c577ad4b1 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/EncasedPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/EncasedPipeBlock.java @@ -12,18 +12,18 @@ import java.util.function.Supplier; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.decoration.encasing.EncasedBlock; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.fluids.FluidPropagator; import com.simibubi.create.content.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.protocol.game.DebugPackets; @@ -51,7 +51,7 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.ticks.TickPriority; public class EncasedPipeBlock extends Block - implements IWrenchable, ISpecialBlockItemRequirement, IBE, EncasedBlock, ITransformableBlock { + implements IWrenchable, SpecialBlockItemRequirement, IBE, EncasedBlock, TransformableBlock { public static final Map FACING_TO_PROPERTY_MAP = PipeBlock.PROPERTY_BY_DIRECTION; private final Supplier casing; @@ -178,17 +178,17 @@ public class EncasedPipeBlock extends Block EncasedPipeBlock.transferSixWayProperties(state, defaultBlockState())); FluidTransportBehaviour.loadFlows(level, pos); } - + @Override public BlockState rotate(BlockState pState, Rotation pRotation) { return FluidPipeBlockRotation.rotate(pState, pRotation); } - + @Override public BlockState mirror(BlockState pState, Mirror pMirror) { return FluidPipeBlockRotation.mirror(pState, pMirror); } - + @Override public BlockState transform(BlockState state, StructureTransform transform) { return FluidPipeBlockRotation.transform(state, transform); diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlock.java index 212b7176c6..d7997a42f4 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlock.java @@ -7,7 +7,7 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; import com.simibubi.create.content.decoration.encasing.EncasableBlock; @@ -18,8 +18,8 @@ import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -55,7 +55,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.ticks.TickPriority; public class FluidPipeBlock extends PipeBlock implements SimpleWaterloggedBlock, IWrenchableWithBracket, - IBE, EncasableBlock, ITransformableBlock { + IBE, EncasableBlock, TransformableBlock { private static final VoxelShape OCCLUSION_BOX = Block.box(4, 4, 4, 12, 12, 12); @@ -341,20 +341,20 @@ public class FluidPipeBlock extends PipeBlock implements SimpleWaterloggedBlock, public VoxelShape getOcclusionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { return OCCLUSION_BOX; } - + @Override public BlockState rotate(BlockState pState, Rotation pRotation) { return FluidPipeBlockRotation.rotate(pState, pRotation); } - + @Override public BlockState mirror(BlockState pState, Mirror pMirror) { return FluidPipeBlockRotation.mirror(pState, pMirror); } - + @Override public BlockState transform(BlockState state, StructureTransform transform) { return FluidPipeBlockRotation.transform(state, transform); } - + } diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockEntity.java index a7021c604b..31d65dcef4 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockEntity.java @@ -2,8 +2,7 @@ package com.simibubi.create.content.fluids.pipes; import java.util.List; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; import com.simibubi.create.content.fluids.FluidPropagator; @@ -14,10 +13,11 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -public class FluidPipeBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { +public class FluidPipeBlockEntity extends SmartBlockEntity implements TransformableBlockEntity { public FluidPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -31,7 +31,7 @@ public class FluidPipeBlockEntity extends SmartBlockEntity implements ITransform } @Override - public void transform(StructureTransform transform) { + public void transform(BlockEntity be, StructureTransform transform) { BracketedBlockEntityBehaviour bracketBehaviour = getBehaviour(BracketedBlockEntityBehaviour.TYPE); if (bracketBehaviour != null) { bracketBehaviour.transformBracket(transform); @@ -65,19 +65,25 @@ public class FluidPipeBlockEntity extends SmartBlockEntity implements ITransform if (state.getBlock() instanceof EncasedPipeBlock && attachment != AttachmentTypes.DRAIN) return AttachmentTypes.NONE; - if (attachment == AttachmentTypes.RIM && !FluidPipeBlock.isPipe(otherState) - && !AllBlocks.MECHANICAL_PUMP.has(otherState) && !AllBlocks.ENCASED_FLUID_PIPE.has(otherState)) { - FluidTransportBehaviour pipeBehaviour = - BlockEntityBehaviour.get(world, offsetPos, FluidTransportBehaviour.TYPE); - if (pipeBehaviour != null) - if (pipeBehaviour.canHaveFlowToward(otherState, direction.getOpposite())) - return AttachmentTypes.CONNECTION; + if (attachment == AttachmentTypes.RIM) { + if (!FluidPipeBlock.isPipe(otherState) && !(otherState.getBlock() instanceof EncasedPipeBlock) + && !(otherState.getBlock() instanceof GlassFluidPipeBlock)) { + FluidTransportBehaviour pipeBehaviour = + BlockEntityBehaviour.get(world, offsetPos, FluidTransportBehaviour.TYPE); + if (pipeBehaviour != null && pipeBehaviour.canHaveFlowToward(otherState, direction.getOpposite())) + return AttachmentTypes.DETAILED_CONNECTION; + } + + if (!FluidPipeBlock.shouldDrawRim(world, pos, state, direction)) + return FluidPropagator.getStraightPipeAxis(state) == direction.getAxis() + ? AttachmentTypes.CONNECTION + : AttachmentTypes.DETAILED_CONNECTION; } - if (attachment == AttachmentTypes.RIM && !FluidPipeBlock.shouldDrawRim(world, pos, state, direction)) - return AttachmentTypes.CONNECTION; - if (attachment == AttachmentTypes.NONE && state.getValue(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(direction))) - return AttachmentTypes.CONNECTION; + if (attachment == AttachmentTypes.NONE + && state.getValue(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(direction))) + return AttachmentTypes.DETAILED_CONNECTION; + return attachment; } diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockRotation.java b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockRotation.java index df559fbf27..0c044fa00d 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockRotation.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockRotation.java @@ -3,8 +3,8 @@ package com.simibubi.create.content.fluids.pipes; import java.util.Map; import com.simibubi.create.content.contraptions.StructureTransform; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.PipeBlock; diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/GlassFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/GlassFluidPipeBlock.java index 4752f03ae1..6bae8eff31 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/GlassFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/GlassFluidPipeBlock.java @@ -4,8 +4,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.block.IBE; @@ -30,7 +30,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class GlassFluidPipeBlock extends AxisPipeBlock implements IBE, SimpleWaterloggedBlock, ISpecialBlockItemRequirement { +public class GlassFluidPipeBlock extends AxisPipeBlock implements IBE, SimpleWaterloggedBlock, SpecialBlockItemRequirement { public static final BooleanProperty ALT = BooleanProperty.create("alt"); diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlock.java index 5b2a17b61a..12d56a771c 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlock.java @@ -7,9 +7,9 @@ import com.simibubi.create.content.fluids.FluidPropagator; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VoxelShaper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -143,7 +143,7 @@ public class SmartFluidPipeBlock extends FaceAttachedHorizontalDirectionalBlock : face == AttachFace.CEILING ? AllShapes.SMART_FLUID_PIPE_CEILING : AllShapes.SMART_FLUID_PIPE_WALL; return shape.get(state.getValue(FACING)); } - + @Override public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); @@ -159,14 +159,14 @@ public class SmartFluidPipeBlock extends FaceAttachedHorizontalDirectionalBlock public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { return false; } - + @Override public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos) { updateWater(pLevel, pState, pCurrentPos); return pState; } - + @Override public FluidState getFluidState(BlockState pState) { return fluidState(pState); diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlockEntity.java index 4824558da3..2bc10105f1 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlockEntity.java @@ -9,14 +9,15 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.AttachFace; @@ -68,7 +69,7 @@ public class SmartFluidPipeBlockEntity extends SmartBlockEntity { class SmartPipeFilterSlot extends ValueBoxTransform { @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); float y = face == AttachFace.CEILING ? 0.55f : face == AttachFace.WALL ? 11.4f : 15.45f; float z = face == AttachFace.CEILING ? 4.6f : face == AttachFace.WALL ? 0.55f : 4.625f; @@ -81,7 +82,7 @@ public class SmartFluidPipeBlockEntity extends SmartBlockEntity { } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); TransformStack.of(ms) .rotateYDegrees(angleY(state)) diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/StraightPipeBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/StraightPipeBlockEntity.java index de8a98ca84..2a4dc3d92d 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/StraightPipeBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/StraightPipeBlockEntity.java @@ -51,8 +51,12 @@ public class StraightPipeBlockEntity extends SmartBlockEntity { if (attachment == AttachmentTypes.RIM && state.getBlock() instanceof FluidValveBlock) return AttachmentTypes.NONE; - if (attachment == AttachmentTypes.RIM && FluidPipeBlock.isPipe(otherState)) + if (attachment == AttachmentTypes.RIM && !(state.getBlock() instanceof GlassFluidPipeBlock) + && otherState.getBlock() instanceof GlassFluidPipeBlock) return AttachmentTypes.PARTIAL_RIM; + + if (attachment == AttachmentTypes.RIM && FluidPipeBlock.isPipe(otherState)) + return AttachmentTypes.NONE; if (axis == otherAxis && axis != null) return AttachmentTypes.NONE; diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/TransparentStraightPipeRenderer.java b/src/main/java/com/simibubi/create/content/fluids/pipes/TransparentStraightPipeRenderer.java index 8659592cfa..3789ccd50f 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/TransparentStraightPipeRenderer.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/TransparentStraightPipeRenderer.java @@ -6,9 +6,9 @@ import com.simibubi.create.content.fluids.PipeConnection.Flow; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.animation.LerpedFloat; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlock.java index 1bd5f05389..37a5639dfc 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlock.java @@ -10,8 +10,8 @@ import com.simibubi.create.content.fluids.pipes.IAxisPipe; import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlockEntity.java index 33726a4dda..11d4027ee1 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlockEntity.java @@ -7,9 +7,9 @@ import com.simibubi.create.content.fluids.pipes.StraightPipeBlockEntity.Straight import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveRenderer.java b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveRenderer.java index 9cf7f99f19..5294b1a53a 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveRenderer.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveRenderer.java @@ -3,11 +3,11 @@ package com.simibubi.create.content.fluids.pipes.valve; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -30,7 +30,7 @@ public class FluidValveRenderer extends KineticBlockEntityRenderer list = PotionUtils.getAllEffects(fs.getOrCreateTag()); List> list1 = Lists.newArrayList(); if (list.isEmpty()) { - tooltip.add((Components.translatable("effect.none")).withStyle(ChatFormatting.GRAY)); + tooltip.add((Component.translatable("effect.none")).withStyle(ChatFormatting.GRAY)); } else { for (MobEffectInstance effectinstance : list) { - MutableComponent textcomponent = Components.translatable(effectinstance.getDescriptionId()); + MutableComponent textcomponent = Component.translatable(effectinstance.getDescriptionId()); MobEffect effect = effectinstance.getEffect(); Map map = effect.getAttributeModifiers(); if (!map.isEmpty()) { @@ -131,7 +132,7 @@ public class PotionFluidHandler { if (effectinstance.getAmplifier() > 0) { textcomponent.append(" ") - .append(Components.translatable("potion.potency." + effectinstance.getAmplifier()).getString()); + .append(Component.translatable("potion.potency." + effectinstance.getAmplifier()).getString()); } if (effectinstance.getDuration() > 20) { @@ -146,8 +147,8 @@ public class PotionFluidHandler { } if (!list1.isEmpty()) { - tooltip.add(Components.immutableEmpty()); - tooltip.add((Components.translatable("potion.whenDrank")).withStyle(ChatFormatting.DARK_PURPLE)); + tooltip.add(CommonComponents.EMPTY); + tooltip.add((Component.translatable("potion.whenDrank")).withStyle(ChatFormatting.DARK_PURPLE)); for (Tuple tuple : list1) { AttributeModifier attributemodifier2 = tuple.getB(); @@ -161,20 +162,16 @@ public class PotionFluidHandler { } if (d0 > 0.0D) { - tooltip.add((Components.translatable( - "attribute.modifier.plus." + attributemodifier2.getOperation() - .toValue(), - ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), - Components.translatable(tuple.getA()))) - .withStyle(ChatFormatting.BLUE)); + Object[] args = new Object[]{ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), Component.translatable(tuple.getA())}; + tooltip.add((Component.translatable("attribute.modifier.plus." + attributemodifier2.getOperation() + .toValue(), args)) + .withStyle(ChatFormatting.BLUE)); } else if (d0 < 0.0D) { d1 = d1 * -1.0D; - tooltip.add((Components.translatable( - "attribute.modifier.take." + attributemodifier2.getOperation() - .toValue(), - ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), - Components.translatable(tuple.getA()))) - .withStyle(ChatFormatting.RED)); + Object[] args = new Object[]{ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), Component.translatable(tuple.getA())}; + tooltip.add((Component.translatable("attribute.modifier.take." + attributemodifier2.getOperation() + .toValue(), args)) + .withStyle(ChatFormatting.RED)); } } } diff --git a/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlock.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlock.java index b21a288aba..aa42298841 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlock.java @@ -8,8 +8,8 @@ import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -18,7 +18,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; @@ -51,11 +50,6 @@ public class PumpBlock extends DirectionalKineticBlock .getOpposite()); } - @Override - public BlockState updateAfterWrenched(BlockState newState, UseOnContext context) { - return super.updateAfterWrenched(newState, context); - } - @Override public Axis getRotationAxis(BlockState state) { return state.getValue(FACING) @@ -64,13 +58,13 @@ public class PumpBlock extends DirectionalKineticBlock @Override public VoxelShape getShape(BlockState state, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { + CollisionContext p_220053_4_) { return AllShapes.PUMP.get(state.getValue(FACING)); } @Override public void neighborChanged(BlockState state, Level world, BlockPos pos, Block otherBlock, BlockPos neighborPos, - boolean isMoving) { + boolean isMoving) { DebugPackets.sendNeighborsUpdatePacket(world, pos); Direction d = FluidPropagator.validateNeighbourChange(state, world, pos, otherBlock, neighborPos, isMoving); if (d == null) @@ -94,7 +88,7 @@ public class PumpBlock extends DirectionalKineticBlock @Override public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, LevelAccessor world, - BlockPos pos, BlockPos neighbourPos) { + BlockPos pos, BlockPos neighbourPos) { if (state.getValue(BlockStateProperties.WATERLOGGED)) world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); return state; @@ -152,9 +146,8 @@ public class PumpBlock extends DirectionalKineticBlock if (isPump(state) && isPump(oldState) && state.getValue(FACING) == oldState.getValue(FACING) .getOpposite()) { BlockEntity blockEntity = world.getBlockEntity(pos); - if (!(blockEntity instanceof PumpBlockEntity)) + if (!(blockEntity instanceof PumpBlockEntity pump)) return; - PumpBlockEntity pump = (PumpBlockEntity) blockEntity; pump.pressureUpdate = true; } } diff --git a/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlockEntity.java index 58ab21c99a..a8b3f9a9f9 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlockEntity.java @@ -20,11 +20,11 @@ import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.BlockFace; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -33,6 +33,7 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -226,7 +227,7 @@ public class PumpBlockEntity extends KineticBlockEntity { } protected boolean searchForEndpointRecursively(Map>> pipeGraph, - Set targets, Map> validFaces, BlockFace currentFace, boolean pull) { + Set targets, Map> validFaces, BlockFace currentFace, boolean pull) { BlockPos currentPos = currentFace.getPos(); if (!pipeGraph.containsKey(currentPos)) return false; @@ -275,8 +276,7 @@ public class PumpBlockEntity extends KineticBlockEntity { // facing a pump if (PumpBlock.isPump(connectedState) && connectedState.getValue(PumpBlock.FACING) - .getAxis() == face.getAxis() && blockEntity instanceof PumpBlockEntity) { - PumpBlockEntity pumpBE = (PumpBlockEntity) blockEntity; + .getAxis() == face.getAxis() && blockEntity instanceof PumpBlockEntity pumpBE) { return pumpBE.isPullingOnSide(pumpBE.isFront(blockFace.getOppositeFace())) != pull; } @@ -362,7 +362,7 @@ public class PumpBlockEntity extends KineticBlockEntity { @Override public AttachmentTypes getRenderedRimAttachment(BlockAndTintGetter world, BlockPos pos, BlockState state, - Direction direction) { + Direction direction) { AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); if (attachment == AttachmentTypes.RIM) return AttachmentTypes.NONE; diff --git a/src/main/java/com/simibubi/create/content/fluids/pump/PumpCogVisual.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpCogVisual.java deleted file mode 100644 index c94099d615..0000000000 --- a/src/main/java/com/simibubi/create/content/fluids/pump/PumpCogVisual.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.simibubi.create.content.fluids.pump; - -import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; - -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.model.Models; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class PumpCogVisual extends SingleRotatingVisual { - - public PumpCogVisual(VisualizationContext context, PumpBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Model model() { - BlockState referenceState = blockEntity.getBlockState(); - Direction facing = referenceState.getValue(BlockStateProperties.FACING); - return Models.partial(AllPartialModels.MECHANICAL_PUMP_COG, facing); - } -} diff --git a/src/main/java/com/simibubi/create/content/fluids/pump/PumpRenderer.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpRenderer.java index 294e3c6e55..b475a80b7d 100644 --- a/src/main/java/com/simibubi/create/content/fluids/pump/PumpRenderer.java +++ b/src/main/java/com/simibubi/create/content/fluids/pump/PumpRenderer.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.fluids.pump; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.world.level.block.state.BlockState; @@ -16,7 +16,7 @@ public class PumpRenderer extends KineticBlockEntityRenderer { @Override protected SuperByteBuffer getRotatedModel(PumpBlockEntity be, BlockState state) { - return CachedBufferer.partialFacing(AllPartialModels.MECHANICAL_PUMP_COG, state); + return CachedBuffers.partialFacing(AllPartialModels.MECHANICAL_PUMP_COG, state); } } diff --git a/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlockEntity.java index 7ac5e382b6..360795427f 100644 --- a/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlockEntity.java @@ -8,8 +8,8 @@ import java.util.List; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.api.behaviour.spouting.BlockSpoutingBehaviour; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.fluids.FluidFX; import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour; import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult; @@ -22,9 +22,9 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleOptions; @@ -35,6 +35,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; @@ -76,7 +77,7 @@ public class SpoutBlockEntity extends SmartBlockEntity implements IHaveGoggleInf } protected ProcessingResult onItemReceived(TransportedItemStack transported, - TransportedItemStackHandlerBehaviour handler) { + TransportedItemStackHandlerBehaviour handler) { if (handler.blockEntity.isVirtual()) return PASS; if (!FillingBySpout.canItemBeFilled(level, transported.stack)) @@ -89,7 +90,7 @@ public class SpoutBlockEntity extends SmartBlockEntity implements IHaveGoggleInf } protected ProcessingResult whenItemHeld(TransportedItemStack transported, - TransportedItemStackHandlerBehaviour handler) { + TransportedItemStackHandlerBehaviour handler) { if (processingTicks != -1 && processingTicks != 5) return HOLD; if (!FillingBySpout.canItemBeFilled(level, transported.stack)) @@ -106,13 +107,14 @@ public class SpoutBlockEntity extends SmartBlockEntity implements IHaveGoggleInf if (processingTicks == -1) { processingTicks = FILLING_TIME; notifyUpdate(); - AllSoundEvents.SPOUTING.playOnServer(level, worldPosition, 0.75f, 0.9f + 0.2f * (float)Math.random()); + AllSoundEvents.SPOUTING.playOnServer(level, worldPosition, 0.75f, 0.9f + 0.2f * (float) Math.random()); return HOLD; } // Process finished ItemStack out = FillingBySpout.fillItem(level, requiredAmountForItem, transported.stack, fluid); if (!out.isEmpty()) { + transported.clearFanProcessingData(); List outList = new ArrayList<>(); TransportedItemStack held = null; TransportedItemStack result = transported.copy(); @@ -197,21 +199,19 @@ public class SpoutBlockEntity extends SmartBlockEntity implements IHaveGoggleInf FluidStack currentFluidInTank = getCurrentFluidInTank(); if (processingTicks == -1 && (isVirtual() || !level.isClientSide()) && !currentFluidInTank.isEmpty()) { - BlockSpoutingBehaviour.forEach(behaviour -> { - if (customProcess != null) - return; - if (behaviour.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, true) > 0) { - processingTicks = FILLING_TIME; - customProcess = behaviour; - notifyUpdate(); - } - }); + BlockPos filling = this.worldPosition.below(2); + BlockSpoutingBehaviour behavior = BlockSpoutingBehaviour.get(this.level, filling); + if (behavior != null && behavior.fillBlock(this.level, filling, this, currentFluidInTank.copy(), true) > 0) { + processingTicks = FILLING_TIME; + customProcess = behavior; + notifyUpdate(); + } } if (processingTicks >= 0) { processingTicks--; if (processingTicks == 5 && customProcess != null) { - int fillBlock = customProcess.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, false); + int fillBlock = customProcess.fillBlock(level, worldPosition.below(2), this, currentFluidInTank.copy(), false); customProcess = null; if (fillBlock > 0) { tank.getPrimaryHandler() @@ -225,7 +225,7 @@ public class SpoutBlockEntity extends SmartBlockEntity implements IHaveGoggleInf if (processingTicks >= 8 && level.isClientSide) { spawnProcessingParticles(tank.getPrimaryTank() - .getRenderedFluid()); + .getRenderedFluid()); } } diff --git a/src/main/java/com/simibubi/create/content/fluids/spout/SpoutRenderer.java b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutRenderer.java index 5d53155445..fa7af0fc36 100644 --- a/src/main/java/com/simibubi/create/content/fluids/spout/SpoutRenderer.java +++ b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutRenderer.java @@ -6,9 +6,9 @@ import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTank import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -51,10 +51,10 @@ public class SpoutRenderer extends SafeBlockEntityRenderer { if (!top) ms.translate(0, yOffset, 0); else ms.translate(0, max - min, 0); - FluidRenderer.renderFluidBox(fluidStack, + FluidRenderer.renderFluidBox(fluidStack.getFluid(), fluidStack.getAmount(), min, min - yOffset, min, max, min, max, - buffer, ms, light, false); + buffer, ms, light, false, true, fluidStack.getTag()); ms.popPose(); } @@ -68,8 +68,8 @@ public class SpoutRenderer extends SafeBlockEntityRenderer { if (!fluidStack.isEmpty() && processingTicks != -1) { radius = (float) (Math.pow(((2 * processingProgress) - 1), 2) - 1); AABB bb = new AABB(0.5, 0.0, 0.5, 0.5, -1.2, 0.5).inflate(radius / 32f); - FluidRenderer.renderFluidBox(fluidStack, (float) bb.minX, (float) bb.minY, (float) bb.minZ, - (float) bb.maxX, (float) bb.maxY, (float) bb.maxZ, buffer, ms, light, true); + FluidRenderer.renderFluidBox(fluidStack.getFluid(), fluidStack.getAmount(), (float) bb.minX, (float) bb.minY, (float) bb.minZ, + (float) bb.maxX, (float) bb.maxY, (float) bb.maxZ, buffer, ms, light, true, true, fluidStack.getTag()); } float squeeze = radius; @@ -82,7 +82,7 @@ public class SpoutRenderer extends SafeBlockEntityRenderer { ms.pushPose(); for (PartialModel bit : BITS) { - CachedBufferer.partial(bit, be.getBlockState()) + CachedBuffers.partial(bit, be.getBlockState()) .light(light) .renderInto(ms, buffer.getBuffer(RenderType.solid())); ms.translate(0, -3 * squeeze / 32f, 0); diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/BoilerData.java b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerData.java index c6b2753db4..6dfd085c10 100644 --- a/src/main/java/com/simibubi/create/content/fluids/tank/BoilerData.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerData.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.fluids.tank; import java.util.Arrays; +import java.util.EnumMap; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -8,30 +9,35 @@ import java.util.Set; import org.jetbrains.annotations.NotNull; import com.simibubi.create.AllBlocks; -import com.simibubi.create.Create; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.boiler.BoilerHeater; +import com.simibubi.create.api.stress.BlockStressValues; import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock; import com.simibubi.create.content.decoration.steamWhistle.WhistleBlockEntity; -import com.simibubi.create.content.kinetics.BlockStressValues; import com.simibubi.create.content.kinetics.steamEngine.SteamEngineBlock; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; import joptsimple.internal.Strings; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Iterate; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -62,17 +68,34 @@ public class BoilerData { private int maxHeatForWater = 0; private int minValue = 0; private int maxValue = 0; + public boolean[] occludedDirections = {true, true, true, true}; public LerpedFloat gauge = LerpedFloat.linear(); + // client only sound control + + // re-use the same lambda for each side + private final SoundPool.Sound sound = (level, pos) -> { + float volume = 3f / Math.max(2, attachedEngines / 6); + float pitch = 1.18f - level.random.nextFloat() * .25f; + level.playLocalSound(pos.getX(), pos.getY(), pos.getZ(), + SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, volume, pitch, false); + + AllSoundEvents.STEAM.playAt(level, pos, volume / 16, .8f, false); + }; + // separate pools for each side so they sound distinct when standing at corners of the boiler + private final EnumMap pools = new EnumMap<>(Direction.class); + public void tick(FluidTankBlockEntity controller) { if (!isActive()) return; - if (controller.getLevel().isClientSide) { + Level level = controller.getLevel(); + if (level.isClientSide) { + pools.values().forEach(p -> p.play(level)); gauge.tickChaser(); float current = gauge.getValue(1); - if (current > 1 && Create.RANDOM.nextFloat() < 1 / 2f) - gauge.setValueNoUpdate(current + Math.min(-(current - 1) * Create.RANDOM.nextFloat(), 0)); + if (current > 1 && level.random.nextFloat() < 1 / 2f) + gauge.setValueNoUpdate(current + Math.min(-(current - 1) * level.random.nextFloat(), 0)); return; } if (needsHeatLevelUpdate && updateTemperature(controller)) @@ -105,6 +128,32 @@ public class BoilerData { controller.notifyUpdate(); } + public void updateOcclusion(FluidTankBlockEntity controller) { + if (!controller.getLevel().isClientSide) + return; + if (attachedEngines + attachedWhistles == 0) + return; + for (Direction d : Iterate.horizontalDirections) { + AABB aabb = + new AABB(controller.getBlockPos()).move(controller.width / 2f - .5f, 0, controller.width / 2f - .5f) + .deflate(5f / 8); + aabb = aabb.move(d.getStepX() * (controller.width / 2f + 1 / 4f), 0, + d.getStepZ() * (controller.width / 2f + 1 / 4f)); + aabb = aabb.inflate(Math.abs(d.getStepZ()) / 2f, 0.25f, Math.abs(d.getStepX()) / 2f); + occludedDirections[d.get2DDataValue()] = !controller.getLevel() + .noCollision(aabb); + } + } + + public void queueSoundOnSide(BlockPos pos, Direction side) { + SoundPool pool = pools.get(side); + if (pool == null) { + pool = new SoundPool(4, 2, sound); + pools.put(side, pool); + } + pool.queueAt(pos); + } + public int getTheoreticalHeatLevel() { return activeHeat; } @@ -148,11 +197,11 @@ public class BoilerData { calcMinMaxForSize(boilerSize); - Lang.translate("boiler.status", getHeatLevelTextComponent().withStyle(ChatFormatting.GREEN)) - .forGoggles(tooltip); - Lang.builder().add(getSizeComponent(true, false)).forGoggles(tooltip, 1); - Lang.builder().add(getWaterComponent(true, false)).forGoggles(tooltip, 1); - Lang.builder().add(getHeatComponent(true, false)).forGoggles(tooltip, 1); + CreateLang.translate("boiler.status", getHeatLevelTextComponent().withStyle(ChatFormatting.GREEN)) + .forGoggles(tooltip); + CreateLang.builder().add(getSizeComponent(true, false)).forGoggles(tooltip, 1); + CreateLang.builder().add(getWaterComponent(true, false)).forGoggles(tooltip, 1); + CreateLang.builder().add(getHeatComponent(true, false)).forGoggles(tooltip, 1); if (attachedEngines == 0) return true; @@ -161,34 +210,34 @@ public class BoilerData { double totalSU = getEngineEfficiency(boilerSize) * 16 * Math.max(boilerLevel, attachedEngines) * BlockStressValues.getCapacity(AllBlocks.STEAM_ENGINE.get()); - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); if (attachedEngines > 0 && maxHeatForSize > 0 && maxHeatForWater == 0 && (passiveHeat ? 1 : activeHeat) > 0) { - Lang.translate("boiler.water_input_rate") + CreateLang.translate("boiler.water_input_rate") .style(ChatFormatting.GRAY) .forGoggles(tooltip); - Lang.number(waterSupply) + CreateLang.number(waterSupply) .style(ChatFormatting.BLUE) - .add(Lang.translate("generic.unit.millibuckets")) - .add(Lang.text(" / ") + .add(CreateLang.translate("generic.unit.millibuckets")) + .add(CreateLang.text(" / ") .style(ChatFormatting.GRAY)) - .add(Lang.translate("boiler.per_tick", Lang.number(waterSupplyPerLevel) - .add(Lang.translate("generic.unit.millibuckets"))) + .add(CreateLang.translate("boiler.per_tick", CreateLang.number(waterSupplyPerLevel) + .add(CreateLang.translate("generic.unit.millibuckets"))) .style(ChatFormatting.DARK_GRAY)) .forGoggles(tooltip, 1); return true; } - Lang.translate("tooltip.capacityProvided") + CreateLang.translate("tooltip.capacityProvided") .style(ChatFormatting.GRAY) .forGoggles(tooltip); - Lang.number(totalSU) + CreateLang.number(totalSU) .translate("generic.unit.stress") .style(ChatFormatting.AQUA) .space() - .add((attachedEngines == 1 ? Lang.translate("boiler.via_one_engine") - : Lang.translate("boiler.via_engines", attachedEngines)).style(ChatFormatting.DARK_GRAY)) + .add((attachedEngines == 1 ? CreateLang.translate("boiler.via_one_engine") + : CreateLang.translate("boiler.via_engines", attachedEngines)).style(ChatFormatting.DARK_GRAY)) .forGoggles(tooltip, 1); return true; @@ -206,10 +255,10 @@ public class BoilerData { public MutableComponent getHeatLevelTextComponent() { int boilerLevel = Math.min(activeHeat, Math.min(maxHeatForWater, maxHeatForSize)); - return isPassive() ? Lang.translateDirect("boiler.passive") - : (boilerLevel == 0 ? Lang.translateDirect("boiler.idle") - : boilerLevel == 18 ? Lang.translateDirect("boiler.max_lvl") - : Lang.translateDirect("boiler.lvl", String.valueOf(boilerLevel))); + return isPassive() ? CreateLang.translateDirect("boiler.passive") + : (boilerLevel == 0 ? CreateLang.translateDirect("boiler.idle") + : boilerLevel == 18 ? CreateLang.translateDirect("boiler.max_lvl") + : CreateLang.translateDirect("boiler.lvl", String.valueOf(boilerLevel))); } public MutableComponent getSizeComponent(boolean forGoggles, boolean useBlocksAsBars, ChatFormatting... styles) { @@ -225,7 +274,7 @@ public class BoilerData { } private MutableComponent componentHelper(String label, int level, boolean forGoggles, boolean useBlocksAsBars, - ChatFormatting... styles) { + ChatFormatting... styles) { MutableComponent base = useBlocksAsBars ? blockComponent(level) : barComponent(level); if (!forGoggles) @@ -234,20 +283,19 @@ public class BoilerData { ChatFormatting style1 = styles.length >= 1 ? styles[0] : ChatFormatting.GRAY; ChatFormatting style2 = styles.length >= 2 ? styles[1] : ChatFormatting.DARK_GRAY; - return Lang.translateDirect("boiler." + label) + return CreateLang.translateDirect("boiler." + label) .withStyle(style1) - .append(Lang.translateDirect("boiler." + label + "_dots") + .append(CreateLang.translateDirect("boiler." + label + "_dots") .withStyle(style2)) .append(base); } private MutableComponent blockComponent(int level) { - return Components.literal( - "" + "\u2588".repeat(minValue) + "\u2592".repeat(level - minValue) + "\u2591".repeat(maxValue - level)); + return Component.literal("" + "\u2588".repeat(minValue) + "\u2592".repeat(level - minValue) + "\u2591".repeat(maxValue - level)); } private MutableComponent barComponent(int level) { - return Components.empty() + return Component.empty() .append(bars(Math.max(0, minValue - 1), ChatFormatting.DARK_GREEN)) .append(bars(minValue > 0 ? 1 : 0, ChatFormatting.GREEN)) .append(bars(Math.max(0, level - minValue), ChatFormatting.DARK_GREEN)) @@ -258,7 +306,7 @@ public class BoilerData { } private MutableComponent bars(int level, ChatFormatting format) { - return Components.literal(Strings.repeat('|', level)) + return Component.literal(Strings.repeat('|', level)) .withStyle(format); } @@ -285,7 +333,7 @@ public class BoilerData { attachedEngines++; if (AllBlocks.STEAM_WHISTLE.has(attachedState) && WhistleBlock.getAttachedDirection(attachedState) - .getOpposite() == d) + .getOpposite() == d) attachedWhistles++; } } @@ -318,7 +366,7 @@ public class BoilerData { BlockState attachedState = level.getBlockState(attachedPos); if (AllBlocks.STEAM_WHISTLE.has(attachedState) && WhistleBlock.getAttachedDirection(attachedState) - .getOpposite() == d) { + .getOpposite() == d) { if (level.getBlockEntity(attachedPos) instanceof WhistleBlockEntity wbe) whistlePitches.add(wbe.getPitchId()); } @@ -345,7 +393,7 @@ public class BoilerData { for (int zOffset = 0; zOffset < controller.width; zOffset++) { BlockPos pos = controllerPos.offset(xOffset, -1, zOffset); BlockState blockState = level.getBlockState(pos); - float heat = BoilerHeaters.getActiveHeat(level, pos, blockState); + float heat = BoilerHeater.findHeat(level, pos, blockState); if (heat == 0) { passiveHeat = true; } else if (heat > 0) { diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java index daec9ccaa9..7f6cc94245 100644 --- a/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java @@ -1,95 +1,38 @@ package com.simibubi.create.content.fluids.tank; -import java.util.ArrayList; -import java.util.List; - -import org.jetbrains.annotations.Nullable; - import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.api.boiler.BoilerHeater; +import com.simibubi.create.api.registry.SimpleRegistry; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.utility.AttachedRegistry; import com.simibubi.create.foundation.utility.BlockHelper; import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; public class BoilerHeaters { - private static final AttachedRegistry BLOCK_HEATERS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final List GLOBAL_HEATERS = new ArrayList<>(); - - public static void registerHeater(ResourceLocation block, Heater heater) { - BLOCK_HEATERS.register(block, heater); - } - - public static void registerHeater(Block block, Heater heater) { - BLOCK_HEATERS.register(block, heater); - } - - public static void registerHeaterProvider(HeaterProvider provider) { - GLOBAL_HEATERS.add(provider); - } - - /** - * A return value of {@code -1} represents no heat. - * A return value of {@code 0} represents passive heat. - * All other positive values are used as the amount of active heat. - */ - public static float getActiveHeat(Level level, BlockPos pos, BlockState state) { - Heater heater = BLOCK_HEATERS.get(state.getBlock()); - if (heater != null) { - return heater.getActiveHeat(level, pos, state); - } - - for (HeaterProvider provider : GLOBAL_HEATERS) { - heater = provider.getHeater(level, pos, state); - if (heater != null) { - return heater.getActiveHeat(level, pos, state); - } - } - - return -1; - } - public static void registerDefaults() { - registerHeater(AllBlocks.BLAZE_BURNER.get(), (level, pos, state) -> { - HeatLevel value = state.getValue(BlazeBurnerBlock.HEAT_LEVEL); - if (value == HeatLevel.NONE) { - return -1; - } - if (value == HeatLevel.SEETHING) { - return 2; - } - if (value.isAtLeast(HeatLevel.FADING)) { - return 1; - } - return 0; - }); - - registerHeaterProvider((level, pos, state) -> { - if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) && BlockHelper.isNotUnheated(state)) { - return (level1, pos1, state1) -> 0; - } - return null; - }); + BoilerHeater.REGISTRY.register(AllBlocks.BLAZE_BURNER.get(), BoilerHeater.BLAZE_BURNER); + BoilerHeater.REGISTRY.registerProvider(SimpleRegistry.Provider.forBlockTag(AllBlockTags.PASSIVE_BOILER_HEATERS.tag, BoilerHeater.PASSIVE)); } - public interface Heater { - /** - * A return value of {@code -1} represents no heat. - * A return value of {@code 0} represents passive heat. - * All other positive values are used as the amount of active heat. - */ - float getActiveHeat(Level level, BlockPos pos, BlockState state); + public static int passive(Level level, BlockPos pos, BlockState state) { + return BlockHelper.isNotUnheated(state) ? BoilerHeater.PASSIVE_HEAT : BoilerHeater.NO_HEAT; } - public interface HeaterProvider { - @Nullable - Heater getHeater(Level level, BlockPos pos, BlockState state); + public static int blazeBurner(Level level, BlockPos pos, BlockState state) { + HeatLevel value = state.getValue(BlazeBurnerBlock.HEAT_LEVEL); + if (value == HeatLevel.NONE) { + return BoilerHeater.NO_HEAT; + } + if (value == HeatLevel.SEETHING) { + return 2; + } + if (value.isAtLeast(HeatLevel.FADING)) { + return 1; + } + return BoilerHeater.PASSIVE_HEAT; } } diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java index e0c5a55dc4..3371ba1da2 100644 --- a/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java @@ -3,13 +3,17 @@ package com.simibubi.create.content.fluids.tank; import java.util.List; import java.util.function.Consumer; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.foundation.fluid.SmartFluidTank; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; +import net.minecraft.util.ExtraCodecs; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; public class CreativeFluidTankBlockEntity extends FluidTankBlockEntity { @@ -21,26 +25,34 @@ public class CreativeFluidTankBlockEntity extends FluidTankBlockEntity { protected SmartFluidTank createInventory() { return new CreativeSmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged); } - + @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { return false; } public static class CreativeSmartFluidTank extends SmartFluidTank { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + FluidStack.CODEC.fieldOf("fluid").forGetter(FluidTank::getFluid), + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("capacity").forGetter(FluidTank::getCapacity) + ).apply(i, (fluid, capacity) -> { + CreativeSmartFluidTank tank = new CreativeSmartFluidTank(capacity, $ -> {}); + tank.setFluid(fluid); + return tank; + })); public CreativeSmartFluidTank(int capacity, Consumer updateCallback) { super(capacity, updateCallback); } - + @Override public int getFluidAmount() { return getFluid().isEmpty() ? 0 : getTankCapacity(0); } - + public void setContainedFluid(FluidStack fluidStack) { fluid = fluidStack.copy(); - if (!fluidStack.isEmpty()) + if (!fluidStack.isEmpty()) fluid.setAmount(getTankCapacity(0)); onContentsChanged(); } diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlock.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlock.java index 50a7f7ebfb..5c3e237520 100644 --- a/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlock.java @@ -11,8 +11,8 @@ import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.blockEntity.ComparatorUtil; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.FluidHelper.FluidExchange; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.BlockParticleOption; @@ -49,6 +49,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.ForgeSoundType; import net.minecraftforge.common.util.LazyOptional; @@ -124,7 +125,7 @@ public class FluidTankBlock extends Block implements IWrenchable, IBEWith two people walking, you can still pick out which footsteps belong to which person. + * + *
Try and listen to three people walking in a group, however, and you'll find that you can't distinguish + * individual footsteps anymore. You now just hear the sound of a group of people walking. + * + *

You'll likely find that you perceive any number of people walking in a group as a single distinguishable sound. + * This class is a helper to take advantage of that for sound effects in Create to avoid saturating the sound engine + * without a perceptible loss in quality. + * + *

NOTE: It's up to the user of this class to decide how to group sounds such that they are perceived as a single + * sound. There are no spatial calculations made here. + */ +public class SoundPool { + /** + * The maximum number of sounds that can be played at once. + */ + private final int maxConcurrent; + /** + * The number of ticks to wait before playing sounds. Useful if sounds are queued across many block entities, + * and you don't have control over the tick order. + */ + private final int mergeTicks; + + private final Sound sound; + + private final LongList queuedPositions = new LongArrayList(); + + private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); + + private int ticks = 0; + + public SoundPool(int maxConcurrent, int mergeTicks, Sound sound) { + this.maxConcurrent = maxConcurrent; + this.sound = sound; + this.mergeTicks = mergeTicks; + } + + public void queueAt(BlockPos pos) { + queueAt(pos.asLong()); + } + + public void queueAt(long pos) { + queuedPositions.add(pos); + } + + public void play(Level level) { + if (queuedPositions.isEmpty()) { + return; + } + + ticks++; + + if (ticks < mergeTicks) { + // Wait for more sounds to be queued in further ticks. + return; + } + + ticks = 0; + + var numberOfPositions = queuedPositions.size(); + + if (numberOfPositions <= maxConcurrent) { + // Fewer sound positions than maxConcurrent, play them all. + for (long pos : queuedPositions) { + playAt(level, pos); + } + } else { + // Roll for n random positions and play there. + while (!queuedPositions.isEmpty() && queuedPositions.size() > numberOfPositions - maxConcurrent) { + rollNextPosition(level); + } + } + + queuedPositions.clear(); + } + + private void rollNextPosition(Level level) { + int index = level.random.nextInt(queuedPositions.size()); + long pos = queuedPositions.removeLong(index); + playAt(level, pos); + } + + private void playAt(Level level, long pos) { + sound.playAt(level, this.pos.set(pos)); + } + + public interface Sound { + void playAt(Level level, Vec3i pos); + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorage.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorage.java new file mode 100644 index 0000000000..a686bfb59d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorage.java @@ -0,0 +1,110 @@ +package com.simibubi.create.content.fluids.tank.storage; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.fluid.WrapperMountedFluidStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.fluids.tank.storage.FluidTankMountedStorage.Handler; + +import net.createmod.catnip.animation.LerpedFloat; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; + +public class FluidTankMountedStorage extends WrapperMountedFluidStorage implements SyncedMountedStorage { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("capacity").forGetter(FluidTankMountedStorage::getCapacity), + FluidStack.CODEC.fieldOf("fluid").forGetter(FluidTankMountedStorage::getFluid) + ).apply(i, FluidTankMountedStorage::new)); + + private boolean dirty; + + protected FluidTankMountedStorage(MountedFluidStorageType type, int capacity, FluidStack stack) { + super(type, new Handler(capacity, stack)); + this.wrapped.onChange = () -> this.dirty = true; + } + + protected FluidTankMountedStorage(int capacity, FluidStack stack) { + this(AllMountedStorageTypes.FLUID_TANK.get(), capacity, stack); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof FluidTankBlockEntity tank && tank.isController()) { + FluidTank inventory = tank.getTankInventory(); + // capacity shouldn't change, leave it + inventory.setFluid(this.wrapped.getFluid()); + } + } + + public FluidStack getFluid() { + return this.wrapped.getFluid(); + } + + public int getCapacity() { + return this.wrapped.getCapacity(); + } + + @Override + public boolean isDirty() { + return this.dirty; + } + + @Override + public void markClean() { + this.dirty = false; + } + + @Override + public void afterSync(Contraption contraption, BlockPos localPos) { + BlockEntity be = contraption.presentBlockEntities.get(localPos); + if (!(be instanceof FluidTankBlockEntity tank)) + return; + + FluidTank inv = tank.getTankInventory(); + inv.setFluid(this.getFluid()); + float fillLevel = inv.getFluidAmount() / (float) inv.getCapacity(); + if (tank.getFluidLevel() == null) { + tank.setFluidLevel(LerpedFloat.linear().startWithValue(fillLevel)); + } + tank.getFluidLevel().chase(fillLevel, 0.5, LerpedFloat.Chaser.EXP); + } + + public static FluidTankMountedStorage fromTank(FluidTankBlockEntity tank) { + // tank has update callbacks, make an isolated copy + FluidTank inventory = tank.getTankInventory(); + return new FluidTankMountedStorage(inventory.getCapacity(), inventory.getFluid().copy()); + } + + public static FluidTankMountedStorage fromLegacy(CompoundTag nbt) { + int capacity = nbt.getInt("Capacity"); + FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt); + return new FluidTankMountedStorage(capacity, fluid); + } + + public static final class Handler extends FluidTank { + private Runnable onChange = () -> {}; + + public Handler(int capacity, FluidStack stack) { + super(capacity); + this.setFluid(stack); + } + + @Override + protected void onContentsChanged() { + this.onChange.run(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorageType.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorageType.java new file mode 100644 index 0000000000..3ed06d3400 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.fluids.tank.storage; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class FluidTankMountedStorageType extends MountedFluidStorageType { + public FluidTankMountedStorageType() { + super(FluidTankMountedStorage.CODEC); + } + + @Override + @Nullable + public FluidTankMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof FluidTankBlockEntity tank && tank.isController()) { + return FluidTankMountedStorage.fromTank(tank); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorage.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorage.java new file mode 100644 index 0000000000..0d8f1cbc32 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorage.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.fluids.tank.storage.creative; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.fluid.WrapperMountedFluidStorage; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity.CreativeSmartFluidTank; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; + +public class CreativeFluidTankMountedStorage extends WrapperMountedFluidStorage { + public static final Codec CODEC = CreativeSmartFluidTank.CODEC.xmap( + CreativeFluidTankMountedStorage::new, storage -> storage.wrapped + ); + + protected CreativeFluidTankMountedStorage(MountedFluidStorageType type, CreativeSmartFluidTank tank) { + super(type, tank); + } + + protected CreativeFluidTankMountedStorage(CreativeSmartFluidTank tank) { + this(AllMountedStorageTypes.CREATIVE_FLUID_TANK.get(), tank); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + // no need to do anything, supplied stack can't change while mounted + } + + public static CreativeFluidTankMountedStorage fromTank(CreativeFluidTankBlockEntity tank) { + // make an isolated copy + FluidTank inv = tank.getTankInventory(); + CreativeSmartFluidTank copy = new CreativeSmartFluidTank(inv.getCapacity(), $ -> {}); + copy.setContainedFluid(inv.getFluid()); + return new CreativeFluidTankMountedStorage(copy); + } + + public static CreativeFluidTankMountedStorage fromLegacy(CompoundTag nbt) { + int capacity = nbt.getInt("Capacity"); + FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt.getCompound("ProvidedStack")); + CreativeSmartFluidTank tank = new CreativeSmartFluidTank(capacity, $ -> {}); + tank.setContainedFluid(fluid); + return new CreativeFluidTankMountedStorage(tank); + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorageType.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorageType.java new file mode 100644 index 0000000000..0dfe49612a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.fluids.tank.storage.creative; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class CreativeFluidTankMountedStorageType extends MountedFluidStorageType { + public CreativeFluidTankMountedStorageType() { + super(CreativeFluidTankMountedStorage.CODEC); + } + + @Override + @Nullable + public CreativeFluidTankMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof CreativeFluidTankBlockEntity tank) { + return CreativeFluidTankMountedStorage.fromTank(tank); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/transfer/FillingRecipe.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FillingRecipe.java index 54d8b36952..80d7e60b78 100644 --- a/src/main/java/com/simibubi/create/content/fluids/transfer/FillingRecipe.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FillingRecipe.java @@ -11,8 +11,7 @@ import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.Component; import net.minecraft.world.item.crafting.Ingredient; @@ -58,7 +57,7 @@ public class FillingRecipe extends ProcessingRecipe implements IA @Override public void addAssemblyIngredients(List list) {} - + @Override public void addAssemblyFluidIngredients(List list) { list.add(getRequiredFluid()); @@ -69,9 +68,10 @@ public class FillingRecipe extends ProcessingRecipe implements IA public Component getDescriptionForAssembly() { List matchingFluidStacks = fluidIngredients.get(0) .getMatchingFluidStacks(); - if (matchingFluidStacks.size() == 0) - return Components.literal("Invalid"); - return Lang.translateDirect("recipe.assembly.spout_filling_fluid", + if (matchingFluidStacks.size() == 0) { + return Component.literal("Invalid"); + } + return CreateLang.translateDirect("recipe.assembly.spout_filling_fluid", matchingFluidStacks.get(0).getDisplayName().getString()); } @@ -79,7 +79,7 @@ public class FillingRecipe extends ProcessingRecipe implements IA public void addRequiredMachines(Set list) { list.add(AllBlocks.SPOUT.get()); } - + @Override public Supplier> getJEISubCategory() { return () -> SequencedAssemblySubCategory.AssemblySpouting::new; diff --git a/src/main/java/com/simibubi/create/content/fluids/transfer/FluidDrainingBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidDrainingBehaviour.java index 6354642fa0..bb4a6a405a 100644 --- a/src/main/java/com/simibubi/create/content/fluids/transfer/FluidDrainingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidDrainingBehaviour.java @@ -12,11 +12,11 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.BBHelper; -import com.simibubi.create.foundation.utility.Iterate; import it.unimi.dsi.fastutil.PriorityQueue; import it.unimi.dsi.fastutil.objects.ObjectHeapPriorityQueue; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.BBHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -29,6 +29,7 @@ import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraftforge.fluids.FluidStack; public class FluidDrainingBehaviour extends FluidManipulationBehaviour { @@ -106,8 +107,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { && blockState.getValue(BlockStateProperties.WATERLOGGED)) { emptied = blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(false)); fluid = Fluids.WATER; - } else if (blockState.getBlock() instanceof LiquidBlock) { - LiquidBlock flowingFluid = (LiquidBlock) blockState.getBlock(); + } else if (blockState.getBlock() instanceof LiquidBlock flowingFluid) { emptied = Blocks.AIR.defaultBlockState(); if (blockState.getValue(LiquidBlock.LEVEL) == 0) fluid = flowingFluid.getFluid(); @@ -124,7 +124,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { } } else if (blockState.getFluidState() .getType() != Fluids.EMPTY && blockState.getCollisionShape(world, currentPos, CollisionContext.empty()) - .isEmpty()) { + .isEmpty()) { fluid = blockState.getFluidState() .getType(); emptied = Blocks.AIR.defaultBlockState(); @@ -148,8 +148,14 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { playEffect(world, currentPos, fluid, true); blockEntity.award(AllAdvancements.HOSE_PULLEY); - if (!blockEntity.isVirtual()) + if (!blockEntity.isVirtual()) { world.setBlock(currentPos, emptied, 2 | 16); + + BlockState stateAbove = world.getBlockState(currentPos.above()); + if (stateAbove.getFluidState() + .getType() == Fluids.EMPTY && !stateAbove.canSurvive(world, currentPos.above())) + world.setBlock(currentPos.above(), Blocks.AIR.defaultBlockState(), 2 | 16); + } affectedArea = BBHelper.encapsulate(affectedArea, currentPos); queue.dequeue(); @@ -223,7 +229,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { return blockState.getValue(LiquidBlock.LEVEL) == 0 ? FluidBlockType.SOURCE : FluidBlockType.FLOWING; if (blockState.getFluidState() .getType() != Fluids.EMPTY && blockState.getCollisionShape(getWorld(), pos, CollisionContext.empty()) - .isEmpty()) + .isEmpty()) return FluidBlockType.SOURCE; return FluidBlockType.NONE; } diff --git a/src/main/java/com/simibubi/create/content/fluids/transfer/FluidFillingBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidFillingBehaviour.java index 52ea8b456a..3374988e05 100644 --- a/src/main/java/com/simibubi/create/content/fluids/transfer/FluidFillingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidFillingBehaviour.java @@ -10,12 +10,12 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.BBHelper; -import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.infrastructure.config.AllConfigs; import it.unimi.dsi.fastutil.PriorityQueue; import it.unimi.dsi.fastutil.objects.ObjectHeapPriorityQueue; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.BBHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.sounds.SoundEvents; @@ -203,8 +203,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { } LevelTickAccess pendingFluidTicks = world.getFluidTicks(); - if (pendingFluidTicks instanceof LevelTicks) { - LevelTicks serverTickList = (LevelTicks) pendingFluidTicks; + if (pendingFluidTicks instanceof LevelTicks serverTickList) { serverTickList.clearArea(new BoundingBox(currentPos)); } @@ -268,7 +267,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { if (fluidState.getType() != Fluids.EMPTY && blockState.getCollisionShape(getWorld(), pos, CollisionContext.empty()) - .isEmpty()) + .isEmpty()) return toFill.isSame(fluidState.getType()) ? SpaceType.FILLED : SpaceType.BLOCKING; return canBeReplacedByFluid(world, pos, blockState) ? SpaceType.FILLABLE : SpaceType.BLOCKING; diff --git a/src/main/java/com/simibubi/create/content/fluids/transfer/FluidManipulationBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidManipulationBehaviour.java index d3433d5fd5..1781bcf40f 100644 --- a/src/main/java/com/simibubi/create/content/fluids/transfer/FluidManipulationBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidManipulationBehaviour.java @@ -12,11 +12,11 @@ import com.simibubi.create.AllTags.AllFluidTags; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemEmptying.java b/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemEmptying.java index d77d00c12a..672e5a9c0d 100644 --- a/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemEmptying.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemEmptying.java @@ -5,10 +5,9 @@ import java.util.Optional; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.fluids.potion.PotionFluidHandler; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Pair; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.PotionItem; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.level.Level; import net.minecraftforge.common.capabilities.ForgeCapabilities; @@ -26,7 +25,7 @@ public class GenericItemEmptying { public static boolean canItemBeEmptied(Level world, ItemStack stack) { if (PotionFluidHandler.isPotionItem(stack)) return true; - + WRAPPER.setItem(0, stack); if (AllRecipeTypes.EMPTYING.find(WRAPPER, world) .isPresent()) @@ -51,7 +50,7 @@ public class GenericItemEmptying { if (PotionFluidHandler.isPotionItem(stack)) return PotionFluidHandler.emptyPotion(stack, simulate); - + WRAPPER.setItem(0, stack); Optional> recipe = AllRecipeTypes.EMPTYING.find(WRAPPER, world); if (recipe.isPresent()) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/BlockStressDefaults.java b/src/main/java/com/simibubi/create/content/kinetics/BlockStressDefaults.java deleted file mode 100644 index 3b1db16a8d..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/BlockStressDefaults.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.simibubi.create.content.kinetics; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - -import com.simibubi.create.foundation.utility.Couple; -import com.tterrag.registrate.builders.BlockBuilder; -import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; - -public class BlockStressDefaults { - - /** - * Increment this number if all stress entries should be forced to update in the - * next release. Worlds from the previous version will overwrite potentially - * changed values with the new defaults. - */ - public static final int FORCED_UPDATE_VERSION = 2; - - public static final Map DEFAULT_IMPACTS = new ConcurrentHashMap<>(); - public static final Map DEFAULT_CAPACITIES = new ConcurrentHashMap<>(); - public static final Map>> GENERATOR_SPEEDS = new ConcurrentHashMap<>(); - - public static void setDefaultImpact(ResourceLocation blockId, double impact) { - DEFAULT_IMPACTS.put(blockId, impact); - } - - public static void setDefaultCapacity(ResourceLocation blockId, double capacity) { - DEFAULT_CAPACITIES.put(blockId, capacity); - } - - public static void setGeneratorSpeed(ResourceLocation blockId, Supplier> provider) { - GENERATOR_SPEEDS.put(blockId, provider); - } - - public static NonNullUnaryOperator> setNoImpact() { - return setImpact(0); - } - - public static NonNullUnaryOperator> setImpact(double impact) { - return b -> { - setDefaultImpact(new ResourceLocation(b.getOwner() - .getModid(), b.getName()), impact); - return b; - }; - } - - public static NonNullUnaryOperator> setCapacity(double capacity) { - return b -> { - setDefaultCapacity(new ResourceLocation(b.getOwner() - .getModid(), b.getName()), capacity); - return b; - }; - } - - public static NonNullUnaryOperator> setGeneratorSpeed( - Supplier> provider) { - return b -> { - setGeneratorSpeed(new ResourceLocation(b.getOwner() - .getModid(), b.getName()), provider); - return b; - }; - } - -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/BlockStressValues.java b/src/main/java/com/simibubi/create/content/kinetics/BlockStressValues.java deleted file mode 100644 index 7225fbfa65..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/BlockStressValues.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.simibubi.create.content.kinetics; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.RegisteredObjects; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; - -public class BlockStressValues { - - private static final Map PROVIDERS = new HashMap<>(); - - public static void registerProvider(String namespace, IStressValueProvider provider) { - PROVIDERS.put(namespace, provider); - } - - @Nullable - public static IStressValueProvider getProvider(String namespace) { - return PROVIDERS.get(namespace); - } - - @Nullable - public static IStressValueProvider getProvider(Block block) { - return getProvider(RegisteredObjects.getKeyOrThrow(block) - .getNamespace()); - } - - public static double getImpact(Block block) { - ResourceLocation blockId = RegisteredObjects.getKeyOrThrow(block); - IStressValueProvider provider = getProvider(blockId.getNamespace()); - if (provider != null) { - return provider.getImpact(block); - } - Double defaultImpact = BlockStressDefaults.DEFAULT_IMPACTS.get(blockId); - if (defaultImpact != null) { - return defaultImpact; - } - return 0; - } - - public static double getCapacity(Block block) { - ResourceLocation blockId = RegisteredObjects.getKeyOrThrow(block); - IStressValueProvider provider = getProvider(blockId.getNamespace()); - if (provider != null) { - return provider.getCapacity(block); - } - Double defaultCapacity = BlockStressDefaults.DEFAULT_CAPACITIES.get(blockId); - if (defaultCapacity != null) { - return defaultCapacity; - } - return 0; - } - - public static boolean hasImpact(Block block) { - ResourceLocation blockId = RegisteredObjects.getKeyOrThrow(block); - IStressValueProvider provider = getProvider(blockId.getNamespace()); - if (provider != null) { - return provider.hasImpact(block); - } - return BlockStressDefaults.DEFAULT_IMPACTS.containsKey(blockId); - } - - public static boolean hasCapacity(Block block) { - ResourceLocation blockId = RegisteredObjects.getKeyOrThrow(block); - IStressValueProvider provider = getProvider(blockId.getNamespace()); - if (provider != null) { - return provider.hasCapacity(block); - } - return BlockStressDefaults.DEFAULT_CAPACITIES.containsKey(blockId); - } - - @Nullable - public static Couple getGeneratedRPM(Block block) { - ResourceLocation blockId = RegisteredObjects.getKeyOrThrow(block); - IStressValueProvider provider = getProvider(blockId.getNamespace()); - if (provider != null) { - return provider.getGeneratedRPM(block); - } - return null; - } - - public interface IStressValueProvider { - /** - * Gets the stress impact of a block. - * - * @param block The block. - * @return the stress impact value of the block, or 0 if it does not have one. - */ - double getImpact(Block block); - - /** - * Gets the stress capacity of a block. - * - * @param block The block. - * @return the stress capacity value of the block, or 0 if it does not have one. - */ - double getCapacity(Block block); - - boolean hasImpact(Block block); - - boolean hasCapacity(Block block); - - /** - * - * @param block - * @return min, max generated RPM; null if block does not have a stress capacity - */ - @Nullable - Couple getGeneratedRPM(Block block); - } - -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/KineticDebugger.java b/src/main/java/com/simibubi/create/content/kinetics/KineticDebugger.java index 90c5a4ee5e..b8716230f7 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/KineticDebugger.java +++ b/src/main/java/com/simibubi/create/content/kinetics/KineticDebugger.java @@ -1,13 +1,14 @@ package com.simibubi.create.content.kinetics; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.render.SuperByteBufferCache; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; @@ -28,7 +29,7 @@ public class KineticDebugger { if (!isActive()) { if (KineticBlockEntityRenderer.rainbowMode) { KineticBlockEntityRenderer.rainbowMode = false; - CreateClient.BUFFER_CACHE.invalidate(); + SuperByteBufferCache.getInstance().invalidate(); } return; } @@ -44,18 +45,18 @@ public class KineticDebugger { .getBlockSupportShape(world, toOutline); if (be.getTheoreticalSpeed() != 0 && !shape.isEmpty()) - CreateClient.OUTLINER.chaseAABB("kineticSource", shape.bounds() + Outliner.getInstance().chaseAABB("kineticSource", shape.bounds() .move(toOutline)) - .lineWidth(1 / 16f) - .colored(be.hasSource() ? Color.generateFromLong(be.network).getRGB() : 0xffcc00); + .lineWidth(1 / 16f) + .colored(be.hasSource() ? Color.generateFromLong(be.network).getRGB() : 0xffcc00); if (state.getBlock() instanceof IRotate) { Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); Vec3 vec = Vec3.atLowerCornerOf(Direction.get(AxisDirection.POSITIVE, axis) - .getNormal()); + .getNormal()); Vec3 center = VecHelper.getCenterOf(be.getBlockPos()); - CreateClient.OUTLINER.showLine("rotationAxis", center.add(vec), center.subtract(vec)) - .lineWidth(1 / 16f); + Outliner.getInstance().showLine("rotationAxis", center.add(vec), center.subtract(vec)) + .lineWidth(1 / 16f); } } @@ -75,10 +76,9 @@ public class KineticDebugger { return null; if (world == null) return null; - if (!(obj instanceof BlockHitResult)) + if (!(obj instanceof BlockHitResult ray)) return null; - BlockHitResult ray = (BlockHitResult) obj; BlockEntity be = world.getBlockEntity(ray.getBlockPos()); if (!(be instanceof KineticBlockEntity)) return null; diff --git a/src/main/java/com/simibubi/create/content/kinetics/RotationPropagator.java b/src/main/java/com/simibubi/create/content/kinetics/RotationPropagator.java index 0399ba8081..0b2ad4f2f7 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/RotationPropagator.java +++ b/src/main/java/com/simibubi/create/content/kinetics/RotationPropagator.java @@ -16,9 +16,9 @@ import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlock; import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlockEntity; import com.simibubi.create.content.kinetics.transmission.SplitShaftBlockEntity; -import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -47,11 +47,9 @@ public class RotationPropagator { Block fromBlock = stateFrom.getBlock(); Block toBlock = stateTo.getBlock(); - if (!(fromBlock instanceof IRotate && toBlock instanceof IRotate)) + if (!(fromBlock instanceof IRotate definitionFrom && toBlock instanceof IRotate definitionTo)) return 0; - final IRotate definitionFrom = (IRotate) fromBlock; - final IRotate definitionTo = (IRotate) toBlock; final BlockPos diff = to.getBlockPos() .subtract(from.getBlockPos()); final Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); @@ -157,7 +155,7 @@ public class RotationPropagator { } private static float getAxisModifier(KineticBlockEntity be, Direction direction) { - if (!(be.hasSource()||be.isSource()) || !(be instanceof DirectionalShaftHalvesBlockEntity)) + if (!(be.hasSource() || be.isSource()) || !(be instanceof DirectionalShaftHalvesBlockEntity)) return 1; Direction source = ((DirectionalShaftHalvesBlockEntity) be).getSourceFacing(); @@ -235,7 +233,7 @@ public class RotationPropagator { Math.signum(newSpeed) != Math.signum(speedOfNeighbour) && (newSpeed != 0 && speedOfNeighbour != 0); boolean tooFast = Math.abs(newSpeed) > AllConfigs.server().kinetics.maxRotationSpeed.get() - || Math.abs(oppositeSpeed) > AllConfigs.server().kinetics.maxRotationSpeed.get(); + || Math.abs(oppositeSpeed) > AllConfigs.server().kinetics.maxRotationSpeed.get(); // Check for both the new speed and the opposite speed, just in case boolean speedChangedTooOften = currentTE.getFlickerScore() > MAX_FLICKER_SCORE; @@ -321,10 +319,9 @@ public class RotationPropagator { if (!(neighbourState.getBlock() instanceof IRotate)) continue; BlockEntity blockEntity = worldIn.getBlockEntity(neighbourPos); - if (!(blockEntity instanceof KineticBlockEntity)) + if (!(blockEntity instanceof KineticBlockEntity neighbourBE)) continue; - final KineticBlockEntity neighbourBE = (KineticBlockEntity) blockEntity; if (!neighbourBE.hasSource() || !neighbourBE.source.equals(pos)) continue; @@ -350,9 +347,8 @@ public class RotationPropagator { while (!frontier.isEmpty()) { final BlockPos pos = frontier.remove(0); BlockEntity blockEntity = world.getBlockEntity(pos); - if (!(blockEntity instanceof KineticBlockEntity)) + if (!(blockEntity instanceof KineticBlockEntity currentBE)) continue; - final KineticBlockEntity currentBE = (KineticBlockEntity) blockEntity; currentBE.removeSource(); currentBE.sendData(); @@ -393,9 +389,8 @@ public class RotationPropagator { return null; BlockEntity neighbourBE = currentTE.getLevel() .getBlockEntity(neighbourPos); - if (!(neighbourBE instanceof KineticBlockEntity)) + if (!(neighbourBE instanceof KineticBlockEntity neighbourKBE)) return null; - KineticBlockEntity neighbourKBE = (KineticBlockEntity) neighbourBE; if (!(neighbourKBE.getBlockState() .getBlock() instanceof IRotate)) return null; @@ -439,9 +434,8 @@ public class RotationPropagator { } BlockState blockState = be.getBlockState(); - if (!(blockState.getBlock() instanceof IRotate)) + if (!(blockState.getBlock() instanceof IRotate block)) return neighbours; - IRotate block = (IRotate) blockState.getBlock(); return be.addPropagationLocations(block, blockState, neighbours); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/TorquePropagator.java b/src/main/java/com/simibubi/create/content/kinetics/TorquePropagator.java index 5f6c64f51f..bd4dbaf69b 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/TorquePropagator.java +++ b/src/main/java/com/simibubi/create/content/kinetics/TorquePropagator.java @@ -5,8 +5,8 @@ import java.util.Map; import com.simibubi.create.Create; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; -import com.simibubi.create.foundation.utility.WorldHelper; +import net.createmod.catnip.levelWrappers.WorldHelper; import net.minecraft.world.level.LevelAccessor; public class TorquePropagator { diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/BackHalfShaftVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/BackHalfShaftVisual.java deleted file mode 100644 index 5a464e698c..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/base/BackHalfShaftVisual.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.content.kinetics.base; - -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class BackHalfShaftVisual extends HalfShaftVisual { - public BackHalfShaftVisual(VisualizationContext context, T blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Direction getShaftDirection() { - return blockState.getValue(BlockStateProperties.FACING).getOpposite(); - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity.java index ceddd76692..278440b658 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity.java @@ -2,9 +2,10 @@ package com.simibubi.create.content.kinetics.base; import java.util.concurrent.atomic.AtomicInteger; +import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; @@ -129,7 +130,7 @@ public abstract class BlockBreakingKineticBlockEntity extends KineticBlockEntity } public static boolean isBreakable(BlockState stateToBreak, float blockHardness) { - return !(stateToBreak.liquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1); + return !(stateToBreak.liquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1 || AllBlockTags.NON_BREAKABLE.matches(stateToBreak)); } public void onBlockBroken(BlockState stateToBreak) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingMovementBehaviour.java index df9fe85586..c406f8bb3c 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingMovementBehaviour.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.kinetics.base; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.mounted.MountedContraption; import com.simibubi.create.content.trains.entity.CarriageContraption; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalAxisKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalAxisKineticBlock.java index f94b67d2b4..92c8a065e4 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalAxisKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalAxisKineticBlock.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; import com.simibubi.create.content.contraptions.StructureTransform; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -16,7 +16,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.properties.BooleanProperty; -public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBlock implements ITransformableBlock { +public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBlock implements TransformableBlock { public static final BooleanProperty AXIS_ALONG_FIRST_COORDINATE = BooleanProperty.create("axis_along_first"); diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalKineticBlock.java index 9e96697557..6ff6962bf4 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalKineticBlock.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.foundation.utility.Iterate; - +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.Block; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java index 724bab243d..e3c5e67db3 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java @@ -5,7 +5,7 @@ import java.util.List; import com.simibubi.create.content.kinetics.KineticNetwork; import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -38,9 +38,8 @@ public abstract class GeneratingKineticBlockEntity extends KineticBlockEntity { public void setSource(BlockPos source) { super.setSource(source); BlockEntity blockEntity = level.getBlockEntity(source); - if (!(blockEntity instanceof KineticBlockEntity)) + if (!(blockEntity instanceof KineticBlockEntity sourceBE)) return; - KineticBlockEntity sourceBE = (KineticBlockEntity) blockEntity; if (reActivateSource && Math.abs(sourceBE.getSpeed()) >= Math.abs(getGeneratedSpeed())) reActivateSource = false; } @@ -64,9 +63,9 @@ public abstract class GeneratingKineticBlockEntity extends KineticBlockEntity { if (Mth.equal(stressBase, 0)) return added; - Lang.translate("gui.goggles.generator_stats") + CreateLang.translate("gui.goggles.generator_stats") .forGoggles(tooltip); - Lang.translate("tooltip.capacityProvided") + CreateLang.translate("tooltip.capacityProvided") .style(ChatFormatting.GRAY) .forGoggles(tooltip); @@ -76,11 +75,11 @@ public abstract class GeneratingKineticBlockEntity extends KineticBlockEntity { float stressTotal = Math.abs(stressBase * speed); - Lang.number(stressTotal) + CreateLang.number(stressTotal) .translate("generic.unit.stress") .style(ChatFormatting.AQUA) .space() - .add(Lang.translate("gui.goggles.at_current_speed") + .add(CreateLang.translate("gui.goggles.at_current_speed") .style(ChatFormatting.DARK_GRAY)) .forGoggles(tooltip, 1); diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/HalfShaftVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/HalfShaftVisual.java deleted file mode 100644 index d20ec91a9d..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/base/HalfShaftVisual.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.simibubi.create.content.kinetics.base; - -import com.simibubi.create.AllPartialModels; - -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.model.Models; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class HalfShaftVisual extends SingleRotatingVisual { - public HalfShaftVisual(VisualizationContext context, T blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Model model() { - return Models.partial(AllPartialModels.SHAFT_HALF, getShaftDirection()); - } - - protected Direction getShaftDirection() { - return blockState.getValue(BlockStateProperties.FACING); - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalAxisKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalAxisKineticBlock.java index 5b12fc4bdb..827615518f 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalAxisKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalAxisKineticBlock.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.foundation.utility.Iterate; - +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalHalfShaftVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalHalfShaftVisual.java deleted file mode 100644 index 48effc0247..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalHalfShaftVisual.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.simibubi.create.content.kinetics.base; - -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class HorizontalHalfShaftVisual extends HalfShaftVisual { - - public HorizontalHalfShaftVisual(VisualizationContext context, T blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Direction getShaftDirection() { - return blockState.getValue(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalKineticBlock.java index 027ba89ebe..cfbc1bd4df 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalKineticBlock.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.foundation.utility.Iterate; - +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.Block; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/IRotate.java b/src/main/java/com/simibubi/create/content/kinetics/base/IRotate.java index 73afc24b96..1275ec7f35 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/IRotate.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/IRotate.java @@ -2,10 +2,11 @@ package com.simibubi.create.content.kinetics.base; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.lang.LangBuilder; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -73,12 +74,12 @@ public interface IRotate extends IWrenchable { public static LangBuilder getFormattedSpeedText(float speed, boolean overstressed) { SpeedLevel speedLevel = of(speed); - LangBuilder builder = Lang.text(TooltipHelper.makeProgressBar(3, speedLevel.ordinal())); + LangBuilder builder = CreateLang.text(TooltipHelper.makeProgressBar(3, speedLevel.ordinal())); builder.translate("tooltip.speedRequirement." + Lang.asId(speedLevel.name())) .space() .text("(") - .add(Lang.number(Math.abs(speed))) + .add(CreateLang.number(Math.abs(speed))) .space() .translate("generic.unit.rpm") .text(")") @@ -133,7 +134,7 @@ public interface IRotate extends IWrenchable { public static LangBuilder getFormattedStressText(double stressPercent) { StressImpact stressLevel = of(stressPercent); - return Lang.text(TooltipHelper.makeProgressBar(3, Math.min(stressLevel.ordinal() + 1, 3))) + return CreateLang.text(TooltipHelper.makeProgressBar(3, Math.min(stressLevel.ordinal() + 1, 3))) .translate("tooltip.stressImpact." + Lang.asId(stressLevel.name())) .text(String.format(" (%s%%) ", (int) (stressPercent * 100))) .style(stressLevel.getRelativeColor()); diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlock.java index 40882f34f5..d92c48f1db 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlock.java @@ -28,8 +28,7 @@ public abstract class KineticBlock extends Block implements IRotate { // we can prevent a major re-propagation here BlockEntity blockEntity = worldIn.getBlockEntity(pos); - if (blockEntity instanceof KineticBlockEntity) { - KineticBlockEntity kineticBlockEntity = (KineticBlockEntity) blockEntity; + if (blockEntity instanceof KineticBlockEntity kineticBlockEntity) { kineticBlockEntity.preventSpeedUpdate = 0; if (oldState.getBlock() != state.getBlock()) @@ -42,7 +41,7 @@ public abstract class KineticBlock extends Block implements IRotate { kineticBlockEntity.preventSpeedUpdate = 2; } } - + @Override public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { IBE.onRemove(pState, pLevel, pPos, pNewState); @@ -61,14 +60,13 @@ public abstract class KineticBlock extends Block implements IRotate { @Override public void updateIndirectNeighbourShapes(BlockState stateIn, LevelAccessor worldIn, BlockPos pos, int flags, - int count) { + int count) { if (worldIn.isClientSide()) return; BlockEntity blockEntity = worldIn.getBlockEntity(pos); - if (!(blockEntity instanceof KineticBlockEntity)) + if (!(blockEntity instanceof KineticBlockEntity kbe)) return; - KineticBlockEntity kbe = (KineticBlockEntity) blockEntity; if (kbe.preventSpeedUpdate > 0) return; @@ -86,10 +84,9 @@ public abstract class KineticBlock extends Block implements IRotate { return; BlockEntity blockEntity = worldIn.getBlockEntity(pos); - if (!(blockEntity instanceof KineticBlockEntity)) + if (!(blockEntity instanceof KineticBlockEntity kbe)) return; - KineticBlockEntity kbe = (KineticBlockEntity) blockEntity; kbe.effects.queueRotationIndicators(); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntity.java index f5bae223eb..bab6c06ea9 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntity.java @@ -8,9 +8,9 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.Create; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; -import com.simibubi.create.content.equipment.goggles.IHaveHoveringInformation; -import com.simibubi.create.content.kinetics.BlockStressValues; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.api.equipment.goggles.IHaveHoveringInformation; +import com.simibubi.create.api.stress.BlockStressValues; import com.simibubi.create.content.kinetics.KineticNetwork; import com.simibubi.create.content.kinetics.RotationPropagator; import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; @@ -21,13 +21,13 @@ import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGear import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.sound.SoundScapes; import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; +import net.createmod.catnip.lang.FontHelper.Palette; import net.minecraft.ChatFormatting; import net.minecraft.client.resources.language.I18n; import net.minecraft.core.BlockPos; @@ -44,6 +44,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -393,41 +394,46 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI kineticBlockEntity.removeSource(); } + if (blockEntity instanceof GeneratingKineticBlockEntity generatingBlockEntity) { + generatingBlockEntity.reActivateSource = true; + } + world.setBlock(pos, state, 3); } @Override - public void addBehaviours(List behaviours) {} + public void addBehaviours(List behaviours) { + } @Override public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0; if (overStressed && AllConfigs.client().enableOverstressedTooltip.get()) { - Lang.translate("gui.stressometer.overstressed") + CreateLang.translate("gui.stressometer.overstressed") .style(GOLD) .forGoggles(tooltip); - Component hint = Lang.translateDirect("gui.contraptions.network_overstressed"); + Component hint = CreateLang.translateDirect("gui.contraptions.network_overstressed"); List cutString = TooltipHelper.cutTextComponent(hint, Palette.GRAY_AND_WHITE); - for (int i = 0; i < cutString.size(); i++) - Lang.builder() - .add(cutString.get(i) + for (Component component : cutString) + CreateLang.builder() + .add(component .copy()) .forGoggles(tooltip); return true; } if (notFastEnough) { - Lang.translate("tooltip.speedRequirement") + CreateLang.translate("tooltip.speedRequirement") .style(GOLD) .forGoggles(tooltip); MutableComponent hint = - Lang.translateDirect("gui.contraptions.not_fast_enough", I18n.get(getBlockState().getBlock() + CreateLang.translateDirect("gui.contraptions.not_fast_enough", I18n.get(getBlockState().getBlock() .getDescriptionId())); List cutString = TooltipHelper.cutTextComponent(hint, Palette.GRAY_AND_WHITE); - for (int i = 0; i < cutString.size(); i++) - Lang.builder() - .add(cutString.get(i) + for (Component component : cutString) + CreateLang.builder() + .add(component .copy()) .forGoggles(tooltip); return true; @@ -446,7 +452,7 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI if (Mth.equal(stressAtBase, 0)) return added; - Lang.translate("gui.goggles.kinetic_stats") + CreateLang.translate("gui.goggles.kinetic_stats") .forGoggles(tooltip); addStressImpactStats(tooltip, stressAtBase); @@ -456,17 +462,17 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI } protected void addStressImpactStats(List tooltip, float stressAtBase) { - Lang.translate("tooltip.stressImpact") + CreateLang.translate("tooltip.stressImpact") .style(GRAY) .forGoggles(tooltip); float stressTotal = stressAtBase * Math.abs(getTheoreticalSpeed()); - Lang.number(stressTotal) + CreateLang.number(stressTotal) .translate("generic.unit.stress") .style(ChatFormatting.AQUA) .space() - .add(Lang.translate("gui.goggles.at_current_speed") + .add(CreateLang.translate("gui.goggles.at_current_speed") .style(ChatFormatting.DARK_GRAY)) .forGoggles(tooltip, 1); } @@ -521,10 +527,10 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI * @param connectedViaCogs whether these kinetic blocks are connected via mutual * IRotate.hasIntegratedCogwheel() * @return factor of rotation speed from this BE to other. 0 if no rotation is - * transferred, or the standard rules apply (integrated shafts/cogs) + * transferred, or the standard rules apply (integrated shafts/cogs) */ public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, - boolean connectedViaAxes, boolean connectedViaCogs) { + boolean connectedViaAxes, boolean connectedViaCogs) { return 0; } @@ -564,7 +570,7 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI * @param state * @param otherState * @return true if this and the other component should check their propagation - * factor and are not already connected via integrated cogs or shafts + * factor and are not already connected via integrated cogs or shafts */ public boolean isCustomConnection(KineticBlockEntity other, BlockState state, BlockState otherState) { return false; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java index 312087cc6c..ec924455ce 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java @@ -1,20 +1,19 @@ package com.simibubi.create.content.kinetics.base; +import net.createmod.catnip.animation.AnimationTickHolder; import org.apache.commons.lang3.ArrayUtils; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.kinetics.KineticDebugger; -import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.SuperByteBufferCache; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.render.SuperByteBufferCache; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -69,12 +68,12 @@ public class KineticBlockEntityRenderer extends Sa } protected SuperByteBuffer getRotatedModel(T be, BlockState state) { - return CachedBufferer.block(KINETIC_BLOCK, state); + return CachedBuffers.block(KINETIC_BLOCK, state); } public static void renderRotatingKineticBlock(KineticBlockEntity be, BlockState renderedState, PoseStack ms, VertexConsumer buffer, int light) { - SuperByteBuffer superByteBuffer = CachedBufferer.block(KINETIC_BLOCK, renderedState); + SuperByteBuffer superByteBuffer = CachedBuffers.block(KINETIC_BLOCK, renderedState); renderRotatingBuffer(be, superByteBuffer, ms, buffer, light); } @@ -121,12 +120,7 @@ public class KineticBlockEntityRenderer extends Sa } public static float getRotationOffsetForPosition(KineticBlockEntity be, final BlockPos pos, final Axis axis) { - float offset = ICogWheel.isLargeCog(be.getBlockState()) ? 11.25f : 0; - double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY()) - + ((axis == Axis.Z) ? 0 : pos.getZ())) % 2; - if (d == 0) - offset = 22.5f; - return offset + be.getRotationAngleOffset(axis); + return KineticBlockEntityVisual.rotationOffset(be.getBlockState(), axis, pos) + be.getRotationAngleOffset(axis); } public static BlockState shaft(Axis axis) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityVisual.java index da80dd7943..87291d3c53 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityVisual.java @@ -1,91 +1,41 @@ package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.AllBlocks; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; -import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Vec3i; import net.minecraft.world.level.block.state.BlockState; public abstract class KineticBlockEntityVisual extends AbstractBlockEntityVisual { - protected final Direction.Axis axis; - public KineticBlockEntityVisual(VisualizationContext context, T blockEntity, float partialTick) { super(context, blockEntity, partialTick); - axis = (blockState.getBlock() instanceof IRotate irotate) ? irotate.getRotationAxis(blockState) : Axis.Y; } - protected final void updateRotation(RotatingInstance instance) { - updateRotation(instance, getRotationAxis(), getBlockEntitySpeed()); + protected Direction.Axis rotationAxis() { + return rotationAxis(blockState); } - protected final void updateRotation(RotatingInstance instance, Direction.Axis axis) { - updateRotation(instance, axis, getBlockEntitySpeed()); - } - - protected final void updateRotation(RotatingInstance instance, float speed) { - updateRotation(instance, getRotationAxis(), speed); - } - - protected final void updateRotation(RotatingInstance instance, Direction.Axis axis, float speed) { - instance.setRotationAxis(axis) - .setRotationOffset(getRotationOffset(axis)) - .setRotationalSpeed(speed) - .setColor(blockEntity) - .setChanged(); - } - - protected final RotatingInstance setup(RotatingInstance key) { - return setup(key, getRotationAxis(), getBlockEntitySpeed()); - } - - protected final RotatingInstance setup(RotatingInstance key, Direction.Axis axis) { - return setup(key, axis, getBlockEntitySpeed()); - } - - protected final RotatingInstance setup(RotatingInstance key, float speed) { - return setup(key, getRotationAxis(), speed); - } - - protected final RotatingInstance setup(RotatingInstance key, Direction.Axis axis, float speed) { - key.setRotationAxis(axis) - .setRotationalSpeed(speed) - .setRotationOffset(getRotationOffset(axis)) - .setColor(blockEntity) - .setPosition(getVisualPosition()) - .setChanged(); - - return key; - } - - protected float getRotationOffset(final Direction.Axis axis) { - float offset = ICogWheel.isLargeCog(blockState) ? 11.25f : 0; - double d = (((axis == Direction.Axis.X) ? 0 : pos.getX()) + ((axis == Direction.Axis.Y) ? 0 : pos.getY()) - + ((axis == Direction.Axis.Z) ? 0 : pos.getZ())) % 2; - if (d == 0) { - offset = 22.5f; + public static float rotationOffset(BlockState state, Axis axis, Vec3i pos) { + if (shouldOffset(axis, pos)) { + return 22.5f; + } else { + return ICogWheel.isLargeCog(state) ? 11.25f : 0; } - return offset; } - protected Direction.Axis getRotationAxis() { - return axis; + public static boolean shouldOffset(Axis axis, Vec3i pos) { + // Sum the components of the other 2 axes. + int x = (axis == Axis.X) ? 0 : pos.getX(); + int y = (axis == Axis.Y) ? 0 : pos.getY(); + int z = (axis == Axis.Z) ? 0 : pos.getZ(); + return ((x + y + z) % 2) == 0; } - protected float getBlockEntitySpeed() { - return blockEntity.getSpeed(); - } - - protected BlockState shaft() { - return shaft(getRotationAxis()); - } - - public static BlockState shaft(Direction.Axis axis) { - return AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, axis); + public static Axis rotationAxis(BlockState blockState) { + return (blockState.getBlock() instanceof IRotate irotate) ? irotate.getRotationAxis(blockState) : Axis.Y; } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticEffectHandler.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticEffectHandler.java index b80763459b..0a49c8a449 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/KineticEffectHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticEffectHandler.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.kinetics.base; import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; import net.minecraft.core.particles.ParticleOptions; @@ -76,10 +76,9 @@ public class KineticEffectHandler { BlockState state = kte.getBlockState(); Block block = state.getBlock(); - if (!(block instanceof KineticBlock)) + if (!(block instanceof KineticBlock kb)) return; - KineticBlock kb = (KineticBlock) block; float radius1 = kb.getParticleInitialRadius(); float radius2 = kb.getParticleTargetRadius(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticInstance.java deleted file mode 100644 index f8b716dc82..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/base/KineticInstance.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.simibubi.create.content.kinetics.base; - -import org.joml.Vector3f; - -import com.simibubi.create.foundation.utility.Color; - -import dev.engine_room.flywheel.api.instance.InstanceHandle; -import dev.engine_room.flywheel.api.instance.InstanceType; -import dev.engine_room.flywheel.lib.instance.ColoredLitInstance; -import net.minecraft.core.BlockPos; - -public class KineticInstance extends ColoredLitInstance { - public float x; - public float y; - public float z; - public float rotationalSpeed; - public float rotationOffset; - - protected KineticInstance(InstanceType type, InstanceHandle handle) { - super(type, handle); - } - - public KineticInstance setPosition(BlockPos pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); - } - - public KineticInstance setPosition(Vector3f pos) { - return setPosition(pos.x(), pos.y(), pos.z()); - } - - public KineticInstance setPosition(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - public KineticInstance nudge(float x, float y, float z) { - this.x += x; - this.y += y; - this.z += z; - return this; - } - - public KineticInstance setColor(KineticBlockEntity blockEntity) { - if (blockEntity.hasNetwork()) { - setColor(Color.generateFromLong(blockEntity.network)); - }else { - color(0xFF, 0xFF, 0xFF); - } - return this; - } - - public KineticInstance setColor(Color c) { - color(c.getRed(), c.getGreen(), c.getBlue()); - return this; - } - - public KineticInstance setRotationalSpeed(float rotationalSpeed) { - this.rotationalSpeed = rotationalSpeed; - return this; - } - - public KineticInstance setRotationOffset(float rotationOffset) { - this.rotationOffset = rotationOffset; - return this; - } - -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/OrientedRotatingVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/OrientedRotatingVisual.java new file mode 100644 index 0000000000..2d25b7d0da --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/OrientedRotatingVisual.java @@ -0,0 +1,94 @@ +package com.simibubi.create.content.kinetics.base; + +import java.util.function.Consumer; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllPartialModels.GantryShaftKey; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock.Part; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlockEntity; +import com.simibubi.create.foundation.render.AllInstanceTypes; + +import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.api.visual.BlockEntityVisual; +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.model.Models; +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import dev.engine_room.flywheel.lib.visualization.SimpleBlockEntityVisualizer; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class OrientedRotatingVisual extends KineticBlockEntityVisual { + protected final RotatingInstance rotatingModel; + + /** + * @param from The source model orientation to rotate away from. + * @param to The orientation to rotate to. + * @param model The model to spin. + */ + public OrientedRotatingVisual(VisualizationContext context, T blockEntity, float partialTick, Direction from, Direction to, Model model) { + super(context, blockEntity, partialTick); + + rotatingModel = instancerProvider().instancer(AllInstanceTypes.ROTATING, model) + .createInstance() + .rotateToFace(from, to) + .setup(blockEntity) + .setPosition(getVisualPosition()); + + rotatingModel.setChanged(); + } + + public static SimpleBlockEntityVisualizer.Factory of(PartialModel partial) { + return (context, blockEntity, partialTick) -> { + Direction facing = blockEntity.getBlockState() + .getValue(BlockStateProperties.FACING); + return new OrientedRotatingVisual<>(context, blockEntity, partialTick, Direction.SOUTH, facing, Models.partial(partial)); + }; + } + + public static SimpleBlockEntityVisualizer.Factory backHorizontal(PartialModel partial) { + return (context, blockEntity, partialTick) -> { + Direction facing = blockEntity.getBlockState() + .getValue(BlockStateProperties.HORIZONTAL_FACING) + .getOpposite(); + return new OrientedRotatingVisual<>(context, blockEntity, partialTick, Direction.SOUTH, facing, Models.partial(partial)); + }; + } + + public static BlockEntityVisual gantryShaft(VisualizationContext visualizationContext, GantryShaftBlockEntity gantryShaftBlockEntity, float partialTick) { + var blockState = gantryShaftBlockEntity.getBlockState(); + + Part part = blockState.getValue(GantryShaftBlock.PART); + + boolean isPowered = blockState.getValue(GantryShaftBlock.POWERED); + boolean isFlipped = blockState.getValue(GantryShaftBlock.FACING) + .getAxisDirection() == AxisDirection.NEGATIVE; + + var model = Models.partial(AllPartialModels.GANTRY_SHAFTS.get(new GantryShaftKey(part, isPowered, isFlipped))); + + return new OrientedRotatingVisual<>(visualizationContext, gantryShaftBlockEntity, partialTick, Direction.UP, blockState.getValue(GantryShaftBlock.FACING), model); + } + + @Override + public void update(float pt) { + rotatingModel.setup(blockEntity) + .setChanged(); + } + + @Override + public void updateLight(float partialTick) { + relight(rotatingModel); + } + + @Override + protected void _delete() { + rotatingModel.delete(); + } + + @Override + public void collectCrumblingInstances(Consumer consumer) { + consumer.accept(rotatingModel); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/RotatedPillarKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/RotatedPillarKineticBlock.java index 9c97e6b34f..f56a793d85 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/RotatedPillarKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/RotatedPillarKineticBlock.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.foundation.utility.Iterate; - +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.world.item.context.BlockPlaceContext; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/RotatingInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/RotatingInstance.java index 56d998c008..b8665949f8 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/RotatingInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/RotatingInstance.java @@ -1,27 +1,108 @@ package com.simibubi.create.content.kinetics.base; +import org.joml.Quaternionf; import org.joml.Vector3f; import dev.engine_room.flywheel.api.instance.InstanceHandle; import dev.engine_room.flywheel.api.instance.InstanceType; +import dev.engine_room.flywheel.lib.instance.ColoredLitOverlayInstance; +import net.createmod.catnip.theme.Color; import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Vec3i; -public class RotatingInstance extends KineticInstance { - public byte rotationAxisX; - public byte rotationAxisY; - public byte rotationAxisZ; +public class RotatingInstance extends ColoredLitOverlayInstance { + public static final float SPEED_MULTIPLIER = 6; - public RotatingInstance(InstanceType type, InstanceHandle handle) { + public byte rotationAxisX; + public byte rotationAxisY; + public byte rotationAxisZ; + public float x; + public float y; + public float z; + /** + * Speed in degrees per second + */ + public float rotationalSpeed; + /** + * Offset in degrees + */ + public float rotationOffset; + + /** + * Base rotation of the instance, applied before kinetic rotation + */ + public final Quaternionf rotation = new Quaternionf(); + + public RotatingInstance(InstanceType type, InstanceHandle handle) { super(type, handle); } - public RotatingInstance setRotationAxis(Direction.Axis axis) { - Direction orientation = Direction.get(Direction.AxisDirection.POSITIVE, axis); - return setRotationAxis(orientation.step()); - } + public static int colorFromBE(KineticBlockEntity be) { + if (be.hasNetwork()) + return Color.generateFromLong(be.network).getRGB(); + return 0xFFFFFF; + } - public RotatingInstance setRotationAxis(Vector3f axis) { - return setRotationAxis(axis.x(), axis.y(), axis.z()); + public RotatingInstance setup(KineticBlockEntity blockEntity) { + var blockState = blockEntity.getBlockState(); + var axis = KineticBlockEntityVisual.rotationAxis(blockState); + return setup(blockEntity, axis, blockEntity.getSpeed()); + } + + public RotatingInstance setup(KineticBlockEntity blockEntity, Axis axis) { + return setup(blockEntity, axis, blockEntity.getSpeed()); + } + + public RotatingInstance setup(KineticBlockEntity blockEntity, float speed) { + var blockState = blockEntity.getBlockState(); + var axis = KineticBlockEntityVisual.rotationAxis(blockState); + return setup(blockEntity, axis, speed); + } + + public RotatingInstance setup(KineticBlockEntity blockEntity, Axis axis, float speed) { + var blockState = blockEntity.getBlockState(); + var pos = blockEntity.getBlockPos(); + return setRotationAxis(axis) + .setRotationalSpeed(speed * RotatingInstance.SPEED_MULTIPLIER) + .setRotationOffset(KineticBlockEntityVisual.rotationOffset(blockState, axis, pos) + blockEntity.getRotationAngleOffset(axis)) + .setColor(blockEntity); + } + + public RotatingInstance rotateToFace(Direction.Axis axis) { + Direction orientation = Direction.get(Direction.AxisDirection.POSITIVE, axis); + return rotateToFace(orientation); + } + + public RotatingInstance rotateToFace(Direction from, Direction.Axis axis) { + Direction orientation = Direction.get(Direction.AxisDirection.POSITIVE, axis); + return rotateToFace(from, orientation); + } + + public RotatingInstance rotateToFace(Direction orientation) { + return rotateToFace(orientation.getStepX(), orientation.getStepY(), orientation.getStepZ()); + } + + public RotatingInstance rotateToFace(Direction from, Direction orientation) { + return rotateTo(from.getStepX(), from.getStepY(), from.getStepZ(), orientation.getStepX(), orientation.getStepY(), orientation.getStepZ()); + } + + public RotatingInstance rotateToFace(float stepX, float stepY, float stepZ) { + return rotateTo(0, 1, 0, stepX, stepY, stepZ); + } + + public RotatingInstance rotateTo(float fromX, float fromY, float fromZ, float toX, float toY, float toZ) { + rotation.rotateTo(fromX, fromY, fromZ, toX, toY, toZ); + return this; + } + + public RotatingInstance setRotationAxis(Direction.Axis axis) { + Direction orientation = Direction.get(Direction.AxisDirection.POSITIVE, axis); + return setRotationAxis(orientation.step()); + } + + public RotatingInstance setRotationAxis(Vector3f axis) { + return setRotationAxis(axis.x(), axis.y(), axis.z()); } public RotatingInstance setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) { @@ -31,4 +112,45 @@ public class RotatingInstance extends KineticInstance { return this; } + public RotatingInstance setPosition(Vec3i pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } + + public RotatingInstance setPosition(Vector3f pos) { + return setPosition(pos.x(), pos.y(), pos.z()); + } + + public RotatingInstance setPosition(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } + + public RotatingInstance nudge(float x, float y, float z) { + this.x += x; + this.y += y; + this.z += z; + return this; + } + + public RotatingInstance setColor(KineticBlockEntity blockEntity) { + colorRgb(colorFromBE(blockEntity)); + return this; + } + + public RotatingInstance setColor(Color c) { + color(c.getRed(), c.getGreen(), c.getBlue()); + return this; + } + + public RotatingInstance setRotationalSpeed(float rotationalSpeed) { + this.rotationalSpeed = rotationalSpeed; + return this; + } + + public RotatingInstance setRotationOffset(float rotationOffset) { + this.rotationOffset = rotationOffset; + return this; + } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticle.java b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticle.java index 70aa4b0281..66eeaad9d6 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticle.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticle.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.kinetics.base; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.content.equipment.goggles.GogglesItem; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticleData.java b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticleData.java index 7a249f6989..5cc799074d 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticleData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticleData.java @@ -17,6 +17,7 @@ import net.minecraft.core.Direction.Axis; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.network.FriendlyByteBuf; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -24,7 +25,7 @@ public class RotationIndicatorParticleData implements ParticleOptions, ICustomParticleDataWithSprite { // TODO 1.16 make this unnecessary - public static final PrimitiveCodec CHAR = new PrimitiveCodec() { + public static final PrimitiveCodec CHAR = new PrimitiveCodec<>() { @Override public DataResult read(final DynamicOps ops, final T input) { return ops.getNumberValue(input) @@ -44,7 +45,7 @@ public class RotationIndicatorParticleData public static final Codec CODEC = RecordCodecBuilder.create(i -> i .group(Codec.INT.fieldOf("color") - .forGetter(p -> p.color), + .forGetter(p -> p.color), Codec.FLOAT.fieldOf("speed") .forGetter(p -> p.speed), Codec.FLOAT.fieldOf("radius1") @@ -58,9 +59,9 @@ public class RotationIndicatorParticleData .apply(i, RotationIndicatorParticleData::new)); public static final ParticleOptions.Deserializer DESERIALIZER = - new ParticleOptions.Deserializer() { + new ParticleOptions.Deserializer<>() { public RotationIndicatorParticleData fromCommand(ParticleType particleTypeIn, - StringReader reader) throws CommandSyntaxException { + StringReader reader) throws CommandSyntaxException { reader.expect(' '); int color = reader.readInt(); reader.expect(' '); @@ -77,7 +78,7 @@ public class RotationIndicatorParticleData } public RotationIndicatorParticleData fromNetwork(ParticleType particleTypeIn, - FriendlyByteBuf buffer) { + FriendlyByteBuf buffer) { return new RotationIndicatorParticleData(buffer.readInt(), buffer.readFloat(), buffer.readFloat(), buffer.readFloat(), buffer.readInt(), buffer.readChar()); } @@ -91,7 +92,7 @@ public class RotationIndicatorParticleData final char axis; public RotationIndicatorParticleData(int color, float speed, float radius1, float radius2, int lifeSpan, - char axis) { + char axis) { this.color = color; this.speed = speed; this.radius1 = radius1; @@ -145,4 +146,4 @@ public class RotationIndicatorParticleData return RotationIndicatorParticle.Factory::new; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/ShaftVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/ShaftVisual.java index 1c4666886e..1d2c036088 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/ShaftVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/ShaftVisual.java @@ -1,18 +1,12 @@ package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.foundation.render.VirtualRenderHelper; +import com.simibubi.create.AllPartialModels; -import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.model.Models; -public class ShaftVisual extends SingleRotatingVisual { - +public class ShaftVisual extends SingleAxisRotatingVisual { public ShaftVisual(VisualizationContext context, T blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Model model() { - return VirtualRenderHelper.blockModel(shaft()); + super(context, blockEntity, partialTick, Models.partial(AllPartialModels.SHAFT)); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/SingleAxisRotatingVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/SingleAxisRotatingVisual.java new file mode 100644 index 0000000000..5cdd4bc1b9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/SingleAxisRotatingVisual.java @@ -0,0 +1,84 @@ +package com.simibubi.create.content.kinetics.base; + +import java.util.function.Consumer; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.equipment.armor.BacktankRenderer; +import com.simibubi.create.foundation.render.AllInstanceTypes; + +import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.model.Models; +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import dev.engine_room.flywheel.lib.visualization.SimpleBlockEntityVisualizer; +import net.minecraft.core.Direction; + +public class SingleAxisRotatingVisual extends KineticBlockEntityVisual { + + protected final RotatingInstance rotatingModel; + + public SingleAxisRotatingVisual(VisualizationContext context, T blockEntity, float partialTick, Model model) { + this(context, blockEntity, partialTick, Direction.UP, model); + } + + /** + * @param from The source model orientation to rotate away from. + * @param model The model to spin. + */ + public SingleAxisRotatingVisual(VisualizationContext context, T blockEntity, float partialTick, Direction from, Model model) { + super(context, blockEntity, partialTick); + rotatingModel = instancerProvider().instancer(AllInstanceTypes.ROTATING, model) + .createInstance() + .rotateToFace(from, rotationAxis()) + .setup(blockEntity) + .setPosition(getVisualPosition()); + + rotatingModel.setChanged(); + } + + public static SimpleBlockEntityVisualizer.Factory of(PartialModel partial) { + return (context, blockEntity, partialTick) -> { + return new SingleAxisRotatingVisual<>(context, blockEntity, partialTick, Models.partial(partial)); + }; + } + + /** + * For partial models whose source model is aligned with the Z axis instead of Y + */ + public static SimpleBlockEntityVisualizer.Factory ofZ(PartialModel partial) { + return (context, blockEntity, partialTick) -> { + return new SingleAxisRotatingVisual<>(context, blockEntity, partialTick, Direction.SOUTH, Models.partial(partial)); + }; + } + + public static SingleAxisRotatingVisual shaft(VisualizationContext context, T blockEntity, float partialTick) { + return new SingleAxisRotatingVisual<>(context, blockEntity, partialTick, Models.partial(AllPartialModels.SHAFT)); + } + + public static SingleAxisRotatingVisual backtank(VisualizationContext context, T blockEntity, float partialTick) { + var model = Models.partial(BacktankRenderer.getShaftModel(blockEntity.getBlockState())); + return new SingleAxisRotatingVisual<>(context, blockEntity, partialTick, model); + } + + @Override + public void update(float pt) { + rotatingModel.setup(blockEntity) + .setChanged(); + } + + @Override + public void updateLight(float partialTick) { + relight(rotatingModel); + } + + @Override + protected void _delete() { + rotatingModel.delete(); + } + + @Override + public void collectCrumblingInstances(Consumer consumer) { + consumer.accept(rotatingModel); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/SingleRotatingVisual.java b/src/main/java/com/simibubi/create/content/kinetics/base/SingleRotatingVisual.java deleted file mode 100644 index 84cc91d047..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/base/SingleRotatingVisual.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.simibubi.create.content.kinetics.base; - -import java.util.function.Consumer; - -import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.render.VirtualRenderHelper; - -import dev.engine_room.flywheel.api.instance.Instance; -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; - -public class SingleRotatingVisual extends KineticBlockEntityVisual { - - protected RotatingInstance rotatingModel; - - public SingleRotatingVisual(VisualizationContext context, T blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - rotatingModel = instancerProvider().instancer(AllInstanceTypes.ROTATING, model()) - .createInstance(); - setup(rotatingModel); - } - - @Override - public void update(float pt) { - updateRotation(rotatingModel); - } - - @Override - public void updateLight(float partialTick) { - relight(rotatingModel); - } - - @Override - protected void _delete() { - rotatingModel.delete(); - } - - protected Model model() { - return VirtualRenderHelper.blockModel(blockState); - } - - @Override - public void collectCrumblingInstances(Consumer consumer) { - consumer.accept(rotatingModel); - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlock.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlock.java index c373d7933e..c0e31bb0d3 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlock.java @@ -12,8 +12,8 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.equipment.armor.DivingBootsItem; import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; @@ -24,17 +24,20 @@ import com.simibubi.create.content.kinetics.belt.BeltSlicer.Feedback; import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; import com.simibubi.create.content.kinetics.belt.transport.BeltMovementHandler.TransportedEntityInfo; import com.simibubi.create.content.kinetics.belt.transport.BeltTunnelInteractionHandler; +import com.simibubi.create.content.logistics.box.PackageEntity; +import com.simibubi.create.content.logistics.box.PackageItem; import com.simibubi.create.content.logistics.funnel.FunnelBlock; import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.render.MultiPosDestructionHandler; import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; -import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.item.ItemHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -46,6 +49,7 @@ import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; @@ -79,10 +83,12 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientBlockExtensions; @@ -91,7 +97,7 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.items.IItemHandler; public class BeltBlock extends HorizontalKineticBlock - implements IBE, ISpecialBlockItemRequirement, ITransformableBlock, ProperWaterloggedBlock { + implements IBE, SpecialBlockItemRequirement, TransformableBlock, ProperWaterloggedBlock { public static final Property SLOPE = EnumProperty.create("slope", BeltSlope.class); public static final Property PART = EnumProperty.create("part", BeltPart.class); @@ -135,7 +141,7 @@ public class BeltBlock extends HorizontalKineticBlock @Override public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, - Player player) { + Player player) { return AllItems.BELT_CONNECTOR.asStack(); } @@ -185,9 +191,8 @@ public class BeltBlock extends HorizontalKineticBlock public void entityInside(BlockState state, Level worldIn, BlockPos pos, Entity entityIn) { if (!canTransportObjects(state)) return; - if (entityIn instanceof Player) { - Player player = (Player) entityIn; - if (player.isShiftKeyDown()) + if (entityIn instanceof Player player) { + if (player.isShiftKeyDown() && !AllItems.CARDBOARD_BOOTS.isIn(player.getItemBySlot(EquipmentSlot.FEET))) return; if (player.getAbilities().flying) return; @@ -199,26 +204,27 @@ public class BeltBlock extends HorizontalKineticBlock BeltBlockEntity belt = BeltHelper.getSegmentBE(worldIn, pos); if (belt == null) return; - if (entityIn instanceof ItemEntity && entityIn.isAlive()) { + ItemStack asItem = ItemHelper.fromItemEntity(entityIn); + if (!asItem.isEmpty()) { if (worldIn.isClientSide) return; if (entityIn.getDeltaMovement().y > 0) return; - if (!entityIn.isAlive()) + Vec3 targetLocation = VecHelper.getCenterOf(pos) + .add(0, 5 / 16f, 0); + if (!PackageEntity.centerPackage(entityIn, targetLocation)) return; if (BeltTunnelInteractionHandler.getTunnelOnPosition(worldIn, pos) != null) return; withBlockEntityDo(worldIn, pos, be -> { - ItemEntity itemEntity = (ItemEntity) entityIn; IItemHandler handler = be.getCapability(ForgeCapabilities.ITEM_HANDLER) .orElse(null); if (handler == null) return; - ItemStack remainder = handler.insertItem(0, itemEntity.getItem() - .copy(), false); + ItemStack remainder = handler.insertItem(0, asItem, false); if (remainder.isEmpty()) - itemEntity.discard(); - else if (remainder.getCount() != itemEntity.getItem().getCount()) + entityIn.discard(); + else if (entityIn instanceof ItemEntity itemEntity && remainder.getCount() != itemEntity.getItem().getCount()) itemEntity.setItem(remainder); }); return; @@ -246,7 +252,7 @@ public class BeltBlock extends HorizontalKineticBlock @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { + BlockHitResult hit) { if (player.isShiftKeyDown() || !player.mayBuild()) return InteractionResult.PASS; ItemStack heldItem = player.getItemInHand(handIn); @@ -274,6 +280,19 @@ public class BeltBlock extends HorizontalKineticBlock if (belt == null) return InteractionResult.PASS; + if (PackageItem.isPackage(heldItem)) { + ItemStack toInsert = heldItem.copy(); + IItemHandler handler = belt.getCapability(ForgeCapabilities.ITEM_HANDLER) + .orElse(null); + if (handler == null) + return InteractionResult.PASS; + ItemStack remainder = handler.insertItem(0, toInsert, false); + if (remainder.isEmpty()) { + heldItem.shrink(1); + return InteractionResult.SUCCESS; + } + } + if (isHand) { BeltBlockEntity controllerBelt = belt.getControllerBE(); if (controllerBelt == null) @@ -290,7 +309,7 @@ public class BeltBlock extends HorizontalKineticBlock }); if (success.isTrue()) world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f, - 1f + Create.RANDOM.nextFloat()); + 1f + world.random.nextFloat()); } if (isShaft) { @@ -383,18 +402,18 @@ public class BeltBlock extends HorizontalKineticBlock return shape; return getBlockEntityOptional(worldIn, pos).map(be -> { - Entity entity = ((EntityCollisionContext) context).getEntity(); - if (entity == null) + Entity entity = ((EntityCollisionContext) context).getEntity(); + if (entity == null) + return shape; + + BeltBlockEntity controller = be.getControllerBE(); + if (controller == null) + return shape; + if (controller.passengers == null || !controller.passengers.containsKey(entity)) + return BeltShapes.getCollisionShape(state); return shape; - BeltBlockEntity controller = be.getControllerBE(); - if (controller == null) - return shape; - if (controller.passengers == null || !controller.passengers.containsKey(entity)) - return BeltShapes.getCollisionShape(state); - return shape; - - }) + }) .orElse(shape); } @@ -442,8 +461,7 @@ public class BeltBlock extends HorizontalKineticBlock BlockEntity blockEntity = world.getBlockEntity(beltPos); BlockState currentState = world.getBlockState(beltPos); - if (blockEntity instanceof BeltBlockEntity && AllBlocks.BELT.has(currentState)) { - BeltBlockEntity be = (BeltBlockEntity) blockEntity; + if (blockEntity instanceof BeltBlockEntity be && AllBlocks.BELT.has(currentState)) { be.setController(currentPos); be.beltLength = beltChain.size(); be.index = index; @@ -466,7 +484,7 @@ public class BeltBlock extends HorizontalKineticBlock @Override public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { super.onRemove(state, world, pos, newState, isMoving); - + if (world.isClientSide) return; if (state.getBlock() == newState.getBlock()) @@ -485,8 +503,7 @@ public class BeltBlock extends HorizontalKineticBlock boolean hasPulley = false; BlockEntity blockEntity = world.getBlockEntity(currentPos); - if (blockEntity instanceof BeltBlockEntity) { - BeltBlockEntity belt = (BeltBlockEntity) blockEntity; + if (blockEntity instanceof BeltBlockEntity belt) { if (belt.isController()) belt.getInventory() .ejectAll(); @@ -505,7 +522,7 @@ public class BeltBlock extends HorizontalKineticBlock @Override public BlockState updateShape(BlockState state, Direction side, BlockState p_196271_3_, LevelAccessor world, - BlockPos pos, BlockPos p_196271_6_) { + BlockPos pos, BlockPos p_196271_6_) { updateWater(world, state, pos); if (side.getAxis() .isHorizontal()) @@ -521,7 +538,7 @@ public class BeltBlock extends HorizontalKineticBlock if (state.getValue(CASING) && state.getValue(SLOPE) == BeltSlope.HORIZONTAL) withBlockEntityDo(world, pos, bbe -> bbe.setCovered(isBlockCoveringBelt(world, pos.above()))); } - + public static boolean isBlockCoveringBelt(LevelAccessor world, BlockPos pos) { BlockState blockState = world.getBlockState(pos); VoxelShape collisionShape = blockState.getCollisionShape(world, pos); @@ -548,7 +565,7 @@ public class BeltBlock extends HorizontalKineticBlock ((BeltTunnelBlock) tunnelBlock).updateTunnel(world, pos); } - public static List getBeltChain(Level world, BlockPos controllerPos) { + public static List getBeltChain(LevelAccessor world, BlockPos controllerPos) { List positions = new LinkedList<>(); BlockState blockState = world.getBlockState(controllerPos); @@ -615,7 +632,7 @@ public class BeltBlock extends HorizontalKineticBlock return rotate; if (state.getValue(HORIZONTAL_FACING) .getAxisDirection() != rotate.getValue(HORIZONTAL_FACING) - .getAxisDirection()) { + .getAxisDirection()) { if (state.getValue(PART) == BeltPart.START) return rotate.setValue(PART, BeltPart.END); if (state.getValue(PART) == BeltPart.END) @@ -723,7 +740,7 @@ public class BeltBlock extends HorizontalKineticBlock public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { return false; } - + @Override public FluidState getFluidState(BlockState pState) { return fluidState(pState); diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlockEntity.java index fc6156d558..bc1bd8d013 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlockEntity.java @@ -27,8 +27,8 @@ import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -45,6 +45,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; @@ -389,7 +390,7 @@ public class BeltBlockEntity extends KineticBlockEntity { } private void applyToAllItems(float maxDistanceFromCenter, - Function processFunction) { + Function processFunction) { BeltBlockEntity controller = getControllerBE(); if (controller == null) return; @@ -472,8 +473,7 @@ public class BeltBlockEntity extends KineticBlockEntity { return inserted; BlockEntity teAbove = level.getBlockEntity(worldPosition.above()); - if (teAbove instanceof BrassTunnelBlockEntity) { - BrassTunnelBlockEntity tunnelBE = (BrassTunnelBlockEntity) teAbove; + if (teAbove instanceof BrassTunnelBlockEntity tunnelBE) { if (tunnelBE.hasDistributionBehaviour()) { if (!tunnelBE.getStackToDistribute() .isEmpty()) @@ -501,11 +501,16 @@ public class BeltBlockEntity extends KineticBlockEntity { .isVertical()) { if (movementFacing != side) { transportedStack.sideOffset = side.getAxisDirection() - .getStep() * .35f; + .getStep() * .675f; if (side.getAxis() == Axis.X) transportedStack.sideOffset *= -1; - } else - transportedStack.beltPosition = getDirectionAwareBeltMovementSpeed() > 0 ? index : index + 1; + } else { + float extraOffset = + BeltHelper.getSegmentBE(level, worldPosition.relative(movementFacing.getOpposite())) != null ? .26f + : 0; + transportedStack.beltPosition = + getDirectionAwareBeltMovementSpeed() > 0 ? index - extraOffset : index + 1 + extraOffset; + } } transportedStack.prevSideOffset = transportedStack.sideOffset; @@ -537,7 +542,7 @@ public class BeltBlockEntity extends KineticBlockEntity { @Override public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, - boolean connectedViaAxes, boolean connectedViaCogs) { + boolean connectedViaAxes, boolean connectedViaCogs) { if (target instanceof BeltBlockEntity && !connectedViaAxes) return getController().equals(((BeltBlockEntity) target).getController()) ? 1 : 0; return 0; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltHelper.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltHelper.java index 1293c230d3..40edc1c8f0 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltHelper.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltHelper.java @@ -3,9 +3,9 @@ package com.simibubi.create.content.kinetics.belt; import java.util.Map; import com.simibubi.create.AllTags.AllItemTags; -import com.simibubi.create.foundation.utility.VecHelper; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltInstance.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltInstance.java deleted file mode 100644 index 1359862b63..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltInstance.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.simibubi.create.content.kinetics.belt; - -import org.joml.Quaternionf; -import org.joml.Quaternionfc; - -import com.simibubi.create.content.kinetics.base.KineticInstance; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; - -import dev.engine_room.flywheel.api.instance.InstanceHandle; -import dev.engine_room.flywheel.api.instance.InstanceType; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; - -public class BeltInstance extends KineticInstance { - public final Quaternionf rotation = new Quaternionf(); - public float sourceU; - public float sourceV; - public float minU; - public float minV; - public float maxU; - public float maxV; - public float scrollMult; - - public BeltInstance(InstanceType type, InstanceHandle handle) { - super(type, handle); - } - - public BeltInstance setRotation(Quaternionfc q) { - this.rotation.set(q); - return this; - } - - public BeltInstance setScrollTexture(SpriteShiftEntry spriteShift) { - TextureAtlasSprite source = spriteShift.getOriginal(); - TextureAtlasSprite target = spriteShift.getTarget(); - - this.sourceU = source.getU0(); - this.sourceV = source.getV0(); - this.minU = target.getU0(); - this.minV = target.getV0(); - this.maxU = target.getU1(); - this.maxV = target.getV1(); - - return this; - } - - public BeltInstance setScrollMult(float scrollMult) { - this.scrollMult = scrollMult; - return this; - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltModel.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltModel.java index e80256677d..7dc919bb07 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltModel.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltModel.java @@ -6,9 +6,9 @@ import java.util.List; import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity.CasingType; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.model.BakedQuadHelper; +import net.createmod.catnip.render.SpriteShiftEntry; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -31,7 +31,7 @@ public class BeltModel extends BakedModelWrapper { public BeltModel(BakedModel template) { super(template); } - + @Override public TextureAtlasSprite getParticleIcon(ModelData data) { if (!data.has(CASING_PROPERTY)) @@ -47,11 +47,11 @@ public class BeltModel extends BakedModelWrapper { List quads = super.getQuads(state, side, rand, extraData, renderType); if (!extraData.has(CASING_PROPERTY)) return quads; - + boolean cover = extraData.get(COVER_PROPERTY); CasingType type = extraData.get(CASING_PROPERTY); boolean brassCasing = type == CasingType.BRASS; - + if (type == CasingType.NONE || brassCasing && !cover) return quads; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltPart.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltPart.java index 537e4e2cd7..370245ea12 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltPart.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltPart.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.kinetics.belt; -import com.simibubi.create.foundation.utility.Lang; - +import net.createmod.catnip.lang.Lang; import net.minecraft.util.StringRepresentable; public enum BeltPart implements StringRepresentable { @@ -11,4 +10,4 @@ public enum BeltPart implements StringRepresentable { public String getSerializedName() { return Lang.asId(name()); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltRenderer.java index 35f251a082..68c10ce112 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltRenderer.java @@ -10,28 +10,30 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.belt.transport.BeltInventory; import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.content.logistics.box.PackageItem; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.ShadowRenderHelper; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.levelWrappers.WrappedLevel; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.core.Vec3i; @@ -44,8 +46,7 @@ import net.minecraft.world.phys.Vec3; public class BeltRenderer extends SafeBlockEntityRenderer { - public BeltRenderer(BlockEntityRendererProvider.Context context) { - } + public BeltRenderer(BlockEntityRendererProvider.Context context) {} @Override public boolean shouldRenderOffScreen(BeltBlockEntity be) { @@ -53,13 +54,14 @@ public class BeltRenderer extends SafeBlockEntityRenderer { } @Override - protected void renderSafe(BeltBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { + protected void renderSafe(BeltBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { if (!VisualizationManager.supportsVisualization(be.getLevel())) { BlockState blockState = be.getBlockState(); - if (!AllBlocks.BELT.has(blockState)) return; + if (!AllBlocks.BELT.has(blockState)) + return; BeltSlope beltSlope = blockState.getValue(BeltBlock.SLOPE); BeltPart part = blockState.getValue(BeltBlock.PART); @@ -75,7 +77,7 @@ public class BeltRenderer extends SafeBlockEntityRenderer { boolean alongX = facing.getAxis() == Direction.Axis.X; PoseStack localTransforms = new PoseStack(); - var msr = TransformStack.of(localTransforms); + var msr = TransformStack.of(localTransforms); VertexConsumer vb = buffer.getBuffer(RenderType.solid()); float renderTick = AnimationTickHolder.getRenderTime(be.getLevel()); @@ -97,8 +99,8 @@ public class BeltRenderer extends SafeBlockEntityRenderer { PartialModel beltPartial = getBeltPartial(diagonal, start, end, bottom); - SuperByteBuffer beltBuffer = CachedBufferer.partial(beltPartial, blockState) - .light(light); + SuperByteBuffer beltBuffer = CachedBuffers.partial(beltPartial, blockState) + .light(light); SpriteShiftEntry spriteShift = getSpriteShiftEntry(color, diagonal, bottom); @@ -106,12 +108,16 @@ public class BeltRenderer extends SafeBlockEntityRenderer { float speed = be.getSpeed(); if (speed != 0 || be.color.isPresent()) { float time = renderTick * axisDirection.getStep(); - if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX || sideways && axisDirection == AxisDirection.NEGATIVE) + if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX + || sideways && axisDirection == AxisDirection.NEGATIVE) speed = -speed; float scrollMult = diagonal ? 3f / 8f : 0.5f; - float spriteSize = spriteShift.getTarget().getV1() - spriteShift.getTarget().getV0(); + float spriteSize = spriteShift.getTarget() + .getV1() + - spriteShift.getTarget() + .getV0(); double scroll = speed * time / (31.5 * 16) + (bottom ? 0.5 : 0.0); scroll = scroll - Math.floor(scroll); @@ -121,19 +127,22 @@ public class BeltRenderer extends SafeBlockEntityRenderer { } beltBuffer - .transform(localTransforms) - .renderInto(ms, vb); + .transform(localTransforms) + .renderInto(ms, vb); // Diagonal belt do not have a separate bottom model - if (diagonal) break; + if (diagonal) + break; } if (be.hasPulley()) { - Direction dir = sideways ? Direction.UP : blockState.getValue(BeltBlock.HORIZONTAL_FACING).getClockWise(); + Direction dir = sideways ? Direction.UP + : blockState.getValue(BeltBlock.HORIZONTAL_FACING) + .getClockWise(); Supplier matrixStackSupplier = () -> { PoseStack stack = new PoseStack(); - var stacker = TransformStack.of(stack); + var stacker = TransformStack.of(stack); stacker.center(); if (dir.getAxis() == Direction.Axis.X) stacker.rotateYDegrees(90); if (dir.getAxis() == Direction.Axis.Y) stacker.rotateXDegrees(90); @@ -142,8 +151,10 @@ public class BeltRenderer extends SafeBlockEntityRenderer { return stack; }; - SuperByteBuffer superBuffer = CachedBufferer.partialDirectional(AllPartialModels.BELT_PULLEY, blockState, dir, matrixStackSupplier); - KineticBlockEntityRenderer.standardKineticRotationTransform(superBuffer, be, light).renderInto(ms, vb); + SuperByteBuffer superBuffer = CachedBuffers.partialDirectional(AllPartialModels.BELT_PULLEY, + blockState, dir, matrixStackSupplier); + KineticBlockEntityRenderer.standardKineticRotationTransform(superBuffer, be, light) + .renderInto(ms, vb); } } @@ -153,24 +164,30 @@ public class BeltRenderer extends SafeBlockEntityRenderer { public static SpriteShiftEntry getSpriteShiftEntry(DyeColor color, boolean diagonal, boolean bottom) { if (color != null) { return (diagonal ? AllSpriteShifts.DYED_DIAGONAL_BELTS - : bottom ? AllSpriteShifts.DYED_OFFSET_BELTS : AllSpriteShifts.DYED_BELTS).get(color); + : bottom ? AllSpriteShifts.DYED_OFFSET_BELTS : AllSpriteShifts.DYED_BELTS).get(color); } else return diagonal ? AllSpriteShifts.BELT_DIAGONAL - : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT; + : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT; } public static PartialModel getBeltPartial(boolean diagonal, boolean start, boolean end, boolean bottom) { if (diagonal) { - if (start) return AllPartialModels.BELT_DIAGONAL_START; - if (end) return AllPartialModels.BELT_DIAGONAL_END; + if (start) + return AllPartialModels.BELT_DIAGONAL_START; + if (end) + return AllPartialModels.BELT_DIAGONAL_END; return AllPartialModels.BELT_DIAGONAL_MIDDLE; } else if (bottom) { - if (start) return AllPartialModels.BELT_START_BOTTOM; - if (end) return AllPartialModels.BELT_END_BOTTOM; + if (start) + return AllPartialModels.BELT_START_BOTTOM; + if (end) + return AllPartialModels.BELT_END_BOTTOM; return AllPartialModels.BELT_MIDDLE_BOTTOM; } else { - if (start) return AllPartialModels.BELT_START; - if (end) return AllPartialModels.BELT_END; + if (start) + return AllPartialModels.BELT_START; + if (end) + return AllPartialModels.BELT_END; return AllPartialModels.BELT_MIDDLE; } } @@ -185,151 +202,157 @@ public class BeltRenderer extends SafeBlockEntityRenderer { ms.pushPose(); Direction beltFacing = be.getBeltFacing(); - Vec3i directionVec = beltFacing - .getNormal(); - Vec3 beltStartOffset = Vec3.atLowerCornerOf(directionVec).scale(-.5) + Vec3i directionVec = beltFacing.getNormal(); + Vec3 beltStartOffset = Vec3.atLowerCornerOf(directionVec) + .scale(-.5) .add(.5, 15 / 16f, .5); ms.translate(beltStartOffset.x, beltStartOffset.y, beltStartOffset.z); BeltSlope slope = be.getBlockState() .getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - boolean slopeAlongX = beltFacing - .getAxis() == Direction.Axis.X; - MutableBlockPos mutablePos = new MutableBlockPos(); + boolean slopeAlongX = beltFacing.getAxis() == Direction.Axis.X; + boolean onContraption = be.getLevel() instanceof WrappedLevel; + BeltInventory inventory = be.getInventory(); + for (TransportedItemStack transported : inventory.getTransportedItems()) + renderItem(be, partialTicks, ms, buffer, light, overlay, beltFacing, directionVec, slope, verticality, + slopeAlongX, onContraption, transported, beltStartOffset); + if (inventory.getLazyClientItem() != null) + renderItem(be, partialTicks, ms, buffer, light, overlay, beltFacing, directionVec, slope, verticality, + slopeAlongX, onContraption, inventory.getLazyClientItem(), beltStartOffset); + + ms.popPose(); + } + + private void renderItem(BeltBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + int overlay, Direction beltFacing, Vec3i directionVec, BeltSlope slope, int verticality, boolean slopeAlongX, + boolean onContraption, TransportedItemStack transported, Vec3 beltStartOffset) { Minecraft mc = Minecraft.getInstance(); ItemRenderer itemRenderer = mc.getItemRenderer(); - boolean onContraption = be.getLevel() instanceof WrappedWorld; + MutableBlockPos mutablePos = new MutableBlockPos(); - for (TransportedItemStack transported : be.getInventory() - .getTransportedItems()) { - ms.pushPose(); - TransformStack.of(ms) - .nudge(transported.angle); + float offset = Mth.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition); + float sideOffset = Mth.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset); + float verticalMovement = verticality; - float offset; - float sideOffset; - float verticalMovement; - - if (be.getSpeed() == 0) { - offset = transported.beltPosition; - sideOffset = transported.sideOffset; - } else { - offset = Mth.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition); - sideOffset = Mth.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset); - } - - if (offset < .5) - verticalMovement = 0; - else - verticalMovement = verticality * (Math.min(offset, be.beltLength - .5f) - .5f); - Vec3 offsetVec = Vec3.atLowerCornerOf(directionVec).scale(offset); - if (verticalMovement != 0) - offsetVec = offsetVec.add(0, verticalMovement, 0); - boolean onSlope = - slope != BeltSlope.HORIZONTAL && Mth.clamp(offset, .5f, be.beltLength - .5f) == offset; - boolean tiltForward = (slope == BeltSlope.DOWNWARD ^ beltFacing - .getAxisDirection() == AxisDirection.POSITIVE) == (beltFacing - .getAxis() == Direction.Axis.Z); - float slopeAngle = onSlope ? tiltForward ? -45 : 45 : 0; - - Vec3 itemPos = beltStartOffset.add( - be.getBlockPos().getX(), - be.getBlockPos().getY(), - be.getBlockPos().getZ()) - .add(offsetVec); - - if (this.shouldCullItem(itemPos, be.getLevel())) { - continue; - } - - ms.pushPose(); - TransformStack.of(ms).nudge(transported.angle); - ms.translate(offsetVec.x, offsetVec.y, offsetVec.z); - - boolean alongX = beltFacing - .getClockWise() - .getAxis() == Direction.Axis.X; - if (!alongX) - sideOffset *= -1; - ms.translate(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset); - - int stackLight; - if (onContraption) { - stackLight = light; - } else { - int segment = (int) Math.floor(offset); - mutablePos.set(be.getBlockPos()).move(directionVec.getX() * segment, verticality * segment, directionVec.getZ() * segment); - stackLight = LevelRenderer.getLightColor(be.getLevel(), mutablePos); - } - - boolean renderUpright = BeltHelper.isItemUpright(transported.stack); - BakedModel bakedModel = itemRenderer.getModel(transported.stack, be.getLevel(), null, 0); - boolean blockItem = bakedModel.isGui3d(); - - int count = 0; - if (mc.player.getEyePosition(1.0F).distanceTo(itemPos) < 16) - count = (int) (Mth.log2((int) (transported.stack.getCount()))) / 2; - - Random r = new Random(transported.angle); - - boolean slopeShadowOnly = renderUpright && onSlope; - float slopeOffset = 1 / 8f; - if (slopeShadowOnly) - ms.pushPose(); - if (!renderUpright || slopeShadowOnly) - ms.mulPose((slopeAlongX ? Axis.ZP : Axis.XP).rotationDegrees(slopeAngle)); - if (onSlope) - ms.translate(0, slopeOffset, 0); - ms.pushPose(); - ms.translate(0, -1 / 8f + 0.005f, 0); - ShadowRenderHelper.renderShadow(ms, buffer, .75f, .2f); - ms.popPose(); - if (slopeShadowOnly) { - ms.popPose(); - ms.translate(0, slopeOffset, 0); - } - - if (renderUpright) { - Entity renderViewEntity = mc.cameraEntity; - if (renderViewEntity != null) { - Vec3 positionVec = renderViewEntity.position(); - Vec3 vectorForOffset = BeltHelper.getVectorForOffset(be, offset); - Vec3 diff = vectorForOffset.subtract(positionVec); - float yRot = (float) (Mth.atan2(diff.x, diff.z) + Math.PI); - ms.mulPose(Axis.YP.rotation(yRot)); - } - ms.translate(0, 3 / 32d, 1 / 16f); - } - - for (int i = 0; i <= count; i++) { - ms.pushPose(); - - ms.mulPose(Axis.YP.rotationDegrees(transported.angle)); - if (!blockItem && !renderUpright) { - ms.translate(0, -.09375, 0); - ms.mulPose(Axis.XP.rotationDegrees(90)); - } - - if (blockItem) { - ms.translate(r.nextFloat() * .0625f * i, 0, r.nextFloat() * .0625f * i); - } - - ms.scale(.5f, .5f, .5f); - itemRenderer.render(transported.stack, ItemDisplayContext.FIXED, false, ms, buffer, stackLight, overlay, bakedModel); - ms.popPose(); - - if (!renderUpright) { - if (!blockItem) - ms.mulPose(Axis.YP.rotationDegrees(10)); - ms.translate(0, blockItem ? 1 / 64d : 1 / 16d, 0); - } else - ms.translate(0, 0, -1 / 16f); - - } - - ms.popPose(); + if (be.getSpeed() == 0) { + offset = transported.beltPosition; + sideOffset = transported.sideOffset; } + + if (offset < .5) + verticalMovement = 0; + else + verticalMovement = verticality * (Math.min(offset, be.beltLength - .5f) - .5f); + Vec3 offsetVec = Vec3.atLowerCornerOf(directionVec) + .scale(offset); + if (verticalMovement != 0) + offsetVec = offsetVec.add(0, verticalMovement, 0); + boolean onSlope = slope != BeltSlope.HORIZONTAL && Mth.clamp(offset, .5f, be.beltLength - .5f) == offset; + boolean tiltForward = (slope == BeltSlope.DOWNWARD + ^ beltFacing.getAxisDirection() == AxisDirection.POSITIVE) == (beltFacing.getAxis() == Direction.Axis.Z); + float slopeAngle = onSlope ? tiltForward ? -45 : 45 : 0; + + Vec3 itemPos = beltStartOffset.add( + be.getBlockPos().getX(), + be.getBlockPos().getY(), + be.getBlockPos().getZ()) + .add(offsetVec); + + if (this.shouldCullItem(itemPos, be.getLevel())) { + return; + } + + ms.pushPose(); + TransformStack.of(ms).nudge(transported.angle); + ms.translate(offsetVec.x, offsetVec.y, offsetVec.z); + + boolean alongX = beltFacing.getClockWise() + .getAxis() == Direction.Axis.X; + if (!alongX) + sideOffset *= -1; + ms.translate(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset); + + int stackLight; + if (onContraption) { + stackLight = light; + } else { + int segment = (int) Math.floor(offset); + mutablePos.set(be.getBlockPos()).move(directionVec.getX() * segment, verticality * segment, directionVec.getZ() * segment); + stackLight = LevelRenderer.getLightColor(be.getLevel(), mutablePos); + } + + boolean renderUpright = BeltHelper.isItemUpright(transported.stack); + BakedModel bakedModel = itemRenderer.getModel(transported.stack, be.getLevel(), null, 0); + boolean blockItem = bakedModel.isGui3d(); + + int count = 0; + if (mc.player.getEyePosition(1.0F).distanceTo(itemPos) < 16) + count = (int) (Mth.log2((int) (transported.stack.getCount()))) / 2; + + Random r = new Random(transported.angle); + + boolean slopeShadowOnly = renderUpright && onSlope; + float slopeOffset = 1 / 8f; + if (slopeShadowOnly) + ms.pushPose(); + if (!renderUpright || slopeShadowOnly) + ms.mulPose((slopeAlongX ? Axis.ZP : Axis.XP).rotationDegrees(slopeAngle)); + if (onSlope) + ms.translate(0, slopeOffset, 0); + ms.pushPose(); + ms.translate(0, -1 / 8f + 0.005f, 0); + ShadowRenderHelper.renderShadow(ms, buffer, .75f, .2f); + ms.popPose(); + if (slopeShadowOnly) { + ms.popPose(); + ms.translate(0, slopeOffset, 0); + } + + if (renderUpright) { + Entity renderViewEntity = mc.cameraEntity; + if (renderViewEntity != null) { + Vec3 positionVec = renderViewEntity.position(); + Vec3 vectorForOffset = BeltHelper.getVectorForOffset(be, offset); + Vec3 diff = vectorForOffset.subtract(positionVec); + float yRot = (float) (Mth.atan2(diff.x, diff.z) + Math.PI); + ms.mulPose(Axis.YP.rotation(yRot)); + } + ms.translate(0, 3 / 32d, 1 / 16f); + } + + for (int i = 0; i <= count; i++) { + ms.pushPose(); + + boolean box = PackageItem.isPackage(transported.stack); + ms.mulPose(Axis.YP.rotationDegrees(transported.angle)); + if (!blockItem && !renderUpright) { + ms.translate(0, -.09375, 0); + ms.mulPose(Axis.XP.rotationDegrees(90)); + } + + if (blockItem && !box) + ms.translate(r.nextFloat() * .0625f * i, 0, r.nextFloat() * .0625f * i); + + if (box) { + ms.translate(0, 4 / 16f, 0); + ms.scale(1.5f, 1.5f, 1.5f); + } else { + ms.scale(.5f, .5f, .5f); + } + + itemRenderer.render(transported.stack, ItemDisplayContext.FIXED, false, ms, buffer, stackLight, overlay, bakedModel); + ms.popPose(); + + if (!renderUpright) { + if (!blockItem) + ms.mulPose(Axis.YP.rotationDegrees(10)); + ms.translate(0, blockItem ? 1 / 64d : 1 / 16d, 0); + } else + ms.translate(0, 0, -1 / 16f); + + } + ms.popPose(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltShapes.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltShapes.java index c3129ee199..44b1201c8d 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltShapes.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltShapes.java @@ -6,8 +6,8 @@ import java.util.HashMap; import java.util.Map; import com.simibubi.create.AllShapes; -import com.simibubi.create.foundation.utility.VoxelShaper; +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.world.level.block.state.BlockState; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlicer.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlicer.java index 6fcaf8aa0e..e4885c66a1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlicer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlicer.java @@ -7,23 +7,23 @@ import java.util.Optional; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity.CasingType; import com.simibubi.create.content.kinetics.belt.item.BeltConnectorItem; import com.simibubi.create.content.kinetics.belt.transport.BeltInventory; import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; @@ -40,6 +40,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -53,7 +54,7 @@ public class BeltSlicer { } public static InteractionResult useWrench(BlockState state, Level world, BlockPos pos, Player player, - InteractionHand handIn, BlockHitResult hit, Feedback feedBack) { + InteractionHand handIn, BlockHitResult hit, Feedback feedBack) { BeltBlockEntity controllerBE = BeltHelper.getControllerBE(world, pos); if (controllerBE == null) return InteractionResult.PASS; @@ -162,7 +163,8 @@ public class BeltSlicer { int amountRetrieved = 0; boolean beltFound = false; - Search: while (true) { + Search: + while (true) { for (int i = 0; i < player.getInventory().getContainerSize(); ++i) { if (amountRetrieved == requiredShafts && beltFound) break Search; @@ -171,14 +173,14 @@ public class BeltSlicer { if (itemstack.isEmpty()) continue; int count = itemstack.getCount(); - + if (AllItems.BELT_CONNECTOR.isIn(itemstack)) { if (!world.isClientSide) itemstack.shrink(1); beltFound = true; continue; } - + if (AllBlocks.SHAFT.isIn(itemstack)) { int taken = Math.min(count, requiredShafts - amountRetrieved); if (!world.isClientSide) @@ -220,7 +222,7 @@ public class BeltSlicer { newController.inventory = null; newController.setController(newController.getBlockPos()); for (Iterator iterator = inventory.getTransportedItems() - .iterator(); iterator.hasNext();) { + .iterator(); iterator.hasNext(); ) { TransportedItemStack transportedItemStack = iterator.next(); float newPosition = transportedItemStack.beltPosition - hitSegment - (towardPositive ? 1 : 0); if (newPosition <= 0) @@ -237,7 +239,7 @@ public class BeltSlicer { } public static InteractionResult useConnector(BlockState state, Level world, BlockPos pos, Player player, - InteractionHand handIn, BlockHitResult hit, Feedback feedBack) { + InteractionHand handIn, BlockHitResult hit, Feedback feedBack) { BeltBlockEntity controllerBE = BeltHelper.getControllerBE(world, pos); if (controllerBE == null) return InteractionResult.PASS; @@ -399,16 +401,16 @@ public class BeltSlicer { BeltSlope slope2 = nextState.getValue(BeltBlock.SLOPE); switch (slope1) { - case UPWARD: - if (slope2 == BeltSlope.DOWNWARD) - return facing1 == facing2.getOpposite(); - return slope2 == slope1 && facing1 == facing2; - case DOWNWARD: - if (slope2 == BeltSlope.UPWARD) - return facing1 == facing2.getOpposite(); - return slope2 == slope1 && facing1 == facing2; - default: - return slope2 == slope1 && facing2.getAxis() == facing1.getAxis(); + case UPWARD: + if (slope2 == BeltSlope.DOWNWARD) + return facing1 == facing2.getOpposite(); + return slope2 == slope1 && facing1 == facing2; + case DOWNWARD: + if (slope2 == BeltSlope.UPWARD) + return facing1 == facing2.getOpposite(); + return slope2 == slope1 && facing1 == facing2; + default: + return slope2 == slope1 && facing2.getAxis() == facing1.getAxis(); } } @@ -447,10 +449,9 @@ public class BeltSlicer { public static void tickHoveringInformation() { Minecraft mc = Minecraft.getInstance(); HitResult target = mc.hitResult; - if (target == null || !(target instanceof BlockHitResult)) + if (target == null || !(target instanceof BlockHitResult result)) return; - BlockHitResult result = (BlockHitResult) target; ClientLevel world = mc.level; BlockPos pos = result.getBlockPos(); BlockState state = world.getBlockState(pos); @@ -473,13 +474,13 @@ public class BeltSlicer { return; if (feedback.langKey != null) - mc.player.displayClientMessage(Lang.translateDirect(feedback.langKey) + mc.player.displayClientMessage(CreateLang.translateDirect(feedback.langKey) .withStyle(feedback.formatting), true); else - mc.player.displayClientMessage(Components.immutableEmpty(), true); + mc.player.displayClientMessage(CommonComponents.EMPTY, true); if (feedback.bb != null) - CreateClient.OUTLINER.chaseAABB("BeltSlicer", feedback.bb) + Outliner.getInstance().chaseAABB("BeltSlicer", feedback.bb) .lineWidth(1 / 16f) .colored(feedback.color); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlope.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlope.java index 5e1f38908b..bd45112741 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlope.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlope.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.kinetics.belt; -import com.simibubi.create.foundation.utility.Lang; - +import net.createmod.catnip.lang.Lang; import net.minecraft.util.StringRepresentable; public enum BeltSlope implements StringRepresentable { @@ -15,4 +14,4 @@ public enum BeltSlope implements StringRepresentable { public boolean isDiagonal() { return this == UPWARD || this == DOWNWARD; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltVisual.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltVisual.java index 0a95b470e4..05f20ca30a 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltVisual.java @@ -1,135 +1,117 @@ package com.simibubi.create.content.kinetics.belt; -import java.util.ArrayList; import java.util.function.Consumer; +import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; import com.simibubi.create.content.kinetics.base.RotatingInstance; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.content.processing.burner.ScrollInstance; import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.Instancer; +import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.instance.AbstractInstance; -import dev.engine_room.flywheel.lib.instance.FlatLit; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.world.item.DyeColor; -import net.minecraft.world.level.LightLayer; public class BeltVisual extends KineticBlockEntityVisual { + public static final float MAGIC_SCROLL_MULTIPLIER = 1f / (31.5f * 16f); + public static final float SCROLL_FACTOR_DIAGONAL = 3f / 8f; + public static final float SCROLL_FACTOR_OTHERWISE = 0.5f; + public static final float SCROLL_OFFSET_BOTTOM = 0.5f; + public static final float SCROLL_OFFSET_OTHERWISE = 0f; - boolean upward; - boolean diagonal; - boolean sideways; - boolean vertical; - boolean alongX; - boolean alongZ; - BeltSlope beltSlope; - Direction facing; - protected ArrayList keys; - protected RotatingInstance pulleyKey; + protected final ScrollInstance[] belts; + @Nullable + protected final RotatingInstance pulley; public BeltVisual(VisualizationContext context, BeltBlockEntity blockEntity, float partialTick) { super(context, blockEntity, partialTick); - if (!AllBlocks.BELT.has(blockState)) - return; - keys = new ArrayList<>(2); + BeltPart part = blockState.getValue(BeltBlock.PART); + boolean start = part == BeltPart.START; + boolean end = part == BeltPart.END; + DyeColor color = blockEntity.color.orElse(null); - beltSlope = blockState.getValue(BeltBlock.SLOPE); - facing = blockState.getValue(BeltBlock.HORIZONTAL_FACING); - upward = beltSlope == BeltSlope.UPWARD; - diagonal = beltSlope.isDiagonal(); - sideways = beltSlope == BeltSlope.SIDEWAYS; - vertical = beltSlope == BeltSlope.VERTICAL; - alongX = facing.getAxis() == Direction.Axis.X; - alongZ = facing.getAxis() == Direction.Axis.Z; + boolean diagonal = blockState.getValue(BeltBlock.SLOPE) + .isDiagonal(); + belts = new ScrollInstance[diagonal ? 1 : 2]; - BeltPart part = blockState.getValue(BeltBlock.PART); - boolean start = part == BeltPart.START; - boolean end = part == BeltPart.END; - DyeColor color = blockEntity.color.orElse(null); - - for (boolean bottom : Iterate.trueAndFalse) { + for (boolean bottom : Iterate.trueAndFalse) { PartialModel beltPartial = BeltRenderer.getBeltPartial(diagonal, start, end, bottom); SpriteShiftEntry spriteShift = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom); - Instancer beltModel = instancerProvider().instancer(AllInstanceTypes.BELT, Models.partial(beltPartial)); + Instancer beltModel = instancerProvider().instancer(AllInstanceTypes.SCROLLING, Models.partial(beltPartial)); - keys.add(setup(beltModel.createInstance(), bottom, spriteShift)); + belts[bottom ? 0 : 1] = setup(beltModel.createInstance(), bottom, spriteShift); if (diagonal) break; } if (blockEntity.hasPulley()) { - Instancer pulleyModel = getPulleyModel(); + pulley = instancerProvider() + .instancer(AllInstanceTypes.ROTATING, getPulleyModel()) + .createInstance(); - pulleyKey = setup(pulleyModel.createInstance()); - } + pulley.setup(BeltVisual.this.blockEntity) + .setPosition(getVisualPosition()) + .setChanged(); + } else { + pulley = null; + } } @Override public void update(float pt) { DyeColor color = blockEntity.color.orElse(null); - boolean bottom = true; - for (BeltInstance key : keys) { + boolean diagonal = blockState.getValue(BeltBlock.SLOPE) + .isDiagonal(); - SpriteShiftEntry spriteShiftEntry = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom); - key.setScrollTexture(spriteShiftEntry) - .setColor(blockEntity) - .setRotationalSpeed(getScrollSpeed()) - .setChanged(); + boolean bottom = true; + for (ScrollInstance key : belts) { + setup(key, bottom, BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom)); bottom = false; } - if (pulleyKey != null) { - updateRotation(pulleyKey); - } + if (pulley != null) { + pulley.setup(blockEntity) + .setChanged(); + } } @Override public void updateLight(float partialTick) { - relight(keys.toArray(FlatLit[]::new)); + relight(belts); - if (pulleyKey != null) relight(pulleyKey); + if (pulley != null) relight(pulley); } @Override protected void _delete() { - keys.forEach(AbstractInstance::delete); - keys.clear(); - if (pulleyKey != null) pulleyKey.delete(); - pulleyKey = null; + for (var key : belts) { + key.delete(); + } + if (pulley != null) { + pulley.delete(); + } } - private float getScrollSpeed() { - float speed = blockEntity.getSpeed(); - if (((facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ^ upward) ^ - ((alongX && !diagonal) || (alongZ && diagonal))) { - speed = -speed; - } - if (sideways && (facing == Direction.SOUTH || facing == Direction.WEST) || (vertical && facing == Direction.EAST)) - speed = -speed; - - return speed; - } - - private Instancer getPulleyModel() { + private Model getPulleyModel() { Direction dir = getOrientation(); - var model = Models.partial(AllPartialModels.BELT_PULLEY, dir.getAxis(), (axis11, modelTransform1) -> { + return Models.partial(AllPartialModels.BELT_PULLEY, dir.getAxis(), (axis11, modelTransform1) -> { var msr = TransformStack.of(modelTransform1); msr.center(); if (axis11 == Direction.Axis.X) msr.rotateYDegrees(90); @@ -137,35 +119,50 @@ public class BeltVisual extends KineticBlockEntityVisual { msr.rotateXDegrees(90); msr.uncenter(); }); - - return instancerProvider().instancer(AllInstanceTypes.ROTATING, model); } private Direction getOrientation() { Direction dir = blockState.getValue(BeltBlock.HORIZONTAL_FACING) .getClockWise(); - if (beltSlope == BeltSlope.SIDEWAYS) + + if (blockState.getValue(BeltBlock.SLOPE) == BeltSlope.SIDEWAYS) dir = Direction.UP; return dir; } - private BeltInstance setup(BeltInstance key, boolean bottom, SpriteShiftEntry spriteShift) { + private ScrollInstance setup(ScrollInstance key, boolean bottom, SpriteShiftEntry spriteShift) { + BeltSlope beltSlope = blockState.getValue(BeltBlock.SLOPE); + Direction facing = blockState.getValue(BeltBlock.HORIZONTAL_FACING); + boolean diagonal = beltSlope.isDiagonal(); + boolean sideways = beltSlope == BeltSlope.SIDEWAYS; + boolean vertical = beltSlope == BeltSlope.VERTICAL; + boolean upward = beltSlope == BeltSlope.UPWARD; + boolean alongX = facing.getAxis() == Direction.Axis.X; + boolean alongZ = facing.getAxis() == Direction.Axis.Z; boolean downward = beltSlope == BeltSlope.DOWNWARD; + + float speed = blockEntity.getSpeed(); + if (((facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ^ upward) ^ + ((alongX && !diagonal) || (alongZ && diagonal))) { + speed = -speed; + } + if (sideways && (facing == Direction.SOUTH || facing == Direction.WEST) || (vertical && facing == Direction.EAST)) { + speed = -speed; + } + float rotX = (!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0) + (downward ? 180 : 0) + (sideways ? 90 : 0) + (vertical && alongZ ? 180 : 0); float rotY = facing.toYRot() + ((diagonal ^ alongX) && !downward ? 180 : 0) + (sideways && alongZ ? 180 : 0) + (vertical && alongX ? 90 : 0); float rotZ = (sideways ? 90 : 0) + (vertical && alongX ? 90 : 0); Quaternionf q = new Quaternionf().rotationXYZ(rotX * Mth.DEG_TO_RAD, rotY * Mth.DEG_TO_RAD, rotZ * Mth.DEG_TO_RAD); - key.setScrollTexture(spriteShift) - .setScrollMult(diagonal ? 3f / 8f : 0.5f) - .setRotation(q) - .setRotationalSpeed(getScrollSpeed()) - .setRotationOffset(bottom ? 0.5f : 0f) - .setColor(blockEntity) - .setPosition(getVisualPosition()) - .light(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos)) + key.setSpriteShift(spriteShift, 1f, (diagonal ? SCROLL_FACTOR_DIAGONAL : SCROLL_FACTOR_OTHERWISE)) + .position(getVisualPosition()) + .rotation(q) + .speed(0, speed * MAGIC_SCROLL_MULTIPLIER) + .offset(0, bottom ? SCROLL_OFFSET_BOTTOM : SCROLL_OFFSET_OTHERWISE) + .colorRgb(RotatingInstance.colorFromBE(blockEntity)) .setChanged(); return key; @@ -173,9 +170,11 @@ public class BeltVisual extends KineticBlockEntityVisual { @Override public void collectCrumblingInstances(Consumer consumer) { - if (pulleyKey != null) { - consumer.accept(pulleyKey); + if (pulley != null) { + consumer.accept(pulley); + } + for (var key : belts) { + consumer.accept(key); } - keys.forEach(consumer); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/TransportedItemStackHandlerBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/TransportedItemStackHandlerBehaviour.java index a492180a97..b637f13b60 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/TransportedItemStackHandlerBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/TransportedItemStackHandlerBehaviour.java @@ -10,8 +10,8 @@ import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorItem.java b/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorItem.java index 70941826f3..130a59a5fe 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorItem.java @@ -14,9 +14,9 @@ import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBloc import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -44,7 +44,7 @@ public class BeltConnectorItem extends BlockItem { public String getDescriptionId() { return getOrCreateDescriptionId(); } - + @Nonnull @Override public InteractionResult useOn(UseOnContext context) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltCrusherInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltCrusherInteractionHandler.java index a710973de6..acfe8ec622 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltCrusherInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltCrusherInteractionHandler.java @@ -11,66 +11,65 @@ 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 net.minecraftforge.items.ItemHandlerHelper; public class BeltCrusherInteractionHandler { - public static boolean checkForCrushers(BeltInventory beltInventory, TransportedItemStack currentItem, - float nextOffset) { + public static boolean checkForCrushers(BeltInventory beltInventory, TransportedItemStack currentItem, + float nextOffset) { - boolean beltMovementPositive = beltInventory.beltMovementPositive; - int firstUpcomingSegment = (int) Math.floor(currentItem.beltPosition); - int step = beltMovementPositive ? 1 : -1; - firstUpcomingSegment = Mth.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1); + boolean beltMovementPositive = beltInventory.beltMovementPositive; + int firstUpcomingSegment = (int) Math.floor(currentItem.beltPosition); + int step = beltMovementPositive ? 1 : -1; + firstUpcomingSegment = Mth.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1); - for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset - : segment + 1 >= nextOffset; segment += step) { - BlockPos crusherPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) - .above(); - Level world = beltInventory.belt.getLevel(); - BlockState crusherState = world.getBlockState(crusherPos); - if (!(crusherState.getBlock() instanceof CrushingWheelControllerBlock)) - continue; - Direction crusherFacing = crusherState.getValue(CrushingWheelControllerBlock.FACING); - Direction movementFacing = beltInventory.belt.getMovementFacing(); - if (crusherFacing != movementFacing) - continue; + for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset + : segment + 1 >= nextOffset; segment += step) { + BlockPos crusherPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) + .above(); + Level world = beltInventory.belt.getLevel(); + BlockState crusherState = world.getBlockState(crusherPos); + if (!(crusherState.getBlock() instanceof CrushingWheelControllerBlock)) + continue; + Direction crusherFacing = crusherState.getValue(CrushingWheelControllerBlock.FACING); + Direction movementFacing = beltInventory.belt.getMovementFacing(); + if (crusherFacing != movementFacing) + continue; - float crusherEntry = segment + .5f; - crusherEntry += .399f * (beltMovementPositive ? -1 : 1); - float postCrusherEntry = crusherEntry + .799f * (!beltMovementPositive ? -1 : 1); + float crusherEntry = segment + .5f; + crusherEntry += .399f * (beltMovementPositive ? -1 : 1); + float postCrusherEntry = crusherEntry + .799f * (!beltMovementPositive ? -1 : 1); - boolean hasCrossed = nextOffset > crusherEntry && nextOffset < postCrusherEntry && beltMovementPositive - || nextOffset < crusherEntry && nextOffset > postCrusherEntry && !beltMovementPositive; - if (!hasCrossed) - return false; - currentItem.beltPosition = crusherEntry; + boolean hasCrossed = nextOffset > crusherEntry && nextOffset < postCrusherEntry && beltMovementPositive + || nextOffset < crusherEntry && nextOffset > postCrusherEntry && !beltMovementPositive; + if (!hasCrossed) + return false; + currentItem.beltPosition = crusherEntry; - BlockEntity be = world.getBlockEntity(crusherPos); - if (!(be instanceof CrushingWheelControllerBlockEntity)) - return true; + BlockEntity be = world.getBlockEntity(crusherPos); + if (!(be instanceof CrushingWheelControllerBlockEntity crusherBE)) + return true; - CrushingWheelControllerBlockEntity crusherBE = (CrushingWheelControllerBlockEntity) be; + ItemStack toInsert = currentItem.stack.copy(); - ItemStack toInsert = currentItem.stack.copy(); + ItemStack remainder = ItemHandlerHelper.insertItemStacked(crusherBE.inventory, toInsert, false); + if (toInsert.equals(remainder, false)) + return true; - ItemStack remainder = ItemHandlerHelper.insertItemStacked(crusherBE.inventory, toInsert, false); - if (toInsert.equals(remainder, false)) - return true; + int notFilled = currentItem.stack.getCount() - toInsert.getCount(); + if (!remainder.isEmpty()) { + remainder.grow(notFilled); + } else if (notFilled > 0) + remainder = ItemHandlerHelper.copyStackWithSize(currentItem.stack, notFilled); - int notFilled = currentItem.stack.getCount() - toInsert.getCount(); - if (!remainder.isEmpty()) { - remainder.grow(notFilled); - } else if (notFilled > 0) - remainder = ItemHandlerHelper.copyStackWithSize(currentItem.stack, notFilled); + currentItem.stack = remainder; + beltInventory.belt.sendData(); + return true; + } - currentItem.stack = remainder; - beltInventory.belt.sendData(); - return true; - } - - return false; - } + return false; + } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltFunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltFunnelInteractionHandler.java index 3b214e46e1..3b8267193e 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltFunnelInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltFunnelInteractionHandler.java @@ -15,12 +15,13 @@ 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 net.minecraftforge.items.ItemHandlerHelper; public class BeltFunnelInteractionHandler { public static boolean checkForFunnels(BeltInventory beltInventory, TransportedItemStack currentItem, - float nextOffset) { + float nextOffset) { boolean beltMovementPositive = beltInventory.beltMovementPositive; int firstUpcomingSegment = (int) Math.floor(currentItem.beltPosition); int step = beltMovementPositive ? 1 : -1; @@ -59,10 +60,9 @@ public class BeltFunnelInteractionHandler { continue; BlockEntity be = world.getBlockEntity(funnelPos); - if (!(be instanceof FunnelBlockEntity)) + if (!(be instanceof FunnelBlockEntity funnelBE)) return true; - FunnelBlockEntity funnelBE = (FunnelBlockEntity) be; InvManipulationBehaviour inserting = funnelBE.getBehaviour(InvManipulationBehaviour.TYPE); FilteringBehaviour filtering = funnelBE.getBehaviour(FilteringBehaviour.TYPE); @@ -72,7 +72,7 @@ public class BeltFunnelInteractionHandler { else continue; - if(beltInventory.belt.invVersionTracker.stillWaiting(inserting)) + if (beltInventory.belt.invVersionTracker.stillWaiting(inserting)) continue; int amountToExtract = funnelBE.getAmountToExtract(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltInventory.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltInventory.java index 1d1b80b05c..c984268667 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltInventory.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltInventory.java @@ -8,6 +8,8 @@ import java.util.LinkedList; import java.util.List; import java.util.function.Function; +import javax.annotation.Nullable; + import com.simibubi.create.content.kinetics.belt.BeltBlock; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltHelper; @@ -26,6 +28,7 @@ import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; +import net.minecraft.util.Mth; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -39,6 +42,8 @@ public class BeltInventory { final List toRemove; boolean beltMovementPositive; final float SEGMENT_WINDOW = .75f; + + TransportedItemStack lazyClientItem; public BeltInventory(BeltBlockEntity be) { this.belt = be; @@ -49,6 +54,14 @@ public class BeltInventory { public void tick() { + // Residual item for "smooth" transitions + if (lazyClientItem != null) { + if (lazyClientItem.locked) + lazyClientItem = null; + else + lazyClientItem.locked = true; + } + // Added/Removed items from previous cycle if (!toInsert.isEmpty() || !toRemove.isEmpty()) { toInsert.forEach(this::insert); @@ -167,8 +180,9 @@ public class BeltInventory { // Apply Movement currentItem.beltPosition += limitedMovement; - currentItem.sideOffset += - (currentItem.getTargetSideOffset() - currentItem.sideOffset) * Math.abs(limitedMovement) * 2f; + float diffToMiddle = currentItem.getTargetSideOffset() - currentItem.sideOffset; + currentItem.sideOffset += Mth.clamp(diffToMiddle * Math.abs(limitedMovement) * 6f, -Math.abs(diffToMiddle), + Math.abs(diffToMiddle)); currentPos = currentItem.beltPosition; // Movement successful @@ -195,8 +209,12 @@ public class BeltInventory { continue; currentItem.stack = remainder; - if (remainder.isEmpty()) + if (remainder.isEmpty()) { + lazyClientItem = currentItem; + lazyClientItem.locked = false; iterator.remove(); + } else + currentItem.stack = remainder; flapTunnel(this, lastOffset, movementFacing, false); belt.sendData(); @@ -392,6 +410,8 @@ public class BeltInventory { items.clear(); nbt.getList("Items", Tag.TAG_COMPOUND) .forEach(inbt -> items.add(TransportedItemStack.read((CompoundTag) inbt))); + if (nbt.contains("LazyItem")) + lazyClientItem = TransportedItemStack.read(nbt.getCompound("LazyItem")); beltMovementPositive = nbt.getBoolean("PositiveOrder"); } @@ -400,6 +420,8 @@ public class BeltInventory { ListTag itemsNBT = new ListTag(); items.forEach(stack -> itemsNBT.add(stack.serializeNBT())); nbt.put("Items", itemsNBT); + if (lazyClientItem != null) + nbt.put("LazyItem", lazyClientItem.serializeNBT()); nbt.putBoolean("PositiveOrder", beltMovementPositive); return nbt; } @@ -458,4 +480,9 @@ public class BeltInventory { return items; } + @Nullable + public TransportedItemStack getLazyClientItem() { + return lazyClientItem; + } + } diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltMovementHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltMovementHandler.java index e25e1be2d1..9bf2937a3b 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltMovementHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltMovementHandler.java @@ -7,6 +7,7 @@ import static net.minecraft.world.entity.MoverType.SELF; import java.util.List; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; import com.simibubi.create.content.kinetics.belt.BeltBlock; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltPart; @@ -19,6 +20,7 @@ import net.minecraft.core.Vec3i; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.decoration.HangingEntity; import net.minecraft.world.entity.player.Player; @@ -60,7 +62,8 @@ public class BeltMovementHandler { public static boolean canBeTransported(Entity entity) { if (!entity.isAlive()) return false; - if (entity instanceof Player && ((Player) entity).isShiftKeyDown()) + if (entity instanceof Player p && p.isShiftKeyDown() + && !AllItems.CARDBOARD_BOOTS.isIn(p.getItemBySlot(EquipmentSlot.FEET))) return false; return true; } diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltTunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltTunnelInteractionHandler.java index 2c96df8587..4bd951beb0 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltTunnelInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltTunnelInteractionHandler.java @@ -13,20 +13,21 @@ import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; import com.simibubi.create.content.redstone.displayLink.source.AccumulatedItemCountDisplaySource; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; 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 net.minecraftforge.items.ItemHandlerHelper; public class BeltTunnelInteractionHandler { public static boolean flapTunnelsAndCheckIfStuck(BeltInventory beltInventory, TransportedItemStack current, - float nextOffset) { + float nextOffset) { int currentSegment = (int) current.beltPosition; int upcomingSegment = (int) nextOffset; @@ -48,8 +49,7 @@ public class BeltTunnelInteractionHandler { BeltTunnelBlockEntity nextTunnel = getTunnelOnSegment(beltInventory, upcomingSegment); int transferred = current.stack.getCount(); - if (nextTunnel instanceof BrassTunnelBlockEntity) { - BrassTunnelBlockEntity brassTunnel = (BrassTunnelBlockEntity) nextTunnel; + if (nextTunnel instanceof BrassTunnelBlockEntity brassTunnel) { if (brassTunnel.hasDistributionBehaviour()) { if (!brassTunnel.canTakeItems()) return true; @@ -115,7 +115,7 @@ public class BeltTunnelInteractionHandler { } public static boolean stuckAtTunnel(BeltInventory beltInventory, int offset, ItemStack stack, - Direction movementDirection) { + Direction movementDirection) { BeltBlockEntity belt = beltInventory.belt; BlockPos pos = BeltHelper.getPositionForOffset(belt, offset) .above(); @@ -125,9 +125,8 @@ public class BeltTunnelInteractionHandler { return false; BlockEntity be = belt.getLevel() .getBlockEntity(pos); - if (be == null || !(be instanceof BrassTunnelBlockEntity)) + if (be == null || !(be instanceof BrassTunnelBlockEntity tunnel)) return false; - BrassTunnelBlockEntity tunnel = (BrassTunnelBlockEntity) be; return !tunnel.canInsert(movementDirection.getOpposite(), stack); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/TransportedItemStack.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/TransportedItemStack.java index aa55002608..6185fdf323 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/TransportedItemStack.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/TransportedItemStack.java @@ -2,11 +2,15 @@ package com.simibubi.create.content.kinetics.belt.transport; import java.util.Random; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes; import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType; +import com.simibubi.create.content.logistics.box.PackageItem; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; public class TransportedItemStack implements Comparable { @@ -32,6 +36,8 @@ public class TransportedItemStack implements Comparable { this.stack = stack; boolean centered = BeltHelper.isItemUpright(stack); angle = centered ? 180 : R.nextInt(360); + if (PackageItem.isPackage(stack)) + angle = R.nextInt(4) * 90 + R.nextInt(20) - 10; sideOffset = prevSideOffset = getTargetSideOffset(); insertedFrom = Direction.UP; } @@ -74,6 +80,16 @@ public class TransportedItemStack implements Comparable { nbt.putInt("InSegment", insertedAt); nbt.putInt("Angle", angle); nbt.putInt("InDirection", insertedFrom.get3DDataValue()); + + if (processedBy != null) { + ResourceLocation key = CreateBuiltInRegistries.FAN_PROCESSING_TYPE.getKey(processedBy); + if (key == null) + throw new IllegalArgumentException("Could not get id for FanProcessingType " + processedBy + "!"); + + nbt.putString("FanProcessingType", key.toString()); + nbt.putInt("FanProcessingTime", processingTime); + } + if (locked) nbt.putBoolean("Locked", locked); if (lockedExternally) @@ -92,7 +108,18 @@ public class TransportedItemStack implements Comparable { stack.insertedFrom = Direction.from3DDataValue(nbt.getInt("InDirection")); stack.locked = nbt.getBoolean("Locked"); stack.lockedExternally = nbt.getBoolean("LockedExternally"); + + if (nbt.contains("FanProcessingType")) { + stack.processedBy = AllFanProcessingTypes.parseLegacy(nbt.getString("FanProcessingType")); + stack.processingTime = nbt.getInt("FanProcessingTime"); + } + return stack; } -} \ No newline at end of file + public void clearFanProcessingData() { + processedBy = null; + processingTime = 0; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlock.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlock.java new file mode 100644 index 0000000000..63bb3b00ff --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlock.java @@ -0,0 +1,134 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.KineticBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.IHaveBigOutline; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class ChainConveyorBlock extends KineticBlock implements IBE, IHaveBigOutline { + + public ChainConveyorBlock(Properties properties) { + super(properties); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return Axis.Y; + } + + @Override + public VoxelShape getInteractionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { + return AllShapes.CHAIN_CONVEYOR_INTERACTION; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.CHAIN_CONVEYOR_INTERACTION; + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + if (!pLevel.isClientSide() && pPlayer != null && pPlayer.getItemInHand(pHand) + .is(Items.CHAIN)) + return InteractionResult.SUCCESS; + if (pPlayer != null && AllBlocks.PACKAGE_FROGPORT.isIn(pPlayer.getItemInHand(pHand))) + return InteractionResult.SUCCESS; + return InteractionResult.PASS; + } + + @Override + public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) { + super.playerWillDestroy(pLevel, pPos, pState, pPlayer); + if (pLevel.isClientSide()) + return; + if (!pPlayer.isCreative()) + return; + withBlockEntityDo(pLevel, pPos, be -> be.cancelDrops = true); + } + + @Override + public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { + Player player = context.getPlayer(); + if (player == null) + return super.onSneakWrenched(state, context); + + withBlockEntityDo(context.getLevel(), context.getClickedPos(), be -> { + be.cancelDrops = true; + if (player.isCreative()) + return; + for (BlockPos targetPos : be.connections) { + int chainCost = ChainConveyorBlockEntity.getChainCost(targetPos); + while (chainCost > 0) { + player.getInventory() + .placeItemBackInInventory(new ItemStack(Items.CHAIN, Math.min(chainCost, 64))); + chainCost -= 64; + } + } + }); + + return super.onSneakWrenched(state, context); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + for (int x = -1; x <= 1; x++) + for (int z = -1; z <= 1; z++) + if (pContext.getLevel() + .getBlockState(pContext.getClickedPos() + .offset(x, 0, z)) + .getBlock() == this) + return null; + + return super.getStateForPlacement(pContext); + } + + @Override + public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, + CollisionContext pContext) { + return Shapes.block(); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return face.getAxis() == getRotationAxis(state); + } + + @Override + public Class getBlockEntityClass() { + return ChainConveyorBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CHAIN_CONVEYOR.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java new file mode 100644 index 0000000000..d68fbbb01d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java @@ -0,0 +1,806 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Consumer; + +import javax.annotation.Nullable; + +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorPackage.ChainConveyorPackagePhysicsData; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorShape.ChainConveyorBB; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorShape.ChainConveyorOBB; +import com.simibubi.create.content.logistics.box.PackageEntity; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportBlockEntity; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.items.ItemHandlerHelper; + +public class ChainConveyorBlockEntity extends KineticBlockEntity implements TransformableBlockEntity { + + public record ConnectionStats(float tangentAngle, float chainLength, Vec3 start, Vec3 end) { + } + + public record ConnectedPort(float chainPosition, BlockPos connection, String filter) { + } + + public Set connections = new HashSet<>(); + public Map connectionStats; + + public Map loopPorts = new HashMap<>(); + public Map travelPorts = new HashMap<>(); + public ChainConveyorRoutingTable routingTable = new ChainConveyorRoutingTable(); + + List loopingPackages = new ArrayList<>(); + Map> travellingPackages = new HashMap<>(); + + public boolean reversed; + public boolean cancelDrops; + public boolean checkInvalid; + + BlockPos chainDestroyedEffectToSend; + + public ChainConveyorBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + checkInvalid = true; + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).inflate(connections.isEmpty() ? 3 : 64); + } + + @Override + public void lazyTick() { + super.lazyTick(); + updateChainShapes(); + } + + public boolean canAcceptMorePackages() { + return loopingPackages.size() + travellingPackages.size() < AllConfigs.server().logistics.chainConveyorCapacity + .get(); + } + + public boolean canAcceptPackagesFor(@Nullable BlockPos connection) { + if (connection == null && !canAcceptMorePackages()) + return false; + if (connection != null + && (!(level.getBlockEntity(worldPosition.offset(connection)) instanceof ChainConveyorBlockEntity otherClbe) + || !otherClbe.canAcceptMorePackages())) + return false; + return true; + } + + public boolean canAcceptMorePackagesFromOtherConveyor() { + return loopingPackages.size() < AllConfigs.server().logistics.chainConveyorCapacity.get(); + } + + @Override + public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + return super.addToTooltip(tooltip, isPlayerSneaking); + + // debug routing info +// tooltip.addAll(routingTable.createSummary()); +// if (!loopPorts.isEmpty()) +// tooltip.add(Component.literal(loopPorts.size() + " Loop ports")); +// if (!travelPorts.isEmpty()) +// tooltip.add(Component.literal(travelPorts.size() + " Travel ports")); +// return true; + } + + @Override + public void tick() { + super.tick(); + + if (checkInvalid && !level.isClientSide()) { + checkInvalid = false; + removeInvalidConnections(); + } + + float serverSpeed = level.isClientSide() && !isVirtual() ? ServerSpeedProvider.get() : 1f; + float speed = getSpeed() / 360f; + float radius = 1.5f; + float distancePerTick = Math.abs(speed); + float degreesPerTick = (speed / (Mth.PI * radius)) * 360f; + boolean reversedPreviously = reversed; + + prepareStats(); + + if (level.isClientSide()) { + // We can use TickableVisuals if flywheel is enabled + if (!VisualizationManager.supportsVisualization(level)) + tickBoxVisuals(); + } + + if (!level.isClientSide()) { + routingTable.tick(); + if (routingTable.shouldAdvertise()) { + for (BlockPos pos : connections) + if (level.getBlockEntity(worldPosition.offset(pos)) instanceof ChainConveyorBlockEntity clbe) + routingTable.advertiseTo(pos, clbe.routingTable); + routingTable.changed = false; + routingTable.lastUpdate = 0; + } + } + + if (speed == 0) { + updateBoxWorldPositions(); + return; + } + + if (reversedPreviously != reversed) { + for (Entry> entry : travellingPackages.entrySet()) { + BlockPos offset = entry.getKey(); + if (!(level.getBlockEntity(worldPosition.offset(offset)) instanceof ChainConveyorBlockEntity otherLift)) + continue; + for (Iterator iterator = entry.getValue() + .iterator(); iterator.hasNext(); ) { + ChainConveyorPackage box = iterator.next(); + if (box.justFlipped) + continue; + box.justFlipped = true; + float length = (float) Vec3.atLowerCornerOf(offset) + .length() - 22 / 16f; + box.chainPosition = length - box.chainPosition; + otherLift.addTravellingPackage(box, offset.multiply(-1)); + iterator.remove(); + } + } + notifyUpdate(); + } + + for (Entry> entry : travellingPackages.entrySet()) { + BlockPos target = entry.getKey(); + ConnectionStats stats = connectionStats.get(target); + if (stats == null) + continue; + + Travelling: + for (Iterator iterator = entry.getValue() + .iterator(); iterator.hasNext(); ) { + ChainConveyorPackage box = iterator.next(); + box.justFlipped = false; + + float prevChainPosition = box.chainPosition; + box.chainPosition += serverSpeed * distancePerTick; + box.chainPosition = Math.min(stats.chainLength, box.chainPosition); + + float anticipatePosition = box.chainPosition; + anticipatePosition += serverSpeed * distancePerTick * 4; + anticipatePosition = Math.min(stats.chainLength, anticipatePosition); + + if (level.isClientSide() && !isVirtual()) + continue; + + for (Entry portEntry : travelPorts.entrySet()) { + ConnectedPort port = portEntry.getValue(); + float chainPosition = port.chainPosition(); + + if (prevChainPosition > chainPosition) + continue; + if (!target.equals(port.connection)) + continue; + + boolean notAtPositionYet = box.chainPosition < chainPosition; + if (notAtPositionYet && anticipatePosition < chainPosition) + continue; + if (!PackageItem.matchAddress(box.item, port.filter())) + continue; + if (notAtPositionYet) { + notifyPortToAnticipate(portEntry.getKey()); + continue; + } + + if (!exportToPort(box, portEntry.getKey())) + continue; + + iterator.remove(); + notifyUpdate(); + continue Travelling; + } + + if (box.chainPosition < stats.chainLength) + continue; + + // transfer to other + if (level.getBlockEntity(worldPosition.offset(target)) instanceof ChainConveyorBlockEntity clbe) { + box.chainPosition = wrapAngle(stats.tangentAngle + 180 + 2 * 35 * (reversed ? -1 : 1)); + clbe.addLoopingPackage(box); + iterator.remove(); + notifyUpdate(); + } + } + } + + Looping: + for (Iterator iterator = loopingPackages.iterator(); iterator.hasNext(); ) { + ChainConveyorPackage box = iterator.next(); + box.justFlipped = false; + + float prevChainPosition = box.chainPosition; + box.chainPosition += serverSpeed * degreesPerTick; + box.chainPosition = wrapAngle(box.chainPosition); + + float anticipatePosition = box.chainPosition; + anticipatePosition += serverSpeed * degreesPerTick * 4; + anticipatePosition = wrapAngle(anticipatePosition); + + if (level.isClientSide()) + continue; + + for (Entry portEntry : loopPorts.entrySet()) { + ConnectedPort port = portEntry.getValue(); + float offBranchAngle = port.chainPosition(); + + boolean notAtPositionYet = !loopThresholdCrossed(box.chainPosition, prevChainPosition, offBranchAngle); + if (notAtPositionYet && !loopThresholdCrossed(anticipatePosition, prevChainPosition, offBranchAngle)) + continue; + if (!PackageItem.matchAddress(box.item, port.filter())) + continue; + if (notAtPositionYet) { + notifyPortToAnticipate(portEntry.getKey()); + continue; + } + + if (!exportToPort(box, portEntry.getKey())) + continue; + + iterator.remove(); + notifyUpdate(); + continue Looping; + } + + for (BlockPos connection : connections) { + if (level.getBlockEntity(worldPosition.offset(connection)) instanceof ChainConveyorBlockEntity ccbe + && !ccbe.canAcceptMorePackagesFromOtherConveyor()) + continue; + + float offBranchAngle = connectionStats.get(connection).tangentAngle; + + if (!loopThresholdCrossed(box.chainPosition, prevChainPosition, offBranchAngle)) + continue; + if (!routingTable.getExitFor(box.item) + .equals(connection)) + continue; + + box.chainPosition = 0; + addTravellingPackage(box, connection); + iterator.remove(); + continue Looping; + } + } + + updateBoxWorldPositions(); + } + + public void removeInvalidConnections() { + boolean changed = false; + for (Iterator iterator = connections.iterator(); iterator.hasNext(); ) { + BlockPos next = iterator.next(); + BlockPos target = worldPosition.offset(next); + if (!level.isLoaded(target)) + continue; + if (level.getBlockEntity(target) instanceof ChainConveyorBlockEntity ccbe + && ccbe.connections.contains(next.multiply(-1))) + continue; + iterator.remove(); + changed = true; + } + if (changed) + notifyUpdate(); + } + + public void notifyConnectedToValidate() { + for (BlockPos blockPos : connections) { + BlockPos target = worldPosition.offset(blockPos); + if (!level.isLoaded(target)) + continue; + if (level.getBlockEntity(target) instanceof ChainConveyorBlockEntity ccbe) + ccbe.checkInvalid = true; + } + } + + public void tickBoxVisuals() { + for (ChainConveyorPackage box : loopingPackages) + tickBoxVisuals(box); + for (Entry> entry : travellingPackages.entrySet()) + for (ChainConveyorPackage box : entry.getValue()) + tickBoxVisuals(box); + } + + public boolean loopThresholdCrossed(float chainPosition, float prevChainPosition, float offBranchAngle) { + int sign1 = Mth.sign(AngleHelper.getShortestAngleDiff(offBranchAngle, prevChainPosition)); + int sign2 = Mth.sign(AngleHelper.getShortestAngleDiff(offBranchAngle, chainPosition)); + boolean notCrossed = sign1 >= sign2 && !reversed || sign1 <= sign2 && reversed; + return !notCrossed; + } + + private boolean exportToPort(ChainConveyorPackage box, BlockPos offset) { + BlockPos globalPos = worldPosition.offset(offset); + if (!(level.getBlockEntity(globalPos) instanceof FrogportBlockEntity ppbe)) + return false; + + if (ppbe.isAnimationInProgress()) + return false; + if (ppbe.isBackedUp()) + return false; + + ppbe.startAnimation(box.item, false); + return true; + } + + private void notifyPortToAnticipate(BlockPos offset) { + if (level.getBlockEntity(worldPosition.offset(offset)) instanceof FrogportBlockEntity ppbe) + ppbe.sendAnticipate(); + } + + public boolean addTravellingPackage(ChainConveyorPackage box, BlockPos connection) { + if (!connections.contains(connection)) + return false; + travellingPackages.computeIfAbsent(connection, $ -> new ArrayList<>()) + .add(box); + if (level.isClientSide) + return true; + notifyUpdate(); + return true; + } + + @Override + public void notifyUpdate() { + level.blockEntityChanged(worldPosition); + sendData(); + } + + public boolean addLoopingPackage(ChainConveyorPackage box) { + loopingPackages.add(box); + notifyUpdate(); + return true; + } + + public void prepareStats() { + float speed = getSpeed(); + if (reversed != speed < 0 && speed != 0) { + reversed = speed < 0; + connectionStats = null; + } + if (connectionStats == null) { + connectionStats = new HashMap<>(); + connections.forEach(this::calculateConnectionStats); + } + } + + public void updateBoxWorldPositions() { + prepareStats(); + + for (Entry> entry : travellingPackages.entrySet()) { + BlockPos target = entry.getKey(); + ConnectionStats stats = connectionStats.get(target); + if (stats == null) + continue; + for (ChainConveyorPackage box : entry.getValue()) { + box.worldPosition = getPackagePosition(box.chainPosition, target); + if (level == null || !level.isClientSide()) + continue; + Vec3 diff = stats.end.subtract(stats.start) + .normalize(); + box.yaw = Mth.wrapDegrees((float) Mth.atan2(diff.x, diff.z) * Mth.RAD_TO_DEG - 90); + } + } + + for (ChainConveyorPackage box : loopingPackages) { + box.worldPosition = getPackagePosition(box.chainPosition, null); + box.yaw = Mth.wrapDegrees(box.chainPosition); + if (reversed) + box.yaw += 180; + } + } + + public Vec3 getPackagePosition(float chainPosition, @Nullable BlockPos travelTarget) { + if (travelTarget == null) + return Vec3.atBottomCenterOf(worldPosition) + .add(VecHelper.rotate(new Vec3(0, 6 / 16f, 0.875), chainPosition, Axis.Y)); + prepareStats(); + ConnectionStats stats = connectionStats.get(travelTarget); + if (stats == null) + return Vec3.ZERO; + Vec3 diff = stats.end.subtract(stats.start) + .normalize(); + return stats.start.add(diff.scale(Math.min(stats.chainLength, chainPosition))); + } + + private void tickBoxVisuals(ChainConveyorPackage box) { + if (box.worldPosition == null) + return; + + ChainConveyorPackagePhysicsData physicsData = box.physicsData(level); + physicsData.setBE(this); + + if (!physicsData.shouldTick() && !isVirtual()) + return; + + physicsData.prevTargetPos = physicsData.targetPos; + physicsData.prevPos = physicsData.pos; + physicsData.prevYaw = physicsData.yaw; + physicsData.flipped = reversed; + + if (physicsData.pos != null) { + if (physicsData.pos.distanceToSqr(box.worldPosition) > 1.5f * 1.5f) + physicsData.pos = box.worldPosition.add(physicsData.pos.subtract(box.worldPosition) + .normalize() + .scale(1.5)); + physicsData.motion = physicsData.motion.add(0, -0.25, 0) + .scale(0.75) + .add((box.worldPosition.subtract(physicsData.pos)).scale(0.25)); + physicsData.pos = physicsData.pos.add(physicsData.motion); + } + + physicsData.targetPos = box.worldPosition.subtract(0, 9 / 16f, 0); + + if (physicsData.pos == null) { + physicsData.pos = physicsData.targetPos; + physicsData.prevPos = physicsData.targetPos; + physicsData.prevTargetPos = physicsData.targetPos; + } + + physicsData.yaw = AngleHelper.angleLerp(.25, physicsData.yaw, box.yaw); + } + + private void calculateConnectionStats(BlockPos connection) { + boolean reversed = getSpeed() < 0; + float offBranchDistance = 35f; + float direction = Mth.RAD_TO_DEG * (float) Mth.atan2(connection.getX(), connection.getZ()); + float angle = wrapAngle(direction - offBranchDistance * (reversed ? -1 : 1)); + float oppositeAngle = wrapAngle(angle + 180 + 2 * offBranchDistance * (reversed ? -1 : 1)); + + Vec3 start = Vec3.atBottomCenterOf(worldPosition) + .add(VecHelper.rotate(new Vec3(0, 0, 1.25), angle, Axis.Y)) + .add(0, 6 / 16f, 0); + + Vec3 end = Vec3.atBottomCenterOf(worldPosition.offset(connection)) + .add(VecHelper.rotate(new Vec3(0, 0, 1.25), oppositeAngle, Axis.Y)) + .add(0, 6 / 16f, 0); + + float length = (float) start.distanceTo(end); + connectionStats.put(connection, new ConnectionStats(angle, length, start, end)); + } + + public boolean addConnectionTo(BlockPos target) { + BlockPos localTarget = target.subtract(worldPosition); + boolean added = connections.add(localTarget); + if (added) { + notifyUpdate(); + calculateConnectionStats(localTarget); + updateChainShapes(); + } + + detachKinetics(); + updateSpeed = true; + + return added; + } + + public void chainDestroyed(BlockPos target, boolean spawnDrops, boolean sendEffect) { + int chainCount = getChainCost(target); + if (sendEffect) { + chainDestroyedEffectToSend = target; + sendData(); + } + if (!spawnDrops) + return; + + if (!forPointsAlongChains(target, chainCount, + vec -> level.addFreshEntity(new ItemEntity(level, vec.x, vec.y, vec.z, new ItemStack(Items.CHAIN))))) { + while (chainCount > 0) { + Block.popResource(level, worldPosition, new ItemStack(Blocks.CHAIN.asItem(), Math.min(chainCount, 64))); + chainCount -= 64; + } + } + } + + public boolean removeConnectionTo(BlockPos target) { + BlockPos localTarget = target.subtract(worldPosition); + if (!connections.contains(localTarget)) + return false; + + detachKinetics(); + connections.remove(localTarget); + connectionStats.remove(localTarget); + List packages = travellingPackages.remove(localTarget); + if (packages != null) + for (ChainConveyorPackage box : packages) + drop(box); + notifyUpdate(); + updateChainShapes(); + updateSpeed = true; + + return true; + } + + private void updateChainShapes() { + prepareStats(); + + List shapes = new ArrayList<>(); + shapes.add(new ChainConveyorBB(Vec3.atBottomCenterOf(BlockPos.ZERO))); + for (BlockPos target : connections) { + ConnectionStats stats = connectionStats.get(target); + if (stats == null) + continue; + Vec3 localStart = stats.start.subtract(Vec3.atLowerCornerOf(worldPosition)); + Vec3 localEnd = stats.end.subtract(Vec3.atLowerCornerOf(worldPosition)); + shapes.add(new ChainConveyorOBB(target, localStart, localEnd)); + } + + if (level != null && level.isClientSide()) + ChainConveyorInteractionHandler.loadedChains.get(level) + .put(worldPosition, shapes); + } + + @Override + public void remove() { + super.remove(); + if (level == null || !level.isClientSide()) + return; + for (BlockPos blockPos : connections) + spawnDestroyParticles(blockPos); + } + + private void spawnDestroyParticles(BlockPos blockPos) { + forPointsAlongChains(blockPos, (int) Math.round(Vec3.atLowerCornerOf(blockPos) + .length() * 8), + vec -> level.addParticle(new BlockParticleOption(ParticleTypes.BLOCK, Blocks.CHAIN.defaultBlockState()), + vec.x, vec.y, vec.z, 0, 0, 0)); + } + + @Override + public void destroy() { + super.destroy(); + + for (BlockPos blockPos : connections) { + chainDestroyed(blockPos, !cancelDrops, false); + if (level.getBlockEntity(worldPosition.offset(blockPos)) instanceof ChainConveyorBlockEntity clbe) + clbe.removeConnectionTo(worldPosition); + } + + for (ChainConveyorPackage box : loopingPackages) + drop(box); + for (Entry> entry : travellingPackages.entrySet()) + for (ChainConveyorPackage box : entry.getValue()) + drop(box); + } + + public boolean forPointsAlongChains(BlockPos connection, int positions, Consumer callback) { + prepareStats(); + ConnectionStats stats = connectionStats.get(connection); + if (stats == null) + return false; + + Vec3 start = stats.start; + Vec3 direction = stats.end.subtract(start); + Vec3 origin = Vec3.atCenterOf(worldPosition); + Vec3 normal = direction.cross(new Vec3(0, 1, 0)) + .normalize(); + Vec3 offset = start.subtract(origin); + Vec3 start2 = origin.add(offset.add(normal.scale(-2 * normal.dot(offset)))); + + for (boolean firstChain : Iterate.trueAndFalse) { + int steps = positions / 2; + if (firstChain) + steps += positions % 2; + for (int i = 0; i < steps; i++) + callback.accept((firstChain ? start : start2).add(direction.scale((0.5 + i) / steps))); + } + + return true; + } + + @Override + public void invalidate() { + super.invalidate(); + if (level != null && level.isClientSide()) + ChainConveyorInteractionHandler.loadedChains.get(level) + .invalidate(worldPosition); + } + + private void drop(ChainConveyorPackage box) { + if (box.worldPosition != null) + level.addFreshEntity(PackageEntity.fromItemStack(level, box.worldPosition.subtract(0, 0.5, 0), box.item)); + } + + @Override + public List addPropagationLocations(IRotate block, BlockState state, List neighbours) { + connections.forEach(p -> neighbours.add(worldPosition.offset(p))); + return super.addPropagationLocations(block, state, neighbours); + } + + @Override + public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, + boolean connectedViaAxes, boolean connectedViaCogs) { + if (connections.contains(target.getBlockPos() + .subtract(worldPosition))) { + if (!(target instanceof ChainConveyorBlockEntity)) + return 0; + return 1; + } + return super.propagateRotationTo(target, stateFrom, stateTo, diff, connectedViaAxes, connectedViaCogs); + } + + @Override + public void writeSafe(CompoundTag tag) { + super.writeSafe(tag); + tag.put("Connections", NBTHelper.writeCompoundList(connections, NbtUtils::writeBlockPos)); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + if (clientPacket && chainDestroyedEffectToSend != null) { + compound.put("DestroyEffect", NbtUtils.writeBlockPos(chainDestroyedEffectToSend)); + chainDestroyedEffectToSend = null; + } + + compound.put("Connections", NBTHelper.writeCompoundList(connections, NbtUtils::writeBlockPos)); + compound.put("TravellingPackages", NBTHelper.writeCompoundList(travellingPackages.entrySet(), entry -> { + CompoundTag compoundTag = new CompoundTag(); + compoundTag.put("Target", NbtUtils.writeBlockPos(entry.getKey())); + compoundTag.put("Packages", NBTHelper.writeCompoundList(entry.getValue(), + clientPacket ? ChainConveyorPackage::writeToClient : ChainConveyorPackage::write)); + return compoundTag; + })); + compound.put("LoopingPackages", NBTHelper.writeCompoundList(loopingPackages, + clientPacket ? ChainConveyorPackage::writeToClient : ChainConveyorPackage::write)); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (clientPacket && compound.contains("DestroyEffect") && level != null) + spawnDestroyParticles(NbtUtils.readBlockPos(compound.getCompound("DestroyEffect"))); + + int sizeBefore = connections.size(); + connections.clear(); + NBTHelper.iterateCompoundList(compound.getList("Connections", Tag.TAG_COMPOUND), + c -> connections.add(NbtUtils.readBlockPos(c))); + travellingPackages.clear(); + NBTHelper.iterateCompoundList(compound.getList("TravellingPackages", Tag.TAG_COMPOUND), + c -> travellingPackages.put(NbtUtils.readBlockPos(c.getCompound("Target")), + NBTHelper.readCompoundList(c.getList("Packages", Tag.TAG_COMPOUND), ChainConveyorPackage::read))); + loopingPackages = NBTHelper.readCompoundList(compound.getList("LoopingPackages", Tag.TAG_COMPOUND), + ChainConveyorPackage::read); + connectionStats = null; + updateBoxWorldPositions(); + updateChainShapes(); + + if (connections.size() != sizeBefore && level != null && level.isClientSide) + invalidateRenderBoundingBox(); + } + + public float wrapAngle(float angle) { + angle %= 360; + if (angle < 0) + angle += 360; + return angle; + } + + public static int getChainCost(BlockPos connection) { + return (int) Math.max(Math.round(Vec3.atLowerCornerOf(connection) + .length() / 2.5), 1); + } + + public static boolean getChainsFromInventory(Player player, ItemStack chain, int cost, boolean simulate) { + int found = 0; + + Inventory inv = player.getInventory(); + int size = inv.items.size(); + for (int j = 0; j <= size + 1; j++) { + int i = j; + boolean offhand = j == size + 1; + if (j == size) + i = inv.selected; + else if (offhand) + i = 0; + else if (j == inv.selected) + continue; + + ItemStack stackInSlot = (offhand ? inv.offhand : inv.items).get(i); + if (!stackInSlot.is(chain.getItem())) + continue; + if (found >= cost) + continue; + + int count = stackInSlot.getCount(); + + if (!simulate) { + int remainingItems = count - Math.min(cost - found, count); + if (i == inv.selected) + stackInSlot.setTag(null); + ItemStack newItem = ItemHandlerHelper.copyStackWithSize(stackInSlot, remainingItems); + if (offhand) + player.setItemInHand(InteractionHand.OFF_HAND, newItem); + else + inv.setItem(i, newItem); + } + + found += count; + } + + return found >= cost; + } + + public List getLoopingPackages() { + return loopingPackages; + } + + public Map> getTravellingPackages() { + return travellingPackages; + } + + @Override + public ItemRequirement getRequiredItems(BlockState state) { + // TODO: Uncomment when Schematicannon is able to print these with chains +// int totalCost = 0; +// for (BlockPos pos : connections) +// totalCost += getChainCost(pos); +// if (totalCost > 0) +// return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(Items.CHAIN, Mth.ceil(totalCost / 2.0))); + return super.getRequiredItems(state); + } + + @Override + public void transform(BlockEntity be, StructureTransform transform) { + if (connections == null || connections.isEmpty()) + return; + + connections = new HashSet<>(connections.stream() + .map(transform::applyWithoutOffset) + .toList()); + + HashMap> newMap = new HashMap<>(); + travellingPackages.entrySet() + .forEach(e -> newMap.put(transform.applyWithoutOffset(e.getKey()), e.getValue())); + travellingPackages = newMap; + + connectionStats = null; + notifyUpdate(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorConnectionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorConnectionHandler.java new file mode 100644 index 0000000000..a4eb6ee2f2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorConnectionHandler.java @@ -0,0 +1,282 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer; +import com.simibubi.create.foundation.utility.CreateLang; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.resources.ResourceKey; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.HitResult.Type; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(Dist.CLIENT) +public class ChainConveyorConnectionHandler { + + private static BlockPos firstPos; + private static ResourceKey firstDim; + + public static boolean onRightClick() { + Minecraft mc = Minecraft.getInstance(); + if (!isChain(mc.player.getMainHandItem())) + return false; + if (firstPos == null) + return false; + boolean missed = false; + if (mc.hitResult instanceof BlockHitResult bhr && bhr.getType() != Type.MISS) + if (!(mc.level.getBlockEntity(bhr.getBlockPos()) instanceof ChainConveyorBlockEntity)) + missed = true; + if (!mc.player.isShiftKeyDown() && !missed) + return false; + firstPos = null; + CreateLang.translate("chain_conveyor.selection_cleared") + .sendStatus(mc.player); + return true; + } + + @SubscribeEvent + public static void onItemUsedOnBlock(PlayerInteractEvent.RightClickBlock event) { + ItemStack itemStack = event.getItemStack(); + BlockPos pos = event.getPos(); + Level level = event.getLevel(); + Player player = event.getEntity(); + BlockState blockState = level.getBlockState(pos); + + if (!AllBlocks.CHAIN_CONVEYOR.has(blockState)) + return; + if (!isChain(itemStack)) + return; + if (!player.mayBuild() || player instanceof FakePlayer) + return; + + event.setCanceled(true); + event.setCancellationResult(InteractionResult.CONSUME); + + if (!level.isClientSide()) + return; + if (level.getBlockEntity(pos) instanceof ChainConveyorBlockEntity ccbe + && ccbe.connections.size() >= AllConfigs.server().kinetics.maxChainConveyorConnections.get()) { + CreateLang.translate("chain_conveyor.cannot_add_more_connections") + .style(ChatFormatting.RED) + .sendStatus(player); + return; + } + + if (firstPos == null || firstDim != level.dimension()) { + firstPos = pos; + firstDim = level.dimension(); + player.swing(event.getHand()); + return; + } + + boolean success = validateAndConnect(level, pos, player, itemStack, false); + firstPos = null; + + if (!success) { + AllSoundEvents.DENY.play(level, player, pos); + return; + } + + SoundType soundtype = Blocks.CHAIN.defaultBlockState() + .getSoundType(); + if (soundtype != null) + level.playSound(player, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS, + (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); + } + + private static boolean isChain(ItemStack itemStack) { + return itemStack.is(Items.CHAIN); // Replace with tag? generic renderer? + } + + public static void clientTick() { + if (firstPos == null) + return; + + LocalPlayer player = Minecraft.getInstance().player; + BlockEntity sourceLift = player.level() + .getBlockEntity(firstPos); + + if (firstDim != player.level() + .dimension() || !(sourceLift instanceof ChainConveyorBlockEntity)) { + firstPos = null; + CreateLang.translate("chain_conveyor.selection_cleared") + .sendStatus(player); + return; + } + + ItemStack stack = player.getMainHandItem(); + HitResult hitResult = Minecraft.getInstance().hitResult; + + if (!isChain(stack)) { + stack = player.getOffhandItem(); + if (!isChain(stack)) + return; + } + + if (hitResult == null || hitResult.getType() != Type.BLOCK) { + highlightConveyor(firstPos, 0xFFFFFF, "chain_connect"); + return; + } + + Level level = player.level(); + BlockHitResult bhr = (BlockHitResult) hitResult; + BlockPos pos = bhr.getBlockPos(); + BlockState hitState = level.getBlockState(pos); + + if (pos.equals(firstPos)) { + highlightConveyor(firstPos, 0xFFFFFF, "chain_connect"); + CreateLang.translate("chain_conveyor.select_second") + .sendStatus(player); + return; + } + + if (!(hitState.getBlock() instanceof ChainConveyorBlock)) { + highlightConveyor(firstPos, 0xFFFFFF, "chain_connect"); + return; + } + + boolean success = validateAndConnect(level, pos, player, stack, true); + + if (success) + CreateLang.translate("chain_conveyor.valid_connection") + .style(ChatFormatting.GREEN) + .sendStatus(player); + + int color = success ? 0x95CD41 : 0xEA5C2B; + + highlightConveyor(firstPos, color, "chain_connect"); + highlightConveyor(pos, color, "chain_connect_to"); + + Vec3 from = Vec3.atCenterOf(pos); + Vec3 to = Vec3.atCenterOf(firstPos); + Vec3 diff = from.subtract(to); + + if (diff.length() < 1) + return; + + from = from.subtract(diff.normalize() + .scale(.5)); + to = to.add(diff.normalize() + .scale(.5)); + + Vec3 normal = diff.cross(new Vec3(0, 1, 0)) + .normalize() + .scale(.875); + + Outliner.getInstance().showLine("chain_connect_line", from.add(normal), to.add(normal)) + .lineWidth(1 / 16f) + .colored(color); + Outliner.getInstance().showLine("chain_connect_line_1", from.subtract(normal), to.subtract(normal)) + .lineWidth(1 / 16f) + .colored(color); + + } + + private static void highlightConveyor(BlockPos pos, int color, String key) { + for (int y : Iterate.zeroAndOne) { + Vec3 prevV = VecHelper.rotate(new Vec3(0, .125 + y * .75, 1.25), -22.5, Axis.Y) + .add(Vec3.atBottomCenterOf(pos)); + for (int i = 0; i < 8; i++) { + Vec3 v = VecHelper.rotate(new Vec3(0, .125 + y * .75, 1.25), 22.5 + i * 45, Axis.Y) + .add(Vec3.atBottomCenterOf(pos)); + Outliner.getInstance().showLine(key + y + i, prevV, v) + .lineWidth(1 / 16f) + .colored(color); + prevV = v; + } + } + } + + public static boolean validateAndConnect(LevelAccessor level, BlockPos pos, Player player, ItemStack chain, + boolean simulate) { + if (!simulate && player.isShiftKeyDown()) { + CreateLang.translate("chain_conveyor.selection_cleared") + .sendStatus(player); + return false; + } + + if (pos.equals(firstPos)) + return false; + if (!pos.closerThan(firstPos, AllConfigs.server().kinetics.maxChainConveyorLength.get())) + return fail("chain_conveyor.too_far"); + if (pos.closerThan(firstPos, 2.5)) + return fail("chain_conveyor.too_close"); + + Vec3 diff = Vec3.atLowerCornerOf(pos.subtract(firstPos)); + double horizontalDistance = diff.multiply(1, 0, 1) + .length() - 1.5; + + if (horizontalDistance <= 0) + return fail("chain_conveyor.cannot_connect_vertically"); + if (Math.abs(diff.y) / horizontalDistance > 1) + return fail("chain_conveyor.too_steep"); + + ChainConveyorBlock chainConveyorBlock = AllBlocks.CHAIN_CONVEYOR.get(); + ChainConveyorBlockEntity sourceLift = chainConveyorBlock.getBlockEntity(level, firstPos); + ChainConveyorBlockEntity targetLift = chainConveyorBlock.getBlockEntity(level, pos); + + if (targetLift.connections.size() >= AllConfigs.server().kinetics.maxChainConveyorConnections.get()) + return fail("chain_conveyor.cannot_add_more_connections"); + if (targetLift.connections.contains(firstPos.subtract(pos))) + return fail("chain_conveyor.already_connected"); + if (sourceLift == null || targetLift == null) + return fail("chain_conveyor.blocks_invalid"); + + if (!player.isCreative()) { + int chainCost = ChainConveyorBlockEntity.getChainCost(pos.subtract(firstPos)); + boolean hasEnough = ChainConveyorBlockEntity.getChainsFromInventory(player, chain, chainCost, true); + if (simulate) + BlueprintOverlayRenderer.displayChainRequirements(chain.getItem(), chainCost, hasEnough); + if (!hasEnough) + return fail("chain_conveyor.not_enough_chains"); + } + + if (simulate) + return true; + + AllPackets.getChannel() + .sendToServer(new ChainConveyorConnectionPacket(firstPos, pos, chain, true)); + + CreateLang.text("") // Clear status message + .sendStatus(player); + firstPos = null; + firstDim = null; + return true; + } + + private static boolean fail(String message) { + CreateLang.translate(message) + .style(ChatFormatting.RED) + .sendStatus(Minecraft.getInstance().player); + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorConnectionPacket.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorConnectionPacket.java new file mode 100644 index 0000000000..764a14a3a8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorConnectionPacket.java @@ -0,0 +1,97 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class ChainConveyorConnectionPacket extends BlockEntityConfigurationPacket { + + private BlockPos targetPos; + private boolean connect; + private ItemStack chain; + + public ChainConveyorConnectionPacket(BlockPos pos, BlockPos targetPos, ItemStack chain, boolean connect) { + super(pos); + this.targetPos = targetPos; + this.chain = chain; + this.connect = connect; + } + + public ChainConveyorConnectionPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBlockPos(targetPos); + buffer.writeBoolean(connect); + buffer.writeItem(chain); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + targetPos = buffer.readBlockPos(); + connect = buffer.readBoolean(); + chain = buffer.readItem(); + } + + @Override + protected int maxRange() { + return AllConfigs.server().kinetics.maxChainConveyorLength.get() + 16; + } + + @Override + protected void applySettings(ServerPlayer player, ChainConveyorBlockEntity be) { + if (!be.getBlockPos() + .closerThan(targetPos, maxRange() - 16 + 1)) + return; + if (!(be.getLevel() + .getBlockEntity(targetPos) instanceof ChainConveyorBlockEntity clbe)) + return; + + if (connect && !player.isCreative()) { + int chainCost = ChainConveyorBlockEntity.getChainCost(targetPos.subtract(be.getBlockPos())); + boolean hasEnough = ChainConveyorBlockEntity.getChainsFromInventory(player, chain, chainCost, true); + if (!hasEnough) + return; + ChainConveyorBlockEntity.getChainsFromInventory(player, chain, chainCost, false); + } + + if (!connect) { + if (!player.isCreative()) { + int chainCost = ChainConveyorBlockEntity.getChainCost(targetPos.subtract(pos)); + while (chainCost > 0) { + player.getInventory() + .placeItemBackInInventory(new ItemStack(Items.CHAIN, Math.min(chainCost, 64))); + chainCost -= 64; + } + } + be.chainDestroyed(targetPos.subtract(be.getBlockPos()), false, true); + be.getLevel() + .playSound(null, player.blockPosition(), SoundEvents.CHAIN_BREAK, SoundSource.BLOCKS); + } + + if (connect) { + if (!clbe.addConnectionTo(be.getBlockPos())) + return; + } else + clbe.removeConnectionTo(be.getBlockPos()); + + if (connect) { + if (!be.addConnectionTo(targetPos)) + clbe.removeConnectionTo(be.getBlockPos()); + } else + be.removeConnectionTo(targetPos); + } + + @Override + protected void applySettings(ChainConveyorBlockEntity be) {} + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorInteractionHandler.java new file mode 100644 index 0000000000..cca47498dc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorInteractionHandler.java @@ -0,0 +1,177 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.List; +import java.util.Map.Entry; + +import com.google.common.cache.Cache; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.packagePort.PackagePortTarget; +import com.simibubi.create.content.logistics.packagePort.PackagePortTargetSelectionHandler; +import com.simibubi.create.foundation.utility.RaycastHelper; +import com.simibubi.create.foundation.utility.TickBasedCache; + +import net.createmod.catnip.data.WorldAttached; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.theme.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderHighlightEvent; +import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(Dist.CLIENT) +public class ChainConveyorInteractionHandler { + + public static WorldAttached>> loadedChains = + new WorldAttached<>($ -> new TickBasedCache<>(60, true)); + + public static BlockPos selectedLift; + public static float selectedChainPosition; + public static BlockPos selectedConnection; + public static Vec3 selectedBakedPosition; + public static ChainConveyorShape selectedShape; + + public static void clientTick() { + if (!isActive()) { + selectedLift = null; + return; + } + + Minecraft mc = Minecraft.getInstance(); + ItemStack mainHandItem = mc.player.getMainHandItem(); + boolean isWrench = AllItemTags.CHAIN_RIDEABLE.matches(mainHandItem); + boolean dismantling = isWrench && mc.player.isShiftKeyDown(); + double range = mc.player.getAttribute(ForgeMod.BLOCK_REACH.get()) + .getValue() + 1; + + Vec3 from = RaycastHelper.getTraceOrigin(mc.player); + Vec3 to = RaycastHelper.getTraceTarget(mc.player, range, from); + HitResult hitResult = mc.hitResult; + + double bestDiff = Float.MAX_VALUE; + if (hitResult != null) + bestDiff = hitResult.getLocation() + .distanceToSqr(from); + + BlockPos bestLift = null; + ChainConveyorShape bestShape = null; + selectedConnection = null; + + for (Entry> entry : loadedChains.get(Minecraft.getInstance().level) + .asMap() + .entrySet()) { + BlockPos liftPos = entry.getKey(); + for (ChainConveyorShape chainConveyorShape : entry.getValue()) { + if (chainConveyorShape instanceof ChainConveyorShape.ChainConveyorBB && dismantling) + continue; + Vec3 liftVec = Vec3.atLowerCornerOf(liftPos); + Vec3 intersect = chainConveyorShape.intersect(from.subtract(liftVec), to.subtract(liftVec)); + if (intersect == null) + continue; + + double distanceToSqr = intersect.add(liftVec) + .distanceToSqr(from); + if (distanceToSqr > bestDiff) + continue; + bestDiff = distanceToSqr; + bestLift = liftPos; + bestShape = chainConveyorShape; + selectedChainPosition = chainConveyorShape.getChainPosition(intersect); + if (chainConveyorShape instanceof ChainConveyorShape.ChainConveyorOBB obb) + selectedConnection = obb.connection; + } + } + + selectedLift = bestLift; + if (bestLift == null) + return; + + selectedShape = bestShape; + selectedBakedPosition = bestShape.getVec(bestLift, selectedChainPosition); + + if (!isWrench) { + Outliner.getInstance() + .chaseAABB("ChainPointSelection", new AABB(selectedBakedPosition, selectedBakedPosition)) + .colored(Color.WHITE) + .lineWidth(1 / 6f) + .disableLineNormals(); + } + } + + private static boolean isActive() { + Minecraft mc = Minecraft.getInstance(); + ItemStack mainHandItem = mc.player.getMainHandItem(); + return AllItemTags.CHAIN_RIDEABLE.matches(mainHandItem) || AllBlocks.PACKAGE_FROGPORT.isIn(mainHandItem) + || PackageItem.isPackage(mainHandItem); + } + + public static boolean onUse() { + if (selectedLift == null) + return false; + + Minecraft mc = Minecraft.getInstance(); + ItemStack mainHandItem = mc.player.getMainHandItem(); + + if (AllItemTags.CHAIN_RIDEABLE.matches(mainHandItem)) { + if (!mc.player.isShiftKeyDown()) { + ChainConveyorRidingHandler.embark(selectedLift, selectedChainPosition, selectedConnection); + return true; + } + + AllPackets.getChannel() + .sendToServer(new ChainConveyorConnectionPacket(selectedLift, selectedLift.offset(selectedConnection), + mainHandItem, false)); + return true; + } + + if (AllBlocks.PACKAGE_FROGPORT.isIn(mainHandItem)) { + PackagePortTargetSelectionHandler.exactPositionOfTarget = selectedBakedPosition; + PackagePortTargetSelectionHandler.activePackageTarget = + new PackagePortTarget.ChainConveyorFrogportTarget(selectedLift, selectedChainPosition, selectedConnection); + return true; + } + + if (PackageItem.isPackage(mainHandItem)) { + AllPackets.getChannel() + .sendToServer(new ChainPackageInteractionPacket(selectedLift, selectedConnection, selectedChainPosition, + mainHandItem)); + return true; + } + + return true; + } + + public static void drawCustomBlockSelection(PoseStack ms, MultiBufferSource buffer, Vec3 camera) { + if (selectedLift == null || selectedShape == null) + return; + + VertexConsumer vb = buffer.getBuffer(RenderType.lines()); + ms.pushPose(); + ms.translate(selectedLift.getX() - camera.x, selectedLift.getY() - camera.y, selectedLift.getZ() - camera.z); + selectedShape.drawOutline(selectedLift, ms, vb); + ms.popPose(); + } + + @SubscribeEvent + public static void hideVanillaBlockSelection(RenderHighlightEvent.Block event) { + if (selectedLift == null || selectedShape == null) + return; + + event.setCanceled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorPackage.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorPackage.java new file mode 100644 index 0000000000..f08c45a06d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorPackage.java @@ -0,0 +1,123 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.lang.ref.WeakReference; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicInteger; + +import com.google.common.cache.Cache; +import com.simibubi.create.foundation.utility.TickBasedCache; + +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.WorldAttached; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.phys.Vec3; + +public class ChainConveyorPackage { + + // Server creates unique ids for chain boxes + public static final AtomicInteger netIdGenerator = new AtomicInteger(); + + // Client tracks physics data by id so it can travel between BEs + private static final int ticksUntilExpired = 30; + public static final WorldAttached> physicsDataCache = + new WorldAttached<>($ -> new TickBasedCache<>(ticksUntilExpired, true)); + + public class ChainConveyorPackagePhysicsData { + public Vec3 targetPos; + public Vec3 prevTargetPos; + public Vec3 prevPos; + public Vec3 pos; + + public Vec3 motion; + public int lastTick; + public float yaw; + public float prevYaw; + public boolean flipped; + public ResourceLocation modelKey; + + public WeakReference beReference; + + public ChainConveyorPackagePhysicsData(Vec3 serverPosition) { + this.targetPos = null; + this.prevTargetPos = null; + this.pos = null; + this.prevPos = null; + + this.motion = Vec3.ZERO; + this.lastTick = AnimationTickHolder.getTicks(); + } + + public boolean shouldTick() { + if (lastTick == AnimationTickHolder.getTicks()) + return false; + lastTick = AnimationTickHolder.getTicks(); + return true; + } + + public void setBE(ChainConveyorBlockEntity ccbe) { + if (beReference == null || beReference.get() != ccbe) + beReference = new WeakReference<>(ccbe); + } + + } + + public float chainPosition; + public ItemStack item; + public int netId; + public boolean justFlipped; + + public Vec3 worldPosition; + public float yaw; + + private ChainConveyorPackagePhysicsData physicsData; + + public ChainConveyorPackage(float chainPosition, ItemStack item) { + this(chainPosition, item, netIdGenerator.incrementAndGet()); + } + + public ChainConveyorPackage(float chainPosition, ItemStack item, int netId) { + this.chainPosition = chainPosition; + this.item = item; + this.netId = netId; + this.physicsData = null; + } + + public CompoundTag writeToClient() { + CompoundTag tag = write(); + tag.putInt("NetID", netId); + return tag; + } + + public CompoundTag write() { + CompoundTag compoundTag = new CompoundTag(); + compoundTag.putFloat("Position", chainPosition); + compoundTag.put("Item", item.serializeNBT()); + return compoundTag; + } + + public static ChainConveyorPackage read(CompoundTag compoundTag) { + float pos = compoundTag.getFloat("Position"); + ItemStack item = ItemStack.of(compoundTag.getCompound("Item")); + if (compoundTag.contains("NetID")) + return new ChainConveyorPackage(pos, item, compoundTag.getInt("NetID")); + return new ChainConveyorPackage(pos, item); + } + + public ChainConveyorPackagePhysicsData physicsData(LevelAccessor level) { + if (physicsData == null) { + try { + return physicsData = physicsDataCache.get(level) + .get(netId, () -> new ChainConveyorPackagePhysicsData(worldPosition)); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + physicsDataCache.get(level) + .getIfPresent(netId); + return physicsData; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java new file mode 100644 index 0000000000..afff699b51 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java @@ -0,0 +1,274 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.List; +import java.util.Map.Entry; + +import org.joml.Matrix3f; +import org.joml.Matrix4f; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity.ConnectionStats; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorPackage.ChainConveyorPackagePhysicsData; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.foundation.render.RenderTypes; + +import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.registries.ForgeRegistries; + +public class ChainConveyorRenderer extends KineticBlockEntityRenderer { + + public static final ResourceLocation CHAIN_LOCATION = new ResourceLocation("textures/block/chain.png"); + public static final int MIP_DISTANCE = 48; + + public ChainConveyorRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(ChainConveyorBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + BlockPos pos = be.getBlockPos(); + + renderChains(be, ms, buffer, light, overlay); + + if (VisualizationManager.supportsVisualization(be.getLevel())) + return; + + CachedBuffers.partial(AllPartialModels.CHAIN_CONVEYOR_WHEEL, be.getBlockState()) + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + + for (ChainConveyorPackage box : be.loopingPackages) + renderBox(be, ms, buffer, overlay, pos, box, partialTicks); + for (Entry> entry : be.travellingPackages.entrySet()) + for (ChainConveyorPackage box : entry.getValue()) + renderBox(be, ms, buffer, overlay, pos, box, partialTicks); + } + + private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int overlay, + BlockPos pos, ChainConveyorPackage box, float partialTicks) { + if (box.worldPosition == null) + return; + if (box.item == null || box.item.isEmpty()) + return; + + ChainConveyorPackagePhysicsData physicsData = box.physicsData(be.getLevel()); + if (physicsData.prevPos == null) + return; + + Vec3 position = physicsData.prevPos.lerp(physicsData.pos, partialTicks); + Vec3 targetPosition = physicsData.prevTargetPos.lerp(physicsData.targetPos, partialTicks); + float yaw = AngleHelper.angleLerp(partialTicks, physicsData.prevYaw, physicsData.yaw); + Vec3 offset = + new Vec3(targetPosition.x - pos.getX(), targetPosition.y - pos.getY(), targetPosition.z - pos.getZ()); + + BlockPos containingPos = BlockPos.containing(position); + Level level = be.getLevel(); + BlockState blockState = be.getBlockState(); + int light = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, containingPos), + level.getBrightness(LightLayer.SKY, containingPos)); + + if (physicsData.modelKey == null) { + ResourceLocation key = ForgeRegistries.ITEMS.getKey(box.item.getItem()); + if (key == null) + return; + physicsData.modelKey = key; + } + + SuperByteBuffer rigBuffer = + CachedBuffers.partial(AllPartialModels.PACKAGE_RIGGING.get(physicsData.modelKey), blockState); + SuperByteBuffer boxBuffer = + CachedBuffers.partial(AllPartialModels.PACKAGES.get(physicsData.modelKey), blockState); + + Vec3 dangleDiff = VecHelper.rotate(targetPosition.add(0, 0.5, 0) + .subtract(position), -yaw, Axis.Y); + float zRot = Mth.wrapDegrees((float) Mth.atan2(-dangleDiff.x, dangleDiff.y) * Mth.RAD_TO_DEG) / 2; + float xRot = Mth.wrapDegrees((float) Mth.atan2(dangleDiff.z, dangleDiff.y) * Mth.RAD_TO_DEG) / 2; + zRot = Mth.clamp(zRot, -25, 25); + xRot = Mth.clamp(xRot, -25, 25); + + for (SuperByteBuffer buf : new SuperByteBuffer[] { rigBuffer, boxBuffer }) { + buf.translate(offset); + buf.translate(0, 10 / 16f, 0); + buf.rotateYDegrees(yaw); + + buf.rotateZDegrees(zRot); + buf.rotateXDegrees(xRot); + + if (physicsData.flipped && buf == rigBuffer) + buf.rotateYDegrees(180); + + buf.uncenter(); + buf.translate(0, -PackageItem.getHookDistance(box.item) + 7 / 16f, 0); + + buf.light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + } + } + + private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + float time = AnimationTickHolder.getRenderTime(be.getLevel()) / (360f / Math.abs(be.getSpeed())); + time %= 1; + if (time < 0) + time += 1; + + float animation = time - 0.5f; + + for (BlockPos blockPos : be.connections) { + ConnectionStats stats = be.connectionStats.get(blockPos); + if (stats == null) + continue; + + Vec3 diff = stats.end() + .subtract(stats.start()); + double yaw = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z); + double pitch = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.y, diff.multiply(1, 0, 1) + .length()); + + Level level = be.getLevel(); + BlockPos tilePos = be.getBlockPos(); + Vec3 startOffset = stats.start() + .subtract(Vec3.atCenterOf(tilePos)); + + if (!VisualizationManager.supportsVisualization(be.getLevel())) { + SuperByteBuffer guard = + CachedBuffers.partial(AllPartialModels.CHAIN_CONVEYOR_GUARD, be.getBlockState()); + guard.center(); + guard.rotateYDegrees((float) yaw); + + guard.uncenter(); + guard.light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + } + + ms.pushPose(); + var chain = TransformStack.of(ms); + chain.center(); + chain.translate(startOffset); + chain.rotateYDegrees((float) yaw); + chain.rotateXDegrees(90 - (float) pitch); + chain.rotateYDegrees(45); + chain.translate(0, 8 / 16f, 0); + chain.uncenter(); + + int light1 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos), + level.getBrightness(LightLayer.SKY, tilePos)); + int light2 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos.offset(blockPos)), + level.getBrightness(LightLayer.SKY, tilePos.offset(blockPos))); + + boolean far = Minecraft.getInstance().level == be.getLevel() && !Minecraft.getInstance() + .getBlockEntityRenderDispatcher().camera.getPosition() + .closerThan(Vec3.atCenterOf(tilePos) + .add(blockPos.getX() / 2f, blockPos.getY() / 2f, blockPos.getZ() / 2f), MIP_DISTANCE); + + renderChain(ms, buffer, animation, stats.chainLength(), light1, light2, far); + + ms.popPose(); + } + } + + public static void renderChain(PoseStack ms, MultiBufferSource buffer, float animation, float length, int light1, + int light2, boolean far) { + float radius = far ? 1f / 16f : 1.5f / 16f; + float minV = far ? 0 : animation; + float maxV = far ? 1 / 16f : length + minV; + float minU = far ? 3 / 16f : 0; + float maxU = far ? 4 / 16f : 3 / 16f; + + ms.pushPose(); + ms.translate(0.5D, 0.0D, 0.5D); + + VertexConsumer vc = buffer.getBuffer(RenderTypes.chain(CHAIN_LOCATION)); + renderPart(ms, vc, length, 0.0F, radius, radius, 0.0F, -radius, 0.0F, 0.0F, -radius, minU, maxU, minV, maxV, + light1, light2, far); + + ms.popPose(); + } + + private static void renderPart(PoseStack pPoseStack, VertexConsumer pConsumer, float pMaxY, float pX0, float pZ0, + float pX1, float pZ1, float pX2, float pZ2, float pX3, float pZ3, float pMinU, float pMaxU, float pMinV, + float pMaxV, int light1, int light2, boolean far) { + PoseStack.Pose posestack$pose = pPoseStack.last(); + Matrix4f matrix4f = posestack$pose.pose(); + Matrix3f matrix3f = posestack$pose.normal(); + + float uO = far ? 0f : 3 / 16f; + renderQuad(matrix4f, matrix3f, pConsumer, 0, pMaxY, pX0, pZ0, pX3, pZ3, pMinU, pMaxU, pMinV, pMaxV, light1, + light2); + renderQuad(matrix4f, matrix3f, pConsumer, 0, pMaxY, pX3, pZ3, pX0, pZ0, pMinU, pMaxU, pMinV, pMaxV, light1, + light2); + renderQuad(matrix4f, matrix3f, pConsumer, 0, pMaxY, pX1, pZ1, pX2, pZ2, pMinU + uO, pMaxU + uO, pMinV, pMaxV, + light1, light2); + renderQuad(matrix4f, matrix3f, pConsumer, 0, pMaxY, pX2, pZ2, pX1, pZ1, pMinU + uO, pMaxU + uO, pMinV, pMaxV, + light1, light2); + } + + private static void renderQuad(Matrix4f pPose, Matrix3f pNormal, VertexConsumer pConsumer, float pMinY, float pMaxY, + float pMinX, float pMinZ, float pMaxX, float pMaxZ, float pMinU, float pMaxU, float pMinV, float pMaxV, + int light1, int light2) { + addVertex(pPose, pNormal, pConsumer, pMaxY, pMinX, pMinZ, pMaxU, pMinV, light2); + addVertex(pPose, pNormal, pConsumer, pMinY, pMinX, pMinZ, pMaxU, pMaxV, light1); + addVertex(pPose, pNormal, pConsumer, pMinY, pMaxX, pMaxZ, pMinU, pMaxV, light1); + addVertex(pPose, pNormal, pConsumer, pMaxY, pMaxX, pMaxZ, pMinU, pMinV, light2); + } + + private static void addVertex(Matrix4f pPose, Matrix3f pNormal, VertexConsumer pConsumer, float pY, float pX, + float pZ, float pU, float pV, int light) { + pConsumer.vertex(pPose, pX, pY, pZ) + .color(1.0f, 1.0f, 1.0f, 1.0f) + .uv(pU, pV) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(light) + .normal(pNormal, 0.0F, 1.0F, 0.0F) + .endVertex(); + } + + @Override + public int getViewDistance() { + return 256; + } + + @Override + public boolean shouldRenderOffScreen(ChainConveyorBlockEntity be) { + return true; + } + + @Override + protected SuperByteBuffer getRotatedModel(ChainConveyorBlockEntity be, BlockState state) { + return CachedBuffers.partial(AllPartialModels.CHAIN_CONVEYOR_SHAFT, state); + } + + @Override + protected RenderType getRenderType(ChainConveyorBlockEntity be, BlockState state) { + return RenderType.cutoutMipped(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRidingHandler.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRidingHandler.java new file mode 100644 index 0000000000..883caa0da0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRidingHandler.java @@ -0,0 +1,183 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity.ConnectionStats; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; + +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec3; + +public class ChainConveyorRidingHandler { + + public static BlockPos ridingChainConveyor; + public static float chainPosition; + public static BlockPos ridingConnection; + public static boolean flipped; + public static int catchingUp; + + public static void embark(BlockPos lift, float position, BlockPos connection) { + ridingChainConveyor = lift; + chainPosition = position; + ridingConnection = connection; + catchingUp = 20; + Minecraft mc = Minecraft.getInstance(); + if (mc.level.getBlockEntity(ridingChainConveyor) instanceof ChainConveyorBlockEntity clbe) + flipped = clbe.getSpeed() < 0; + + Component component = Component.translatable("mount.onboard", mc.options.keyShift.getTranslatedKeyMessage()); + mc.gui.setOverlayMessage(component, false); + mc.getSoundManager() + .play(SimpleSoundInstance.forUI(SoundEvents.CHAIN_HIT, 1f, 0.5f)); + } + + public static void clientTick() { + if (ridingChainConveyor == null) + return; + Minecraft mc = Minecraft.getInstance(); + if (mc.isPaused()) + return; + if (!AllItemTags.CHAIN_RIDEABLE.matches(mc.player.getMainHandItem())) { + stopRiding(); + return; + } + BlockEntity blockEntity = mc.level.getBlockEntity(ridingChainConveyor); + if (mc.player.isShiftKeyDown() || !(blockEntity instanceof ChainConveyorBlockEntity clbe)) { + stopRiding(); + return; + } + if (ridingConnection != null && !clbe.connections.contains(ridingConnection)) { + stopRiding(); + return; + } + + clbe.prepareStats(); + + Vec3 playerPosition = mc.player.position() + .add(0, mc.player.getBoundingBox() + .getYsize() + 0.5, 0); + + updateTargetPosition(mc, clbe); + + blockEntity = mc.level.getBlockEntity(ridingChainConveyor); + if (!(blockEntity instanceof ChainConveyorBlockEntity)) + return; + + clbe = (ChainConveyorBlockEntity) blockEntity; + clbe.prepareStats(); + + Vec3 targetPosition; + + if (ridingConnection != null) { + ConnectionStats stats = clbe.connectionStats.get(ridingConnection); + targetPosition = stats.start() + .add((stats.end() + .subtract(stats.start())).normalize() + .scale(Math.min(stats.chainLength(), chainPosition))); + } else { + targetPosition = Vec3.atBottomCenterOf(ridingChainConveyor) + .add(VecHelper.rotate(new Vec3(0, 0.25, 1), chainPosition, Axis.Y)); + } + + if (catchingUp > 0) + catchingUp--; + + Vec3 diff = targetPosition.subtract(playerPosition); + if (catchingUp == 0 && (diff.length() > 3 || diff.y < -1)) { + stopRiding(); + return; + } + + mc.player.setDeltaMovement(mc.player.getDeltaMovement() + .scale(0.75) + .add(diff.scale(0.25))); + if (AnimationTickHolder.getTicks() % 10 == 0) + AllPackets.getChannel() + .sendToServer(new ServerboundChainConveyorRidingPacket(ridingChainConveyor, false)); + } + + private static void stopRiding() { + if (ridingChainConveyor != null) + AllPackets.getChannel() + .sendToServer(new ServerboundChainConveyorRidingPacket(ridingChainConveyor, true)); + ridingChainConveyor = null; + ridingConnection = null; + Minecraft.getInstance() + .getSoundManager() + .play(SimpleSoundInstance.forUI(SoundEvents.CHAIN_HIT, 0.75f, 0.35f)); + } + + private static void updateTargetPosition(Minecraft mc, ChainConveyorBlockEntity clbe) { + float serverSpeed = ServerSpeedProvider.get(); + float speed = clbe.getSpeed() / 360f; + float radius = 1.5f; + float distancePerTick = Math.abs(speed); + float degreesPerTick = (speed / (Mth.PI * radius)) * 360f; + + if (ridingConnection != null) { + ConnectionStats stats = clbe.connectionStats.get(ridingConnection); + + if (flipped != clbe.getSpeed() < 0) { + flipped = clbe.getSpeed() < 0; + ridingChainConveyor = clbe.getBlockPos() + .offset(ridingConnection); + chainPosition = stats.chainLength() - chainPosition; + ridingConnection = ridingConnection.multiply(-1); + return; + } + + chainPosition += serverSpeed * distancePerTick; + chainPosition = Math.min(stats.chainLength(), chainPosition); + if (chainPosition < stats.chainLength()) + return; + + // transfer to other + if (mc.level.getBlockEntity(clbe.getBlockPos() + .offset(ridingConnection)) instanceof ChainConveyorBlockEntity clbe2) { + chainPosition = clbe.wrapAngle(stats.tangentAngle() + 180 + 2 * 35 * (clbe.reversed ? -1 : 1)); + ridingChainConveyor = clbe2.getBlockPos(); + ridingConnection = null; + } + + return; + } + + float prevChainPosition = chainPosition; + chainPosition += serverSpeed * degreesPerTick; + chainPosition = clbe.wrapAngle(chainPosition); + + BlockPos nearestLooking = BlockPos.ZERO; + double bestDiff = Double.MAX_VALUE; + for (BlockPos connection : clbe.connections) { + double diff = Vec3.atLowerCornerOf(connection) + .normalize() + .distanceToSqr(mc.player.getLookAngle() + .normalize()); + if (diff > bestDiff) + continue; + nearestLooking = connection; + bestDiff = diff; + } + + if (nearestLooking == BlockPos.ZERO) + return; + + float offBranchAngle = clbe.connectionStats.get(nearestLooking) + .tangentAngle(); + if (!clbe.loopThresholdCrossed(chainPosition, prevChainPosition, offBranchAngle)) + return; + + chainPosition = 0; + ridingConnection = nearestLooking; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRoutingTable.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRoutingTable.java new file mode 100644 index 0000000000..fb8ac8f5aa --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRoutingTable.java @@ -0,0 +1,97 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.commons.lang3.mutable.MutableInt; + +import com.simibubi.create.content.logistics.box.PackageItem; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; + +public class ChainConveyorRoutingTable { + + public static final int ENTRY_TIMEOUT = 100; + public static final int PORT_ENTRY_TIMEOUT = 20; + + public record RoutingTableEntry(String port, int distance, BlockPos nextConnection, MutableInt timeout, + boolean endOfRoute) { + + public void tick() { + timeout.decrement(); + } + + public boolean invalid() { + return timeout.intValue() <= 0; + } + + public RoutingTableEntry copyForNeighbour(BlockPos connection) { + return new RoutingTableEntry(port, distance + 1, connection.multiply(-1), new MutableInt(ENTRY_TIMEOUT), + false); + } + + } + + public List entriesByDistance = new ArrayList<>(); + public int lastUpdate; + public boolean changed; + + public void tick() { + entriesByDistance.forEach(RoutingTableEntry::tick); + changed |= entriesByDistance.removeIf(RoutingTableEntry::invalid); + lastUpdate++; + } + + public boolean shouldAdvertise() { + return changed || lastUpdate > ENTRY_TIMEOUT - 20; + } + + public void receivePortInfo(String filter, BlockPos connection) { + insert(new RoutingTableEntry(filter, "*".equals(filter) ? 1000 : 0, connection, new MutableInt(PORT_ENTRY_TIMEOUT), true)); + } + + public BlockPos getExitFor(ItemStack box) { + for (RoutingTableEntry entry : entriesByDistance) + if (PackageItem.matchAddress(box, entry.port())) + return entry.nextConnection(); + return BlockPos.ZERO; + } + + public void advertiseTo(BlockPos connection, ChainConveyorRoutingTable otherTable) { + BlockPos backConnection = connection.multiply(-1); + for (RoutingTableEntry entry : entriesByDistance) + if (entry.endOfRoute() || !connection.equals(entry.nextConnection())) + otherTable.insert(entry.copyForNeighbour(connection)); + otherTable.entriesByDistance.removeIf(e -> e.timeout() + .intValue() < ENTRY_TIMEOUT && !e.endOfRoute() && backConnection.equals(e.nextConnection())); + } + + private void insert(RoutingTableEntry entry) { + int targetIndex = 0; + for (int i = 0; i < entriesByDistance.size(); i++) { + RoutingTableEntry otherEntry = entriesByDistance.get(i); + if (otherEntry.distance() > entry.distance()) + break; + if (otherEntry.port() + .equals(entry.port())) { + otherEntry.timeout.setValue(ENTRY_TIMEOUT); + return; + } + targetIndex = i + 1; + } + entriesByDistance.add(targetIndex, entry); + changed = true; + } + + public Collection createSummary() { + ArrayList list = new ArrayList<>(); + for (RoutingTableEntry entry : entriesByDistance) { + list.add(Component.literal(" [" + entry.distance() + "] " + entry.port())); + } + return list; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorShape.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorShape.java new file mode 100644 index 0000000000..3390903088 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorShape.java @@ -0,0 +1,164 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import javax.annotation.Nullable; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.trains.track.TrackBlockOutline; + +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public abstract class ChainConveyorShape { + + @Nullable + public abstract Vec3 intersect(Vec3 from, Vec3 to); + + public abstract float getChainPosition(Vec3 intersection); + + protected abstract void drawOutline(BlockPos anchor, PoseStack ms, VertexConsumer vb); + + public abstract Vec3 getVec(BlockPos anchor, float position); + + public static class ChainConveyorOBB extends ChainConveyorShape { + + BlockPos connection; + double yaw, pitch; + AABB bounds; + Vec3 pivot; + final double radius = 0.175; + VoxelShape voxelShape; + + Vec3[] linePoints; + + public ChainConveyorOBB(BlockPos connection, Vec3 start, Vec3 end) { + this.connection = connection; + Vec3 diff = end.subtract(start); + double d = diff.length(); + double dxz = diff.multiply(1, 0, 1) + .length(); + yaw = Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z); + pitch = Mth.RAD_TO_DEG * Mth.atan2(-diff.y, dxz); + bounds = new AABB(start, start).expandTowards(new Vec3(0, 0, d)) + .inflate(radius, radius, 0); + pivot = start; + voxelShape = Shapes.create(bounds); + } + + @Override + public Vec3 intersect(Vec3 from, Vec3 to) { + from = counterTransform(from); + to = counterTransform(to); + + Vec3 result = bounds.clip(from, to) + .orElse(null); + if (result == null) + return null; + + result = transform(result); + return result; + } + + private Vec3 counterTransform(Vec3 from) { + from = from.subtract(pivot); + from = VecHelper.rotate(from, -yaw, Axis.Y); + from = VecHelper.rotate(from, -pitch, Axis.X); + from = from.add(pivot); + return from; + } + + private Vec3 transform(Vec3 result) { + result = result.subtract(pivot); + result = VecHelper.rotate(result, pitch, Axis.X); + result = VecHelper.rotate(result, yaw, Axis.Y); + result = result.add(pivot); + return result; + } + + @Override + public void drawOutline(BlockPos anchor, PoseStack ms, VertexConsumer vb) { + TransformStack.of(ms) + .translate(pivot) + .rotateYDegrees((float) yaw) + .rotateXDegrees((float) pitch) + .translateBack(pivot); + TrackBlockOutline.renderShape(voxelShape, ms, vb, null); + } + + @Override + public float getChainPosition(Vec3 intersection) { + int dots = (int) Math.round(Vec3.atLowerCornerOf(connection) + .length() - 3); + double length = bounds.getZsize(); + double selection = Math.min(bounds.getZsize(), intersection.distanceTo(pivot)); + + double margin = length - dots; + selection = Mth.clamp(selection - margin, 0, length - margin * 2); + selection = Math.round(selection); + + return (float) (selection + margin + 0.025); + } + + @Override + public Vec3 getVec(BlockPos anchor, float position) { + float x = (float) bounds.getCenter().x; + float y = (float) bounds.getCenter().y; + Vec3 from = new Vec3(x, y, bounds.minZ); + Vec3 to = new Vec3(x, y, bounds.maxZ); + Vec3 point = from.lerp(to, Mth.clamp(position / from.distanceTo(to), 0, 1)); + point = transform(point); + return point.add(Vec3.atLowerCornerOf(anchor)); + } + } + + public static class ChainConveyorBB extends ChainConveyorShape { + + Vec3 lb, rb; + final double radius = 0.875; + AABB bounds; + + public ChainConveyorBB(Vec3 center) { + lb = center.add(0, 0, 0); + rb = center.add(0, 0.5, 0); + bounds = new AABB(lb, rb).inflate(1, 0, 1); + } + + @Override + public Vec3 intersect(Vec3 from, Vec3 to) { + return bounds.clip(from, to) + .orElse(null); + } + + @Override + public void drawOutline(BlockPos anchor, PoseStack ms, VertexConsumer vb) { + TrackBlockOutline.renderShape(AllShapes.CHAIN_CONVEYOR_INTERACTION, ms, vb, null); + } + + @Override + public float getChainPosition(Vec3 intersection) { + Vec3 diff = bounds.getCenter() + .subtract(intersection); + float angle = (float) (Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z) + 360 + 180) % 360; + float rounded = Math.round(angle / 45) * 45f; + return rounded; + } + + @Override + public Vec3 getVec(BlockPos anchor, float position) { + Vec3 point = bounds.getCenter(); + point = point.add(VecHelper.rotate(new Vec3(0, 0, radius), position, Axis.Y)); + return point.add(Vec3.atLowerCornerOf(anchor)) + .add(0, -.125, 0); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorVisual.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorVisual.java new file mode 100644 index 0000000000..aa9b7e9521 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorVisual.java @@ -0,0 +1,198 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.SingleAxisRotatingVisual; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.foundation.render.SpecialModels; + +import dev.engine_room.flywheel.api.visual.DynamicVisual; +import dev.engine_room.flywheel.api.visual.TickableVisual; +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.instance.InstanceTypes; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.model.Models; +import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual; +import dev.engine_room.flywheel.lib.visual.util.SmartRecycler; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.registries.ForgeRegistries; + +public class ChainConveyorVisual extends SingleAxisRotatingVisual implements SimpleDynamicVisual, SimpleTickableVisual { + + private final List guards = new ArrayList<>(); + + private final SmartRecycler boxes; + private final SmartRecycler rigging; + + public ChainConveyorVisual(VisualizationContext context, ChainConveyorBlockEntity blockEntity, float partialTick) { + super(context, blockEntity, partialTick, Models.partial(AllPartialModels.CHAIN_CONVEYOR_SHAFT)); + + setupGuards(); + + boxes = new SmartRecycler<>(key -> instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.PACKAGES.get(key))).createInstance()); + rigging = new SmartRecycler<>(key -> instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.PACKAGE_RIGGING.get(key))).createInstance()); + } + + @Override + public void update(float pt) { + super.update(pt); + + setupGuards(); + } + + @Override + public void tick(TickableVisual.Context context) { + blockEntity.tickBoxVisuals(); + } + + @Override + public void beginFrame(DynamicVisual.Context ctx) { + var partialTicks = ctx.partialTick(); + + boxes.resetCount(); + rigging.resetCount(); + + for (ChainConveyorPackage box : blockEntity.loopingPackages) + setupBoxVisual(blockEntity, box, partialTicks); + + for (Map.Entry> entry : blockEntity.travellingPackages.entrySet()) + for (ChainConveyorPackage box : entry.getValue()) + setupBoxVisual(blockEntity, box, partialTicks); + + boxes.discardExtra(); + rigging.discardExtra(); + } + + + private void setupBoxVisual(ChainConveyorBlockEntity be, ChainConveyorPackage box, float partialTicks) { + if (box.worldPosition == null) + return; + if (box.item == null || box.item.isEmpty()) + return; + + ChainConveyorPackage.ChainConveyorPackagePhysicsData physicsData = box.physicsData(be.getLevel()); + if (physicsData.prevPos == null) + return; + + Vec3 position = physicsData.prevPos.lerp(physicsData.pos, partialTicks); + Vec3 targetPosition = physicsData.prevTargetPos.lerp(physicsData.targetPos, partialTicks); + float yaw = AngleHelper.angleLerp(partialTicks, physicsData.prevYaw, physicsData.yaw); + Vec3 offset = + new Vec3(targetPosition.x - this.pos.getX(), targetPosition.y - this.pos.getY(), targetPosition.z - this.pos.getZ()); + + BlockPos containingPos = BlockPos.containing(position); + Level level = be.getLevel(); + int light = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, containingPos), + level.getBrightness(LightLayer.SKY, containingPos)); + + if (physicsData.modelKey == null) { + ResourceLocation key = ForgeRegistries.ITEMS.getKey(box.item.getItem()); + if (key == null) + return; + physicsData.modelKey = key; + } + + TransformedInstance rigBuffer = rigging.get(physicsData.modelKey); + TransformedInstance boxBuffer = boxes.get(physicsData.modelKey); + + Vec3 dangleDiff = VecHelper.rotate(targetPosition.add(0, 0.5, 0) + .subtract(position), -yaw, Direction.Axis.Y); + float zRot = Mth.wrapDegrees((float) Mth.atan2(-dangleDiff.x, dangleDiff.y) * Mth.RAD_TO_DEG) / 2; + float xRot = Mth.wrapDegrees((float) Mth.atan2(dangleDiff.z, dangleDiff.y) * Mth.RAD_TO_DEG) / 2; + zRot = Mth.clamp(zRot, -25, 25); + xRot = Mth.clamp(xRot, -25, 25); + + for (TransformedInstance buf : new TransformedInstance[] { rigBuffer, boxBuffer }) { + buf.setIdentityTransform(); + buf.translate(getVisualPosition()); + buf.translate(offset); + buf.translate(0, 10 / 16f, 0); + buf.rotateYDegrees(yaw); + + buf.rotateZDegrees(zRot); + buf.rotateXDegrees(xRot); + + if (physicsData.flipped && buf == rigBuffer) + buf.rotateYDegrees(180); + + buf.uncenter(); + buf.translate(0, -PackageItem.getHookDistance(box.item) + 7 / 16f, 0); + + buf.light(light); + + buf.setChanged(); + } + } + + private void deleteGuards() { + for (TransformedInstance guard : guards) { + guard.delete(); + } + guards.clear(); + } + + private void setupGuards() { + deleteGuards(); + + var wheelInstancer = instancerProvider().instancer(InstanceTypes.TRANSFORMED, SpecialModels.chunkDiffuse(AllPartialModels.CHAIN_CONVEYOR_WHEEL)); + var guardInstancer = instancerProvider().instancer(InstanceTypes.TRANSFORMED, SpecialModels.chunkDiffuse(AllPartialModels.CHAIN_CONVEYOR_GUARD)); + + TransformedInstance wheel = wheelInstancer.createInstance(); + + wheel.translate(getVisualPosition()) + .light(rotatingModel.light) + .setChanged(); + + guards.add(wheel); + + for (BlockPos blockPos : blockEntity.connections) { + ChainConveyorBlockEntity.ConnectionStats stats = blockEntity.connectionStats.get(blockPos); + if (stats == null) { + continue; + } + + Vec3 diff = stats.end() + .subtract(stats.start()); + double yaw = Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z); + + TransformedInstance guard = guardInstancer.createInstance(); + guard.translate(getVisualPosition()) + .center() + .rotateYDegrees((float) yaw) + .uncenter() + .light(rotatingModel.light) + .setChanged(); + + guards.add(guard); + } + } + + @Override + public void updateLight(float partialTick) { + super.updateLight(partialTick); + for (TransformedInstance guard : guards) { + relight(guard); + } + } + + @Override + protected void _delete() { + super._delete(); + deleteGuards(); + boxes.delete(); + rigging.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainPackageInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainPackageInteractionHandler.java new file mode 100644 index 0000000000..32796ed4de --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainPackageInteractionHandler.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.List; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.foundation.utility.RaycastHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.ForgeMod; + +public class ChainPackageInteractionHandler { + + public static boolean onUse() { + Minecraft mc = Minecraft.getInstance(); + MutableBoolean success = new MutableBoolean(false); + + ChainConveyorPackage.physicsDataCache.get(mc.level) + .asMap() + .forEach((i, data) -> { + if (success.booleanValue()) + return; + if (data == null || data.targetPos == null || data.beReference == null) + return; + AABB bounds = new AABB(data.targetPos, data.targetPos).move(0, -.25, 0) + .expandTowards(0, 0.5, 0) + .inflate(0.45); + + double range = mc.player.getAttribute(ForgeMod.BLOCK_REACH.get()) + .getValue() + 1; + Vec3 from = RaycastHelper.getTraceOrigin(mc.player); + Vec3 to = RaycastHelper.getTraceTarget(mc.player, range, from); + + if (bounds.clip(from, to) + .isEmpty()) + return; + + ChainConveyorBlockEntity ccbe = data.beReference.get(); + if (ccbe == null || ccbe.isRemoved()) + return; + + for (ChainConveyorPackage pckg : ccbe.getLoopingPackages()) { + if (pckg.netId == i) { + AllPackets.getChannel() + .sendToServer( + new ChainPackageInteractionPacket(ccbe.getBlockPos(), null, pckg.chainPosition, null)); + success.setTrue(); + return; + } + } + + for (BlockPos connection : ccbe.connections) { + List list = ccbe.travellingPackages.get(connection); + if (list == null) + continue; + for (ChainConveyorPackage pckg : list) { + if (pckg.netId == i) { + AllPackets.getChannel() + .sendToServer(new ChainPackageInteractionPacket(ccbe.getBlockPos(), connection, + pckg.chainPosition, null)); + success.setTrue(); + return; + } + } + } + + }); + + return success.booleanValue(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainPackageInteractionPacket.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainPackageInteractionPacket.java new file mode 100644 index 0000000000..c1e01c23ac --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainPackageInteractionPacket.java @@ -0,0 +1,112 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.List; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; + +public class ChainPackageInteractionPacket extends BlockEntityConfigurationPacket { + + private BlockPos selectedConnection; + private float chainPosition; + private ItemStack insertedPackage; + + public ChainPackageInteractionPacket(BlockPos pos, BlockPos selectedConnection, float chainPosition, + ItemStack insertedPackage) { + super(pos); + this.selectedConnection = selectedConnection == null ? BlockPos.ZERO : selectedConnection; + this.chainPosition = chainPosition; + this.insertedPackage = insertedPackage == null ? ItemStack.EMPTY : insertedPackage; + } + + public ChainPackageInteractionPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBlockPos(selectedConnection); + buffer.writeFloat(chainPosition); + buffer.writeItem(insertedPackage); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + selectedConnection = buffer.readBlockPos(); + chainPosition = buffer.readFloat(); + insertedPackage = buffer.readItem(); + } + + @Override + protected int maxRange() { + return AllConfigs.server().kinetics.maxChainConveyorLength.get() + 16; + } + + @Override + protected void applySettings(ChainConveyorBlockEntity be) {} + + @Override + protected void applySettings(ServerPlayer player, ChainConveyorBlockEntity be) { + if (insertedPackage.isEmpty()) { + + float bestDiff = Float.POSITIVE_INFINITY; + ChainConveyorPackage best = null; + List list = selectedConnection.equals(BlockPos.ZERO) ? be.loopingPackages + : be.travellingPackages.get(selectedConnection); + + if (list == null || list.isEmpty()) + return; + + for (ChainConveyorPackage liftPackage : list) { + float diff = Math.abs(selectedConnection == null + ? AngleHelper.getShortestAngleDiff(liftPackage.chainPosition, chainPosition) + : liftPackage.chainPosition - chainPosition); + if (diff > bestDiff) + continue; + bestDiff = diff; + best = liftPackage; + } + + if (best == null) + return; + + if (player.getMainHandItem() + .isEmpty()) + player.setItemInHand(InteractionHand.MAIN_HAND, best.item.copy()); + else + player.getInventory() + .placeItemBackInInventory(best.item.copy()); + + list.remove(best); + be.sendData(); + + return; + } + + ChainConveyorPackage chainConveyorPackage = new ChainConveyorPackage(chainPosition, insertedPackage); + if (!be.canAcceptPackagesFor(selectedConnection)) + return; + + if (!player.isCreative()) { + player.getMainHandItem() + .shrink(1); + if (player.getMainHandItem() + .isEmpty()) + player.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY); + } + + if (selectedConnection.equals(BlockPos.ZERO)) + be.addLoopingPackage(chainConveyorPackage); + else + be.addTravellingPackage(chainConveyorPackage, selectedConnection); + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ClientboundChainConveyorRidingPacket.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ClientboundChainConveyorRidingPacket.java new file mode 100644 index 0000000000..be2fb7c734 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ClientboundChainConveyorRidingPacket.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.Collection; +import java.util.UUID; + +import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.render.PlayerSkyhookRenderer; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class ClientboundChainConveyorRidingPacket extends SimplePacketBase { + + private final Collection uuids; + + public ClientboundChainConveyorRidingPacket(Collection uuids) { + this.uuids = uuids; + } + + public ClientboundChainConveyorRidingPacket(FriendlyByteBuf buffer) { + this.uuids = buffer.readList(FriendlyByteBuf::readUUID); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeCollection(uuids, FriendlyByteBuf::writeUUID); + } + + @Override + public boolean handle(NetworkEvent.Context context) { + context.enqueueWork(() -> { + PlayerSkyhookRenderer.updatePlayerList(this.uuids); + }); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ServerChainConveyorHandler.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ServerChainConveyorHandler.java new file mode 100644 index 0000000000..6e62826c21 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ServerChainConveyorHandler.java @@ -0,0 +1,64 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import java.util.Map; +import java.util.UUID; + +import com.simibubi.create.AllPackets; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectIterator; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.network.PacketDistributor; + +public class ServerChainConveyorHandler { + + + public static Object2IntMap hangingPlayers = new Object2IntOpenHashMap<>(); + + public static int ticks; + + public static void handleTTLPacket(Player player) { + int count = hangingPlayers.size(); + hangingPlayers.put(player.getUUID(), 20); + + if (hangingPlayers.size() != count) + sync(); + } + + public static void handleStopRidingPacket(Player player) { + if (hangingPlayers.removeInt(player.getUUID()) != 0) + sync(); + } + + public static void tick() { + ticks++; + + int before = hangingPlayers.size(); + + ObjectIterator> iterator = hangingPlayers.object2IntEntrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + int newTTL = entry.getValue() - 1; + if (newTTL <= 0) { + iterator.remove(); + } else { + entry.setValue(newTTL); + } + } + + int after = hangingPlayers.size(); + + if (ticks % 10 != 0 && before == after) + return; + + sync(); + + } + + public static void sync() { + ClientboundChainConveyorRidingPacket packet = new ClientboundChainConveyorRidingPacket(hangingPlayers.keySet()); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), packet); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ServerboundChainConveyorRidingPacket.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ServerboundChainConveyorRidingPacket.java new file mode 100644 index 0000000000..23defe3d7b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ServerboundChainConveyorRidingPacket.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.kinetics.chainConveyor; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public class ServerboundChainConveyorRidingPacket extends BlockEntityConfigurationPacket { + + private boolean stop; + + public ServerboundChainConveyorRidingPacket(BlockPos pos, boolean stop) { + super(pos); + this.stop = stop; + } + + public ServerboundChainConveyorRidingPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBoolean(stop); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + stop = buffer.readBoolean(); + } + + @Override + protected int maxRange() { + return AllConfigs.server().kinetics.maxChainConveyorLength.get() * 2; + } + + @Override + protected void applySettings(ChainConveyorBlockEntity be) {} + + @Override + protected void applySettings(ServerPlayer sender, ChainConveyorBlockEntity be) { + sender.fallDistance = 0; + sender.connection.aboveGroundTickCount = 0; + sender.connection.aboveGroundVehicleTickCount = 0; + + if (stop) + ServerChainConveyorHandler.handleStopRidingPacket(sender); + else + ServerChainConveyorHandler.handleTTLPacket(sender); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveBlock.java b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveBlock.java index 665a9efde9..33900b8d34 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveBlock.java @@ -1,15 +1,15 @@ package com.simibubi.create.content.kinetics.chainDrive; import com.simibubi.create.AllBlockEntityTypes; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -33,7 +33,7 @@ import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.material.PushReaction; public class ChainDriveBlock extends RotatedPillarKineticBlock - implements IBE, ITransformableBlock { + implements IBE, TransformableBlock { public static final Property PART = EnumProperty.create("part", Part.class); public static final BooleanProperty CONNECTED_ALONG_FIRST_COORDINATE = diff --git a/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlockEntity.java index 4c9381d1a2..35f308e42a 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlockEntity.java @@ -6,12 +6,12 @@ import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockRenderer.java index 985e3989d4..112957f5b8 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockRenderer.java @@ -5,11 +5,11 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity.Animation; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -36,8 +36,8 @@ public class CuckooClockRenderer extends KineticBlockEntityRenderer { BlockPos connectedPos = crafter1.getBlockPos() @@ -151,10 +152,9 @@ public class ConnectedInputHandler { private static void modifyAndUpdate(Level world, BlockPos pos, Consumer callback) { BlockEntity blockEntity = world.getBlockEntity(pos); - if (!(blockEntity instanceof MechanicalCrafterBlockEntity)) + if (!(blockEntity instanceof MechanicalCrafterBlockEntity crafter)) return; - MechanicalCrafterBlockEntity crafter = (MechanicalCrafterBlockEntity) blockEntity; callback.accept(crafter.input); crafter.setChanged(); crafter.connectivityChanged(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlock.java index 968608871f..6c8f5e6dd1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlock.java @@ -11,11 +11,11 @@ import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pointing; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.Pointing; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -122,7 +122,7 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock ConnectedInputHandler.toggleConnection(worldIn, pos, otherPos); } } - + super.onRemove(state, worldIn, pos, newState, isMoving); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlockEntity.java index 4dc940a642..2e27b7ff8d 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlockEntity.java @@ -21,10 +21,10 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction.EdgeInteractionBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Pointing; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.BlockFace; +import net.createmod.catnip.math.Pointing; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ItemParticleOption; @@ -203,6 +203,8 @@ public class MechanicalCrafterBlockEntity extends KineticBlockEntity { if (phaseBefore != phase && phase == Phase.CRAFTING) groupedItemsBeforeCraft = before; if (phaseBefore == Phase.EXPORTING && phase == Phase.WAITING) { + if (before.onlyEmptyItems()) + return; Direction facing = getBlockState().getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); Vec3 vec = Vec3.atLowerCornerOf(facing.getNormal()) .scale(.75) @@ -253,7 +255,7 @@ public class MechanicalCrafterBlockEntity extends KineticBlockEntity { return; if (RecipeGridHandler.getTargetingCrafter(this) != null) { phase = Phase.EXPORTING; - countDown = 1000; + countDown = groupedItems.onlyEmptyItems() ? 0 : 1000; sendData(); return; } @@ -305,12 +307,15 @@ public class MechanicalCrafterBlockEntity extends KineticBlockEntity { return; } + boolean empty = groupedItems.onlyEmptyItems(); Pointing pointing = getBlockState().getValue(MechanicalCrafterBlock.POINTING); groupedItems.mergeOnto(targetingCrafter.groupedItems, pointing); groupedItems = new GroupedItems(); float pitch = targetingCrafter.groupedItems.grid.size() * 1 / 16f + .5f; - AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, pitch); + + if (!empty) + AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, pitch); phase = Phase.WAITING; countDown = 0; @@ -476,7 +481,7 @@ public class MechanicalCrafterBlockEntity extends KineticBlockEntity { .isEmpty() || covered; } - protected void checkCompletedRecipe(boolean poweredStart) { + public void checkCompletedRecipe(boolean poweredStart) { if (getSpeed() == 0) return; if (level.isClientSide && !isVirtual()) @@ -497,7 +502,7 @@ public class MechanicalCrafterBlockEntity extends KineticBlockEntity { if (RecipeGridHandler.getPrecedingCrafters(this) .isEmpty()) { phase = Phase.ASSEMBLING; - countDown = 500; + countDown = 1; } sendData(); } @@ -514,7 +519,7 @@ public class MechanicalCrafterBlockEntity extends KineticBlockEntity { return; phase = Phase.ASSEMBLING; - countDown = Math.max(100, getCountDownSpeed() + 1); + countDown = 1; } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterRenderer.java index 146539b5c2..6bf59c6468 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterRenderer.java @@ -11,15 +11,15 @@ import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity.Phase; import com.simibubi.create.content.kinetics.crafter.RecipeGridHandler.GroupedItems; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Pointing; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.Pointing; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -170,7 +170,7 @@ public class MechanicalCrafterRenderer extends SafeBlockEntityRenderer visited = new HashSet<>(); frontier.add(Pair.of(root, null)); - boolean powered = false; boolean empty = false; boolean allEmpty = true; @@ -66,9 +65,6 @@ public class RecipeGridHandler { empty = true; else allEmpty = false; - if (poweredStart && current.getLevel() - .hasNeighborSignal(current.getBlockPos())) - powered = true; crafters.add(current); visited.add(current); @@ -81,7 +77,7 @@ public class RecipeGridHandler { frontier.add(Pair.of(preceding, current)); } - return empty && !powered || allEmpty ? null : crafters; + return empty && !poweredStart || allEmpty ? null : crafters; } public static MechanicalCrafterBlockEntity getTargetingCrafter(MechanicalCrafterBlockEntity crafter) { @@ -243,6 +239,13 @@ public class RecipeGridHandler { height = maxY - minY + 1; } + public boolean onlyEmptyItems() { + for (ItemStack stack : grid.values()) + if (!stack.isEmpty()) + return false; + return true; + } + } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/ShaftlessCogwheelVisual.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/ShaftlessCogwheelVisual.java deleted file mode 100644 index 2707f3795e..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/crafter/ShaftlessCogwheelVisual.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.simibubi.create.content.kinetics.crafter; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.base.KineticBlockEntity; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; - -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.model.Models; -import dev.engine_room.flywheel.lib.transform.TransformStack; -import net.minecraft.core.Direction; - -public class ShaftlessCogwheelVisual extends SingleRotatingVisual { - - public ShaftlessCogwheelVisual(VisualizationContext context, KineticBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Model model() { - Direction facing = blockState.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); - - return Models.partial(AllPartialModels.SHAFTLESS_COGWHEEL, facing, ShaftlessCogwheelVisual::rotateToFace); - } - - private static void rotateToFace(Direction facing, PoseStack stack) { - var stacker = TransformStack.of(stack) - .center(); - - if (facing.getAxis() == Direction.Axis.X) stacker.rotateZDegrees(90); - else if (facing.getAxis() == Direction.Axis.Z) stacker.rotateXDegrees(90); - - stacker.uncenter(); - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlock.java index ab8dd5da42..2639e3d6ab 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlock.java @@ -7,7 +7,6 @@ import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; @@ -150,9 +149,4 @@ public class HandCrankBlock extends DirectionalKineticBlock public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { return false; } - - public static Couple getSpeedRange() { - return Couple.create(32, 32); - } - } diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlockEntity.java index 3e9bab1353..7dd9927f9b 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlockEntity.java @@ -4,18 +4,17 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.lib.model.Models; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -49,9 +48,8 @@ public class HandCrankBlockEntity extends GeneratingKineticBlockEntity { @Override public float getGeneratedSpeed() { Block block = getBlockState().getBlock(); - if (!(block instanceof HandCrankBlock)) + if (!(block instanceof HandCrankBlock crank)) return 0; - HandCrankBlock crank = (HandCrankBlock) block; int speed = (inUse == 0 ? 0 : clockwise() ? -1 : 1) * crank.getRotationSpeed(); return convertToDirection(speed, getBlockState().getValue(HandCrankBlock.FACING)); } @@ -97,15 +95,7 @@ public class HandCrankBlockEntity extends GeneratingKineticBlockEntity { BlockState blockState = getBlockState(); Direction facing = blockState.getOptionalValue(HandCrankBlock.FACING) .orElse(Direction.UP); - return CachedBufferer.partialFacing(AllPartialModels.HAND_CRANK_HANDLE, blockState, facing.getOpposite()); - } - - @OnlyIn(Dist.CLIENT) - public Model getRenderedHandleInstance() { - BlockState blockState = getBlockState(); - Direction facing = blockState.getOptionalValue(HandCrankBlock.FACING) - .orElse(Direction.UP); - return Models.partial(AllPartialModels.HAND_CRANK_HANDLE, facing.getOpposite()); + return CachedBuffers.partialFacing(AllPartialModels.HAND_CRANK_HANDLE, blockState, facing.getOpposite()); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankVisual.java b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankVisual.java index 45f4ae30ca..2183e52438 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankVisual.java @@ -2,41 +2,42 @@ package com.simibubi.create.content.kinetics.crank; import java.util.function.Consumer; +import org.joml.Quaternionf; + +import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; import com.simibubi.create.content.kinetics.base.RotatingInstance; import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.render.VirtualRenderHelper; import dev.engine_room.flywheel.api.instance.Instance; -import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.properties.BlockStateProperties; public class HandCrankVisual extends KineticBlockEntityVisual implements SimpleDynamicVisual { - protected RotatingInstance rotatingModel; + private final RotatingInstance rotatingModel; private final TransformedInstance crank; - private final Direction facing; public HandCrankVisual(VisualizationContext modelManager, HandCrankBlockEntity blockEntity, float partialTick) { super(modelManager, blockEntity, partialTick); - facing = blockState.getValue(BlockStateProperties.FACING); - Model model = blockEntity.getRenderedHandleInstance(); - crank = instancerProvider().instancer(InstanceTypes.TRANSFORMED, model) + crank = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.HAND_CRANK_HANDLE)) .createInstance(); rotateCrank(partialTick); - if (blockEntity.shouldRenderShaft()) { - rotatingModel = instancerProvider().instancer(AllInstanceTypes.ROTATING, VirtualRenderHelper.blockModel(blockState)) - .createInstance(); - setup(rotatingModel); - } + rotatingModel = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.HAND_CRANK_BASE)) + .createInstance(); + + rotatingModel.setup(HandCrankVisual.this.blockEntity) + .setPosition(getVisualPosition()) + .rotateToFace(blockState.getValue(BlockStateProperties.FACING)) + .setChanged(); } @Override @@ -45,13 +46,14 @@ public class HandCrankVisual extends KineticBlockEntityVisual getSpeedRange() { - return Couple.create(32, 32); - } - } diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlockEntity.java index 0ad67c5d61..06c56b71d9 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlockEntity.java @@ -14,14 +14,11 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.VirtualRenderHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; -import dev.engine_room.flywheel.api.model.Model; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -31,10 +28,12 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -101,7 +100,7 @@ public class ValveHandleBlockEntity extends HandCrankBlockEntity { return (inUse > 0 && totalUseTicks > 0 ? Mth.lerp(Math.min(totalUseTicks, totalUseTicks - inUse + partialTicks) / (float) totalUseTicks, - startAngle, targetAngle) + startAngle, targetAngle) : targetAngle) * Mth.DEG_TO_RAD * (backwards ? -1 : 1) * step; } @@ -138,18 +137,13 @@ public class ValveHandleBlockEntity extends HandCrankBlockEntity { } @Override - protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {} - - @Override - @OnlyIn(Dist.CLIENT) - public SuperByteBuffer getRenderedHandle() { - return CachedBufferer.block(getBlockState()); + protected void copySequenceContextFrom(KineticBlockEntity sourceBE) { } @Override @OnlyIn(Dist.CLIENT) - public Model getRenderedHandleInstance() { - return VirtualRenderHelper.blockModel(getBlockState()); + public SuperByteBuffer getRenderedHandle() { + return CachedBuffers.block(getBlockState()); } @Override @@ -161,16 +155,16 @@ public class ValveHandleBlockEntity extends HandCrankBlockEntity { public static class ValveHandleScrollValueBehaviour extends ScrollValueBehaviour { public ValveHandleScrollValueBehaviour(SmartBlockEntity be) { - super(Lang.translateDirect("kinetics.valve_handle.rotated_angle"), be, new ValveHandleValueBox()); - withFormatter(v -> String.valueOf(Math.abs(v)) + Lang.translateDirect("generic.unit.degrees") + super(CreateLang.translateDirect("kinetics.valve_handle.rotated_angle"), be, new ValveHandleValueBox()); + withFormatter(v -> String.valueOf(Math.abs(v)) + CreateLang.translateDirect("generic.unit.degrees") .getString()); } @Override public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { - ImmutableList rows = ImmutableList.of(Components.literal("\u27f3") - .withStyle(ChatFormatting.BOLD), - Components.literal("\u27f2") + ImmutableList rows = ImmutableList.of(Component.literal("\u27f3") + .withStyle(ChatFormatting.BOLD), + Component.literal("\u27f2") .withStyle(ChatFormatting.BOLD)); return new ValueSettingsBoard(label, 180, 45, rows, new ValueSettingsFormatter(this::formatValue)); } @@ -189,13 +183,15 @@ public class ValveHandleBlockEntity extends HandCrankBlockEntity { } public MutableComponent formatValue(ValueSettings settings) { - return Lang.number(Math.max(1, Math.abs(settings.value()))) - .add(Lang.translateDirect("generic.unit.degrees")) + return CreateLang.number(Math.max(1, Math.abs(settings.value()))) + .add(CreateLang.translateDirect("generic.unit.degrees")) .component(); } @Override - public void onShortInteract(Player player, InteractionHand hand, Direction side) { + public void onShortInteract(Player player, InteractionHand hand, Direction side, BlockHitResult hitResult) { + if (getWorld().isClientSide) + return; BlockState blockState = blockEntity.getBlockState(); if (blockState.getBlock() instanceof ValveHandleBlock vhb) vhb.clicked(getWorld(), getPos(), blockState, player, hand); @@ -216,8 +212,8 @@ public class ValveHandleBlockEntity extends HandCrankBlockEntity { } @Override - public boolean testHit(BlockState state, Vec3 localHit) { - Vec3 offset = getLocalOffset(state); + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(level, pos, state); if (offset == null) return false; return localHit.distanceTo(offset) < scale / 1.5f; diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleVisual.java b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleVisual.java new file mode 100644 index 0000000000..5b46b98b9c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleVisual.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.kinetics.crank; + +import java.util.function.Consumer; + +import org.joml.Quaternionf; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; + +import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.instance.InstanceTypes; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.model.Models; +import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.minecraft.core.Direction; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class ValveHandleVisual extends KineticBlockEntityVisual implements SimpleDynamicVisual { + private final TransformedInstance crank; + + public ValveHandleVisual(VisualizationContext modelManager, HandCrankBlockEntity blockEntity, float partialTick) { + super(modelManager, blockEntity, partialTick); + + BlockState state = blockEntity.getBlockState(); + DyeColor color = null; + if (state != null && state.getBlock() instanceof ValveHandleBlock vhb) + color = vhb.color; + + crank = instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, + Models.partial( + color == null ? AllPartialModels.VALVE_HANDLE : AllPartialModels.DYED_VALVE_HANDLES.get(color))) + .createInstance(); + + rotateCrank(partialTick); + } + + @Override + public void beginFrame(Context ctx) { + rotateCrank(ctx.partialTick()); + } + + private void rotateCrank(float pt) { + var facing = blockState.getValue(BlockStateProperties.FACING); + float angle = blockEntity.getIndependentAngle(pt); + + crank.setIdentityTransform() + .translate(getVisualPosition()) + .center() + .rotate(angle, Direction.get(Direction.AxisDirection.POSITIVE, facing.getAxis())) + .rotate(new Quaternionf().rotateTo(0, 1, 0, facing.getStepX(), facing.getStepY(), facing.getStepZ())) + .uncenter() + .setChanged(); + } + + @Override + protected void _delete() { + crank.delete(); + } + + @Override + public void updateLight(float partialTick) { + relight(crank); + } + + @Override + public void collectCrumblingInstances(Consumer consumer) { + consumer.accept(crank); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlock.java index 2529a7ad13..3051adb4dd 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlock.java @@ -7,8 +7,8 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -185,7 +185,7 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements IBE public Class getBlockEntityClass() { return CrushingWheelBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.CRUSHING_WHEEL.get(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlockEntity.java index 9d7581083f..c384b06185 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlockEntity.java @@ -6,8 +6,8 @@ import com.simibubi.create.AllDamageTypes; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.damagesource.DamageSource; @@ -16,6 +16,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.event.entity.living.LivingDropsEvent; import net.minecraftforge.event.entity.living.LootingLevelEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -43,7 +44,7 @@ public class CrushingWheelBlockEntity extends KineticBlockEntity { public void fixControllers() { for (Direction d : Iterate.directions) ((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getLevel(), getBlockPos(), - d); + d); } @Override @@ -57,12 +58,14 @@ public class CrushingWheelBlockEntity extends KineticBlockEntity { fixControllers(); } + // This increases the drops when dropCustomDeathLoot is called, and LootingEnchantFunctionMixin increases the drops + // defined in the entity loot table @SubscribeEvent public static void crushingIsFortunate(LootingLevelEvent event) { DamageSource damageSource = event.getDamageSource(); if (damageSource == null || !damageSource.is(AllDamageTypes.CRUSH)) return; - event.setLootingLevel(2); //This does not currently increase mob drops. It seems like this only works for damage done by an entity. + event.setLootingLevel(2); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlock.java index 0310b06eea..355279f029 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlock.java @@ -6,8 +6,8 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlockEntity.java index 2381c2d76f..cb20f6d2f0 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlockEntity.java @@ -15,10 +15,10 @@ import com.simibubi.create.foundation.damageTypes.CreateDamageSources; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.sound.SoundScapes; import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -39,6 +39,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.Capability; @@ -114,10 +115,10 @@ public class CrushingWheelControllerBlockEntity extends SmartBlockEntity { .getStep(); Vec3 outSpeed = new Vec3((facing.getAxis() == Axis.X ? 0.25D : 0.0D) * offset, offset == 1 ? (facing.getAxis() == Axis.Y ? 0.5D : 0.0D) : 0.0D // Increased upwards speed so upwards - // crushing wheels shoot out the item - // properly. + // crushing wheels shoot out the item + // properly. , (facing.getAxis() == Axis.Z ? 0.25D : 0.0D) * offset); // No downwards speed, so downwards crushing wheels - // drop the items as before. + // drop the items as before. Vec3 outPos = centerPos.add((facing.getAxis() == Axis.X ? .55f * offset : 0f), (facing.getAxis() == Axis.Y ? .55f * offset : 0f), (facing.getAxis() == Axis.Z ? .55f * offset : 0f)); @@ -202,32 +203,32 @@ public class CrushingWheelControllerBlockEntity extends SmartBlockEntity { double movement = Math.max(-speed / 4f, -.5f) * -offset; processingEntity.setDeltaMovement( new Vec3(facing.getAxis() == Axis.X ? movement : xMotion, facing.getAxis() == Axis.Y ? movement : 0f // Do - // not - // move - // entities - // upwards - // or - // downwards - // for - // horizontal - // crushers, + // not + // move + // entities + // upwards + // or + // downwards + // for + // horizontal + // crushers, , facing.getAxis() == Axis.Z ? movement : zMotion)); // Or they'll only get their feet crushed. if (level.isClientSide) return; - if (!(processingEntity instanceof ItemEntity)) { + if (!(processingEntity instanceof ItemEntity itemEntity)) { Vec3 entityOutPos = outPos.add(facing.getAxis() == Axis.X ? .5f * offset : 0f, facing.getAxis() == Axis.Y ? .5f * offset : 0f, facing.getAxis() == Axis.Z ? .5f * offset : 0f); int crusherDamage = AllConfigs.server().kinetics.crushingDamage.get(); if (processingEntity instanceof LivingEntity) { if ((((LivingEntity) processingEntity).getHealth() - crusherDamage <= 0) // Takes LivingEntity instances - // as exception, so it can - // move them before it would - // kill them. + // as exception, so it can + // move them before it would + // kill them. && (((LivingEntity) processingEntity).hurtTime <= 0)) { // This way it can actually output the items - // to the right spot. + // to the right spot. processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z); } } @@ -238,7 +239,6 @@ public class CrushingWheelControllerBlockEntity extends SmartBlockEntity { return; } - ItemEntity itemEntity = (ItemEntity) processingEntity; itemEntity.setPickUpDelay(20); if (facing.getAxis() == Axis.Y) { if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) { @@ -301,8 +301,7 @@ public class CrushingWheelControllerBlockEntity extends SmartBlockEntity { for (int roll = 0; roll < rolls; roll++) { List rolledResults = recipe.get() .rollResults(); - for (int i = 0; i < rolledResults.size(); i++) { - ItemStack stack = rolledResults.get(i); + for (ItemStack stack : rolledResults) { ItemHelper.addToList(stack, list); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/BeltDeployerCallbacks.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/BeltDeployerCallbacks.java index e18b1d699a..14412862a1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/BeltDeployerCallbacks.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/BeltDeployerCallbacks.java @@ -113,6 +113,8 @@ public class BeltDeployerCallbacks { .collect(Collectors.toList()); blockEntity.award(AllAdvancements.DEPLOYER); + + transported.clearFanProcessingData(); TransportedItemStack left = transported.copy(); blockEntity.player.spawnedItemEffects = transported.stack.copy(); @@ -153,7 +155,7 @@ public class BeltDeployerCallbacks { if (recipe instanceof SandPaperPolishingRecipe) AllSoundEvents.SANDING_SHORT.playOnServer(world, pos, .35f, 1f); - blockEntity.sendData(); + blockEntity.notifyUpdate(); } private static void awardAdvancements(DeployerBlockEntity blockEntity, ItemStack created) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerActorVisual.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerActorVisual.java index f63a4372d3..2671bc025d 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerActorVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerActorVisual.java @@ -3,19 +3,15 @@ package com.simibubi.create.content.kinetics.deployer; import static com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; import static com.simibubi.create.content.kinetics.base.DirectionalKineticBlock.FACING; -import com.mojang.blaze3d.vertex.PoseStack; +import org.joml.Matrix4f; +import org.joml.Matrix4fc; + import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ActorVisual; -import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; import com.simibubi.create.content.kinetics.base.RotatingInstance; import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.render.VirtualRenderHelper; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; @@ -23,7 +19,10 @@ import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.model.baked.PartialModel; -import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; @@ -32,18 +31,16 @@ import net.minecraft.world.phys.Vec3; public class DeployerActorVisual extends ActorVisual { - private final PoseStack stack = new PoseStack(); Direction facing; boolean stationaryTimer; - float yRot; - float xRot; - float zRot; - TransformedInstance pole; TransformedInstance hand; RotatingInstance shaft; + Matrix4fc baseHandTransform; + Matrix4fc basePoleTransform; + public DeployerActorVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld, MovementContext context) { super(visualizationContext, simulationWorld, context); BlockState state = context.state; @@ -54,69 +51,76 @@ public class DeployerActorVisual extends ActorVisual { facing = state.getValue(FACING); boolean rotatePole = state.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; - yRot = AngleHelper.horizontalAngle(facing); - xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; - zRot = rotatePole ? 90 : 0; + float yRot = AngleHelper.horizontalAngle(facing); + float xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; + float zRot = rotatePole ? 90 : 0; pole = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.DEPLOYER_POLE)).createInstance(); hand = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(handPose)).createInstance(); - Direction.Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); - shaft = instancerProvider.instancer(AllInstanceTypes.ROTATING, VirtualRenderHelper.blockModel(KineticBlockEntityVisual.shaft(axis))) - .createInstance(); + Direction.Axis axis = KineticBlockEntityVisual.rotationAxis(state); + shaft = instancerProvider.instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT)) + .createInstance() + .rotateToFace(axis); int blockLight = localBlockLight(); shaft.setRotationAxis(axis) - .setPosition(context.localPos) - .light(blockLight, 0); + .setRotationOffset(KineticBlockEntityVisual.rotationOffset(state, axis, context.localPos)) + .setPosition(context.localPos) + .light(blockLight, 0) + .setChanged(); - pole.light(blockLight, 0); - hand.light(blockLight, 0); - } + pole.translate(context.localPos) + .center() + .rotate(yRot * Mth.DEG_TO_RAD, Direction.UP) + .rotate(xRot * Mth.DEG_TO_RAD, Direction.EAST) + .rotate(zRot * Mth.DEG_TO_RAD, Direction.SOUTH) + .uncenter() + .light(blockLight, 0) + .setChanged(); + + basePoleTransform = new Matrix4f(pole.pose); + + hand.translate(context.localPos) + .center() + .rotate(yRot * Mth.DEG_TO_RAD, Direction.UP) + .rotate(xRot * Mth.DEG_TO_RAD, Direction.EAST) + .uncenter() + .light(blockLight, 0) + .setChanged(); + + baseHandTransform = new Matrix4f(hand.pose); + } @Override public void beginFrame() { - double factor; - if (context.disabled) { - factor = 0; - } else if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { - factor = Mth.sin(AnimationTickHolder.getRenderTime() * .5f) * .25f + .25f; - } else { - Vec3 center = VecHelper.getCenterOf(BlockPos.containing(context.position)); - double distance = context.position.distanceTo(center); - double nextDistance = context.position.add(context.motion) - .distanceTo(center); - factor = .5f - Mth.clamp(Mth.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); - } + float distance = deploymentDistance(); - Vec3 offset = Vec3.atLowerCornerOf(facing.getNormal()).scale(factor); + pole.setTransform(basePoleTransform) + .translateZ(distance) + .setChanged(); - var tstack = TransformStack.of(stack); - stack.setIdentity(); - tstack.translate(context.localPos) - .translate(offset); + hand.setTransform(baseHandTransform) + .translateZ(distance) + .setChanged(); + } - transformModel(stack, pole, hand, yRot, xRot, zRot); - } - - static void transformModel(PoseStack stack, TransformedInstance pole, TransformedInstance hand, float yRot, float xRot, float zRot) { - var tstack = TransformStack.of(stack); - - tstack.center(); - tstack.rotate((float) ((yRot) / 180 * Math.PI), Direction.UP); - tstack.rotate((float) ((xRot) / 180 * Math.PI), Direction.EAST); - - stack.pushPose(); - tstack.rotate((float) ((zRot) / 180 * Math.PI), Direction.SOUTH); - tstack.uncenter(); - pole.setTransform(stack); - stack.popPose(); - - tstack.uncenter(); - - hand.setTransform(stack); - } + private float deploymentDistance() { + double factor; + if (context.disabled) { + factor = 0; + } else if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { + factor = Mth.sin(AnimationTickHolder.getRenderTime() * .5f) * .25f + .25f; + } else { + Vec3 center = VecHelper.getCenterOf(BlockPos.containing(context.position)); + double distance = context.position.distanceTo(center); + double nextDistance = context.position.add(context.motion) + .distanceTo(center); + factor = .5f - Mth.clamp(Mth.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); + } + return (float) factor; + } @Override protected void _delete() { diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerApplicationRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerApplicationRecipe.java index 79eca9ee0f..81ee1daa3b 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerApplicationRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerApplicationRecipe.java @@ -11,8 +11,7 @@ import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemb import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; @@ -57,10 +56,11 @@ public class DeployerApplicationRecipe extends ItemApplicationRecipe implements public Component getDescriptionForAssembly() { ItemStack[] matchingStacks = ingredients.get(1) .getItems(); - if (matchingStacks.length == 0) - return Components.literal("Invalid"); - return Lang.translateDirect("recipe.assembly.deploying_item", - Components.translatable(matchingStacks[0].getDescriptionId()).getString()); + if (matchingStacks.length == 0) { + return Component.literal("Invalid"); + } + return CreateLang.translateDirect("recipe.assembly.deploying_item", + Component.translatable(matchingStacks[0].getDescriptionId()).getString()); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlock.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlock.java index cb75731955..5129385024 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlock.java @@ -12,10 +12,10 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; import com.simibubi.create.content.processing.AssemblyOperatorUseContext; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlockEntity.java index c252b0ee0b..2179c83d91 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlockEntity.java @@ -24,19 +24,19 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; @@ -57,6 +57,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.MinecraftForge; @@ -339,8 +340,12 @@ public class DeployerBlockEntity extends KineticBlockEntity { DeployerHandler.activate(player, center, clickedPos, movementVector, mode); award(AllAdvancements.DEPLOYER); - if (player != null) + if (player != null) { + int count = heldItem.getCount(); heldItem = player.getMainHandItem(); + if (count != heldItem.getCount()) + setChanged(); + } } protected Vec3 getMovementVector() { @@ -491,22 +496,22 @@ public class DeployerBlockEntity extends KineticBlockEntity { @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - Lang.translate("tooltip.deployer.header") + CreateLang.translate("tooltip.deployer.header") .forGoggles(tooltip); - Lang.translate("tooltip.deployer." + (mode == Mode.USE ? "using" : "punching")) + CreateLang.translate("tooltip.deployer." + (mode == Mode.USE ? "using" : "punching")) .style(ChatFormatting.YELLOW) .forGoggles(tooltip); if (!heldItem.isEmpty()) - Lang.translate("tooltip.deployer.contains", Components.translatable(heldItem.getDescriptionId()) - .getString(), heldItem.getCount()) + CreateLang.translate("tooltip.deployer.contains", Component.translatable(heldItem.getDescriptionId()) + .getString(), heldItem.getCount()) .style(ChatFormatting.GREEN) .forGoggles(tooltip); float stressAtBase = calculateStressApplied(); if (StressImpact.isEnabled() && !Mth.equal(stressAtBase, 0)) { - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); addStressImpactStats(tooltip, stressAtBase); } @@ -552,7 +557,7 @@ public class DeployerBlockEntity extends KineticBlockEntity { if (heldItemMainhand.getItem() instanceof SandPaperItem) { sandpaperInv.setItem(0, stack); Optional> polishingRecipe = checkRecipe(AllRecipeTypes.SANDPAPER_POLISHING, sandpaperInv, level); - if (polishingRecipe.isPresent()){ + if (polishingRecipe.isPresent()) { return polishingRecipe.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFakePlayer.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFakePlayer.java index c8f0fdc5d6..761842d90b 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFakePlayer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFakePlayer.java @@ -9,7 +9,7 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; import com.mojang.authlib.GameProfile; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CKinetics; @@ -35,6 +35,7 @@ import net.minecraft.world.entity.monster.Creeper; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.UsernameCache; @@ -71,7 +72,7 @@ public class DeployerFakePlayer extends FakePlayer { @Override public Component getDisplayName() { - return Lang.translateDirect("block.deployer.damage_source_name"); + return CreateLang.translateDirect("block.deployer.damage_source_name"); } @Override @@ -121,8 +122,7 @@ public class DeployerFakePlayer extends FakePlayer { public static void deployerCollectsDropsFromKilledEntities(LivingDropsEvent event) { DamageSource source = event.getSource(); Entity trueSource = source.getEntity(); - if (trueSource != null && trueSource instanceof DeployerFakePlayer) { - DeployerFakePlayer fakePlayer = (DeployerFakePlayer) trueSource; + if (trueSource != null && trueSource instanceof DeployerFakePlayer fakePlayer) { event.getDrops() .forEach(stack -> fakePlayer.getInventory() .placeItemBackInInventory(stack.getItem())); @@ -158,7 +158,7 @@ public class DeployerFakePlayer extends FakePlayer { CKinetics.DeployerAggroSetting setting = AllConfigs.server().kinetics.ignoreDeployerAttacks.get(); - switch(setting) { + switch (setting) { case ALL -> event.setCanceled(true); case CREEPERS -> { if (mob instanceof Creeper) @@ -216,10 +216,12 @@ public class DeployerFakePlayer extends FakePlayer { } @Override - public void send(Packet packetIn) {} + public void send(Packet packetIn) { + } @Override - public void send(Packet p_243227_, @Nullable PacketSendListener p_243273_) {} + public void send(Packet p_243227_, @Nullable PacketSendListener p_243273_) { + } } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFilterSlot.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFilterSlot.java index 3c238eb794..dabaf1251c 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFilterSlot.java @@ -2,19 +2,21 @@ package com.simibubi.create.content.kinetics.deployer; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; public class DeployerFilterSlot extends ValueBoxTransform.Sided { @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Direction facing = state.getValue(DeployerBlock.FACING); Vec3 vec = VecHelper.voxelSpace(8f, 8f, 15.5f); @@ -37,7 +39,7 @@ public class DeployerFilterSlot extends ValueBoxTransform.Sided { } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { Direction facing = getSide(); float xRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0; float yRot = AngleHelper.horizontalAngle(facing) + 180; diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerHandler.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerHandler.java index 8d2cdac143..7f6a2eae67 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerHandler.java @@ -22,8 +22,8 @@ import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; import com.simibubi.create.content.trains.track.ITrackBlock; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; +import net.createmod.catnip.levelWrappers.WrappedLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -49,6 +49,7 @@ import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.MobBucketItem; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.ClipContext; @@ -67,6 +68,7 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.extensions.IForgeBaseRailBlock; import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock; @@ -75,7 +77,7 @@ import net.minecraftforge.eventbus.api.Event; public class DeployerHandler { - private static final class ItemUseWorld extends WrappedWorld { + private static final class ItemUseWorld extends WrappedLevel { private final Direction face; private final BlockPos pos; boolean rayMode = false; @@ -99,9 +101,9 @@ public class DeployerHandler { if (rayMode && (pos.relative(face.getOpposite(), 3) .equals(position) || pos.relative(face.getOpposite(), 1) - .equals(position))) + .equals(position))) return Blocks.BEDROCK.defaultBlockState(); - return world.getBlockState(position); + return level.getBlockState(position); } } @@ -111,8 +113,7 @@ public class DeployerHandler { .getBlock() == ((BlockItem) held.getItem()).getBlock()) return false; - if (held.getItem() instanceof BucketItem) { - BucketItem bucketItem = (BucketItem) held.getItem(); + if (held.getItem() instanceof BucketItem bucketItem) { Fluid fluid = bucketItem.getFluid(); if (fluid != Fluids.EMPTY && world.getFluidState(targetPos) .getType() == fluid) @@ -133,11 +134,11 @@ public class DeployerHandler { .addTransientAttributeModifiers(attributeModifiers); activateInner(player, vec, clickedPos, extensionVector, mode); player.getAttributes() - .addTransientAttributeModifiers(attributeModifiers); + .removeAttributeModifiers(attributeModifiers); } private static void activateInner(DeployerFakePlayer player, Vec3 vec, BlockPos clickedPos, Vec3 extensionVector, - Mode mode) { + Mode mode) { Vec3 rayOrigin = vec.add(extensionVector.scale(3 / 2f + 1 / 64f)); Vec3 rayTarget = vec.add(extensionVector.scale(5 / 2f - 1 / 64f)); @@ -169,15 +170,14 @@ public class DeployerHandler { if (cancelResult == null) { if (entity.interact(player, hand) .consumesAction()) { - if (entity instanceof AbstractVillager) { - AbstractVillager villager = ((AbstractVillager) entity); + if (entity instanceof AbstractVillager villager) { if (villager.getTradingPlayer() instanceof DeployerFakePlayer) villager.setTradingPlayer(null); } success = true; } else if (entity instanceof LivingEntity && stack.interactLivingEntity(player, (LivingEntity) entity, hand) - .consumesAction()) + .consumesAction()) success = true; } if (!success && entity instanceof Player playerEntity) { @@ -336,6 +336,10 @@ public class DeployerHandler { itemUseWorld = new ItemUseWorld(world, face, pos); InteractionResultHolder onItemRightClick = item.use(itemUseWorld, player, hand); + + if (onItemRightClick.getResult().consumesAction() && item instanceof MobBucketItem bucketItem) + bucketItem.checkExtraContent(player, world, stack, clickedPos); + ItemStack resultStack = onItemRightClick.getObject(); if (resultStack != stack || resultStack.getCount() != stack.getCount() || resultStack.getUseDuration() > 0 || resultStack.getDamageValue() != stack.getDamageValue()) { @@ -406,14 +410,14 @@ public class DeployerHandler { } public static InteractionResult safeOnUse(BlockState state, Level world, BlockPos pos, Player player, - InteractionHand hand, BlockHitResult ray) { + InteractionHand hand, BlockHitResult ray) { if (state.getBlock() instanceof BeehiveBlock) return safeOnBeehiveUse(state, world, pos, player, hand); return state.use(world, player, hand, ray); } protected static InteractionResult safeOnBeehiveUse(BlockState state, Level world, BlockPos pos, Player player, - InteractionHand hand) { + InteractionHand hand) { // <> BeehiveBlock#onUse BeehiveBlock block = (BeehiveBlock) state.getBlock(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java index f86cf76375..46861d0183 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java @@ -10,9 +10,9 @@ import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.mounted.MountedContraption; import com.simibubi.create.content.contraptions.render.ActorVisual; @@ -20,7 +20,6 @@ import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; import com.simibubi.create.content.logistics.filter.FilterItemStack; import com.simibubi.create.content.schematics.SchematicInstances; -import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.trains.entity.CarriageContraption; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; @@ -28,12 +27,13 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.levelWrappers.SchematicLevel; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -48,6 +48,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.items.IItemHandler; @@ -127,7 +128,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour { CompoundTag tag = filter.getTag(); if (!tag.getBoolean("Deployed")) return; - SchematicWorld schematicWorld = SchematicInstances.get(world, filter); + SchematicLevel schematicWorld = SchematicInstances.get(world, filter); if (schematicWorld == null) return; if (!schematicWorld.getBounds() @@ -144,7 +145,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour { ItemStack contextStack = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).stack; if (!context.contraption.hasUniversalCreativeCrate) { - IItemHandler itemHandler = context.contraption.getSharedInventory(); + IItemHandler itemHandler = context.contraption.getStorage().getAllItems(); for (ItemRequirement.StackRequirement required : requiredItems) { ItemStack stack = ItemHelper .extract(itemHandler, required::matches, ExtractionCountMode.EXACTLY, @@ -233,7 +234,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour { FilterItemStack filter = context.getFilterFromBE(); if (AllItems.SCHEMATIC.isIn(filter.item())) return; - ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(), + ItemStack held = ItemHelper.extract(context.contraption.getStorage().getAllItems(), stack -> filter.test(context.world, stack), 1, false); player.setItemInHand(InteractionHand.MAIN_HAND, held); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovingInteraction.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovingInteraction.java index 1c07c4972b..24ac25f1fc 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovingInteraction.java @@ -5,12 +5,12 @@ import java.util.UUID; import org.apache.commons.lang3.tuple.MutablePair; import com.simibubi.create.AllItems; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.behaviour.MovementContext; -import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import com.simibubi.create.content.contraptions.mounted.MountedContraption; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; @@ -28,7 +28,7 @@ public class DeployerMovingInteraction extends MovingInteractionBehaviour { .getActorAt(localPos); if (actor == null || actor.right == null) return false; - + MovementContext ctx = actor.right; ItemStack heldStack = player.getItemInHand(activeHand); if (heldStack.getItem() diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRenderer.java index d3f4e012be..a2d8cf25a7 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRenderer.java @@ -16,17 +16,17 @@ import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; @@ -50,7 +50,7 @@ public class DeployerRenderer extends SafeBlockEntityRenderer blocksAdded = new HashMap<>(); + + public CobbleGenLevel(Level level) { + super(level); + } + + public void clear() { + blocksAdded.clear(); + } + + @Override + public boolean setBlock(BlockPos pos, BlockState newState, int flags) { + blocksAdded.put(pos.immutable(), newState); + return true; + } + + @Override + public boolean setBlockAndUpdate(BlockPos pos, BlockState state) { + return setBlock(pos, state, 0); + } + + @Override + public void scheduleTick(BlockPos pos, Block block, int delay) {} + + @Override + public void scheduleTick(BlockPos pos, Block block, int delay, TickPriority priority) {} + + @Override + public void scheduleTick(BlockPos pos, Fluid fluid, int delay) {} + + @Override + public void scheduleTick(BlockPos pos, Fluid fluid, int delay, TickPriority priority) {} + + @Override + public void levelEvent(int type, BlockPos pos, int data) {} + + @Override + public void levelEvent(Player player, int type, BlockPos pos, int data) {} + + @Override + public void blockEvent(BlockPos pos, Block block, int eventID, int eventParam) {} + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/CobbleGenOptimisation.java b/src/main/java/com/simibubi/create/content/kinetics/drill/CobbleGenOptimisation.java new file mode 100644 index 0000000000..b2bdd6d00d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/CobbleGenOptimisation.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.kinetics.drill; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.fluid.FluidHelper; +import com.simibubi.create.foundation.mixin.accessor.FluidInteractionRegistryAccessor; + +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraftforge.fluids.FluidInteractionRegistry.FluidInteraction; +import net.minecraftforge.fluids.FluidInteractionRegistry.HasFluidInteraction; +import net.minecraftforge.fluids.FluidInteractionRegistry.InteractionInformation; +import net.minecraftforge.fluids.FluidType; + +public class CobbleGenOptimisation { + + static CobbleGenLevel cachedLevel; + + public record CobbleGenBlockConfiguration(List statesAroundDrill) { + } + + @Nullable + public static CobbleGenBlockConfiguration getConfig(LevelAccessor level, BlockPos drillPos, + Direction drillDirection) { + List list = new ArrayList<>(); + for (Direction side : Iterate.directions) { + BlockPos relative = drillPos.relative(drillDirection) + .relative(side); + if (level instanceof Level l && !l.isLoaded(relative)) + return null; + list.add(level.getBlockState(relative)); + } + return new CobbleGenBlockConfiguration(list); + } + + public static BlockState determineOutput(ServerLevel level, BlockPos pos, CobbleGenBlockConfiguration config) { + Map> interactions = FluidInteractionRegistryAccessor.getInteractions(); + Map> presentFluidTypes = new HashMap<>(); + + for (int i = 0; i < Iterate.directions.length; i++) { + if (config.statesAroundDrill.size() <= i) + break; + FluidState fluidState = config.statesAroundDrill.get(i) + .getFluidState(); + FluidType fluidType = fluidState.getFluidType(); + if (!fluidType.isAir() && interactions.get(fluidType) != null) + presentFluidTypes.put(fluidType, Pair.of(Iterate.directions[i], fluidState)); + } + + FluidInteraction interaction = null; + Pair affected = null; + + Search: for (Entry> type : presentFluidTypes.entrySet()) { + List list = interactions.get(type.getKey()); + FluidState state = FluidHelper.convertToFlowing(type.getValue() + .getSecond() + .getType()) + .defaultFluidState(); + + if (list == null) + continue; + for (Direction d : Iterate.horizontalDirections) { + for (InteractionInformation information : list) { + if (d == type.getValue() + .getFirst()) + continue; + BlockPos relative = pos.relative(d); + HasFluidInteraction predicate = information.predicate(); + if (!predicate.test(level, pos, relative, state)) + continue; + interaction = information.interaction(); + affected = Pair.of(d, state); + break Search; + } + } + } + + ServerLevel owLevel = level.getServer().getLevel(Level.OVERWORLD); + if (owLevel == null) + owLevel = level; + + if (cachedLevel == null || cachedLevel.getLevel() != owLevel) + cachedLevel = new CobbleGenLevel(level); + + BlockState result = Blocks.AIR.defaultBlockState(); + if (interaction == null) + return result; + + interaction.interact(cachedLevel, pos, pos.relative(affected.getFirst()), affected.getSecond()); + BlockState output = cachedLevel.blocksAdded.getOrDefault(pos, result); + cachedLevel.clear(); + + return output; + } + + public static void invalidateWorld(LevelAccessor world) { + if (cachedLevel != null && cachedLevel.getLevel() == world) + cachedLevel = null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillActorVisual.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillActorVisual.java index 0ebdad2e87..dab62f632b 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillActorVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillActorVisual.java @@ -1,66 +1,68 @@ package com.simibubi.create.content.kinetics.drill; -import org.joml.Quaternionf; - import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.contraptions.actors.ActorInstance; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ActorVisual; -import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.instance.InstanceTypes; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.Direction; -import net.minecraft.util.Mth; import net.minecraft.world.level.block.state.BlockState; public class DrillActorVisual extends ActorVisual { - ActorInstance drillHead; - private final Direction facing; + TransformedInstance drillHead; + private final Direction facing; - public DrillActorVisual(VisualizationContext visualizationContext, VirtualRenderWorld contraption, MovementContext context) { - super(visualizationContext, contraption, context); + private double rotation; + private double previousRotation; - BlockState state = context.state; + public DrillActorVisual(VisualizationContext visualizationContext, VirtualRenderWorld contraption, MovementContext context) { + super(visualizationContext, contraption, context); - facing = state.getValue(DrillBlock.FACING); + BlockState state = context.state; - Direction.Axis axis = facing.getAxis(); - float eulerX = AngleHelper.verticalAngle(facing); + facing = state.getValue(DrillBlock.FACING); - float eulerY; - if (axis == Direction.Axis.Y) - eulerY = 0; - else - eulerY = facing.toYRot() + ((axis == Direction.Axis.X) ? 180 : 0); + drillHead = instancerProvider.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.DRILL_HEAD)) + .createInstance(); + } - drillHead = instancerProvider.instancer(AllInstanceTypes.ACTOR, Models.partial(AllPartialModels.DRILL_HEAD)) - .createInstance(); + @Override + public void tick() { + previousRotation = rotation; - drillHead.setPosition(context.localPos) - .setBlockLight(localBlockLight()) - .setRotationOffset(0) - .setRotationAxis(0, 0, 1) - .setLocalRotation(new Quaternionf().rotationXYZ(eulerX * Mth.DEG_TO_RAD, eulerY * Mth.DEG_TO_RAD, 0)) - .setSpeed(getSpeed(facing)) - .setChanged(); - } + if (context.disabled + || VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())) + return; - @Override - public void beginFrame() { - drillHead.setSpeed(getSpeed(facing)) - .setChanged(); - } + float deg = context.getAnimationSpeed(); - protected float getSpeed(Direction facing) { - if (context.contraption.stalled || !VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())) - return context.getAnimationSpeed(); - return 0; - } + rotation += deg / 20; + + rotation %= 360; + } + + @Override + public void beginFrame() { + drillHead.setIdentityTransform() + .translate(context.localPos) + .center() + .rotateToFace(facing.getOpposite()) + .rotateZDegrees((float) getRotation()) + .uncenter() + .setChanged(); + } + + protected double getRotation() { + return AngleHelper.angleLerp(AnimationTickHolder.getPartialTicks(), previousRotation, rotation); + } @Override protected void _delete() { diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlock.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlock.java index 3a8095da42..08f94be8d1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlock.java @@ -11,10 +11,10 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlockEntity.java index e8b3ffb5f7..fc83233dcc 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlockEntity.java @@ -1,15 +1,33 @@ package com.simibubi.create.content.kinetics.drill; import com.simibubi.create.content.kinetics.base.BlockBreakingKineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.drill.CobbleGenOptimisation.CobbleGenBlockConfiguration; +import com.simibubi.create.content.logistics.chute.ChuteBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.HopperBlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; public class DrillBlockEntity extends BlockBreakingKineticBlockEntity { + private CobbleGenBlockConfiguration currentConfig; + private BlockState currentOutput; + public DrillBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); + currentOutput = Blocks.AIR.defaultBlockState(); } @Override @@ -17,4 +35,56 @@ public class DrillBlockEntity extends BlockBreakingKineticBlockEntity { return getBlockPos().relative(getBlockState().getValue(DrillBlock.FACING)); } + @Override + public void onBlockBroken(BlockState stateToBreak) { + if (!optimiseCobbleGen(stateToBreak)) + super.onBlockBroken(stateToBreak); + } + + public boolean optimiseCobbleGen(BlockState stateToBreak) { + DirectBeltInputBehaviour inv = + BlockEntityBehaviour.get(level, breakingPos.below(), DirectBeltInputBehaviour.TYPE); + BlockEntity blockEntityBelow = level.getBlockEntity(breakingPos.below()); + BlockEntity blockEntityAbove = level.getBlockEntity(breakingPos.above()); + + if (inv == null && !(blockEntityBelow instanceof HopperBlockEntity) + && !(blockEntityAbove instanceof ChuteBlockEntity chute && chute.getItemMotion() > 0)) + return false; + + CobbleGenBlockConfiguration config = + CobbleGenOptimisation.getConfig(level, worldPosition, getBlockState().getValue(DrillBlock.FACING)); + if (config == null) + return false; + if (!(level instanceof ServerLevel sl)) + return false; + + BlockPos breakingPos = getBreakingPos(); + if (!config.equals(currentConfig)) { + currentConfig = config; + currentOutput = CobbleGenOptimisation.determineOutput(sl, breakingPos, config); + } + + if (currentOutput.isAir() || !currentOutput.equals(stateToBreak)) + return false; + + if (inv != null) + for (ItemStack stack : Block.getDrops(stateToBreak, sl, breakingPos, null)) + inv.handleInsertion(stack, Direction.UP, false); + else if (blockEntityBelow instanceof HopperBlockEntity hbe) { + IItemHandler handler = hbe.getCapability(ForgeCapabilities.ITEM_HANDLER) + .orElse(null); + if (handler != null) + for (ItemStack stack : Block.getDrops(stateToBreak, sl, breakingPos, null)) + ItemHandlerHelper.insertItemStacked(handler, stack, false); + } else if (blockEntityAbove instanceof ChuteBlockEntity chute && chute.getItemMotion() > 0) { + for (ItemStack stack : Block.getDrops(stateToBreak, sl, breakingPos, null)) + if (chute.getItem() + .isEmpty()) + chute.setItem(stack, 0); + } + + level.levelEvent(2001, breakingPos, Block.getId(stateToBreak)); + return true; + } + } diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillMovementBehaviour.java index d98bb572c2..3e7517797f 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillMovementBehaviour.java @@ -8,11 +8,11 @@ import com.simibubi.create.content.contraptions.render.ActorVisual; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.BlockPos; import net.minecraft.world.damagesource.DamageSource; diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillRenderer.java index d4f59f6227..baf199fea6 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillRenderer.java @@ -4,13 +4,13 @@ import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -26,13 +26,13 @@ public class DrillRenderer extends KineticBlockEntityRenderer @Override protected SuperByteBuffer getRotatedModel(DrillBlockEntity be, BlockState state) { - return CachedBufferer.partialFacing(AllPartialModels.DRILL_HEAD, state); + return CachedBuffers.partialFacing(AllPartialModels.DRILL_HEAD, state); } public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, ContraptionMatrices matrices, MultiBufferSource buffer) { BlockState state = context.state; - SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.DRILL_HEAD, state); + SuperByteBuffer superBuffer = CachedBuffers.partial(AllPartialModels.DRILL_HEAD, state); Direction facing = state.getValue(DrillBlock.FACING); float speed = (float) (context.contraption.stalled diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillVisual.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillVisual.java deleted file mode 100644 index 1d5dbb60c1..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillVisual.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.simibubi.create.content.kinetics.drill; - -import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; - -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.model.Models; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class DrillVisual extends SingleRotatingVisual { - - public DrillVisual(VisualizationContext context, DrillBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Model model() { - Direction facing = blockEntity.getBlockState() - .getValue(BlockStateProperties.FACING); - return Models.partial(AllPartialModels.DRILL_HEAD, facing); - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrent.java b/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrent.java index 037ccd2686..735b62cea1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrent.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrent.java @@ -5,20 +5,20 @@ import java.util.Iterator; import java.util.List; import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllTags; import com.simibubi.create.content.decoration.copycat.CopycatBlock; import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes; import com.simibubi.create.content.kinetics.fan.processing.FanProcessing; import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -35,6 +35,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -74,7 +75,7 @@ public class AirCurrent { } protected void tickAffectedEntities(Level world) { - for (Iterator iterator = caughtEntities.iterator(); iterator.hasNext();) { + for (Iterator iterator = caughtEntities.iterator(); iterator.hasNext(); ) { Entity entity = iterator.next(); if (!entity.isAlive() || !entity.getBoundingBox() .intersects(bounds) || isPlayerCreativeFlying(entity)) { @@ -107,7 +108,7 @@ public class AirCurrent { FanProcessingType processingType = getTypeAt((float) entityDistance); - if (processingType == AllFanProcessingTypes.NONE) + if (processingType == null) continue; if (entity instanceof ItemEntity itemEntity) { @@ -128,8 +129,7 @@ public class AirCurrent { } public static boolean isPlayerCreativeFlying(Entity entity) { - if (entity instanceof Player) { - Player player = (Player) entity; + if (entity instanceof Player player) { return player.isCreative() && player.getAbilities().flying; } return false; @@ -140,6 +140,8 @@ public class AirCurrent { TransportedItemStackHandlerBehaviour handler = pair.getKey(); Level world = handler.getWorld(); FanProcessingType processingType = pair.getRight(); + if (processingType == null) + continue; handler.handleProcessingOnAllItems(transported -> { if (world.isClientSide) { @@ -176,7 +178,7 @@ public class AirCurrent { // Determine segments with transported fluids/gases segments.clear(); AirCurrentSegment currentSegment = null; - FanProcessingType type = AllFanProcessingTypes.NONE; + FanProcessingType type = null; int limit = getLimit(); int searchStart = pushing ? 1 : limit; @@ -187,7 +189,7 @@ public class AirCurrent { for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) { BlockPos currentPos = start.relative(direction, i); FanProcessingType newType = FanProcessingType.getAt(world, currentPos); - if (newType != AllFanProcessingTypes.NONE) { + if (newType != null) { type = newType; } if (currentSegment == null) { @@ -248,18 +250,18 @@ public class AirCurrent { if (shapeDepth == Double.POSITIVE_INFINITY) { continue; } - return Math.min((float) (i + shapeDepth + 1/32d), max); + return Math.min((float) (i + shapeDepth + 1 / 32d), max); } return max; } private static final double[][] DEPTH_TEST_COORDINATES = { - { 0.25, 0.25 }, - { 0.25, 0.75 }, - { 0.5, 0.5 }, - { 0.75, 0.25 }, - { 0.75, 0.75 } + {0.25, 0.25}, + {0.25, 0.75}, + {0.5, 0.5}, + {0.75, 0.25}, + {0.75, 0.75} }; // Finds the maximum depth of the shape when traveling in the given direction. @@ -320,7 +322,7 @@ public class AirCurrent { BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE); if (behaviour != null) { FanProcessingType type = FanProcessingType.getAt(world, pos); - if (type == AllFanProcessingTypes.NONE) + if (type == null) type = segmentType; affectedItemHandlers.add(Pair.of(behaviour, type)); } @@ -337,6 +339,7 @@ public class AirCurrent { .getEntities(null, bounds); } + @Nullable public FanProcessingType getTypeAt(float offset) { if (offset >= 0 && offset <= maxDistance) { if (pushing) { @@ -353,10 +356,11 @@ public class AirCurrent { } } } - return AllFanProcessingTypes.NONE; + return null; } private static class AirCurrentSegment { + @Nullable private FanProcessingType type; private int startOffset; private int endOffset; diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticle.java b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticle.java index cc22f3ba77..d7bd952a0e 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticle.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticle.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.kinetics.fan; import javax.annotation.Nonnull; +import javax.annotation.Nullable; -import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes; import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleProvider; @@ -78,7 +78,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle { motion = motion.scale(airCurrent.maxDistance - (distance - 1f)).scale(.5f); FanProcessingType type = getType(distance); - if (type == AllFanProcessingTypes.NONE) { + if (type == null) { setColor(0xEEEEEE); setAlpha(.25f); selectSprite((int) Mth.clamp((distance / airCurrent.maxDistance) * 8 + random.nextInt(4), @@ -100,9 +100,10 @@ public class AirFlowParticle extends SimpleAnimatedParticle { } } + @Nullable private FanProcessingType getType(double distance) { if (source.getAirCurrent() == null) - return AllFanProcessingTypes.NONE; + return null; return source.getAirCurrent().getTypeAt((float) distance); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticleData.java b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticleData.java index 9655950b93..8c7f28024d 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticleData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticleData.java @@ -14,21 +14,22 @@ import net.minecraft.core.Vec3i; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.network.FriendlyByteBuf; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class AirFlowParticleData implements ParticleOptions, ICustomParticleDataWithSprite { - - public static final Codec CODEC = RecordCodecBuilder.create(i -> - i.group( - Codec.INT.fieldOf("x").forGetter(p -> p.posX), - Codec.INT.fieldOf("y").forGetter(p -> p.posY), - Codec.INT.fieldOf("z").forGetter(p -> p.posZ)) - .apply(i, AirFlowParticleData::new)); - public static final ParticleOptions.Deserializer DESERIALIZER = new ParticleOptions.Deserializer() { + public static final Codec CODEC = RecordCodecBuilder.create(i -> + i.group( + Codec.INT.fieldOf("x").forGetter(p -> p.posX), + Codec.INT.fieldOf("y").forGetter(p -> p.posY), + Codec.INT.fieldOf("z").forGetter(p -> p.posZ)) + .apply(i, AirFlowParticleData::new)); + + public static final ParticleOptions.Deserializer DESERIALIZER = new ParticleOptions.Deserializer<>() { public AirFlowParticleData fromCommand(ParticleType particleTypeIn, StringReader reader) - throws CommandSyntaxException { + throws CommandSyntaxException { reader.expect(' '); int x = reader.readInt(); reader.expect(' '); @@ -82,7 +83,7 @@ public class AirFlowParticleData implements ParticleOptions, ICustomParticleData public Deserializer getDeserializer() { return DESERIALIZER; } - + @Override public Codec getCodec(ParticleType type) { return CODEC; @@ -94,4 +95,4 @@ public class AirFlowParticleData implements ParticleOptions, ICustomParticleData return AirFlowParticle.Factory::new; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlock.java b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlock.java index 1f670a1e0d..ed72e3b263 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlock.java @@ -4,8 +4,8 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.content.logistics.chute.AbstractChuteBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; +import net.createmod.catnip.levelWrappers.WrappedLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -63,7 +63,7 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements IBE getBlockEntityClass() { return EncasedFanBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.ENCASED_FAN.get(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlockEntity.java index 836b14a156..01750896d2 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlockEntity.java @@ -39,7 +39,7 @@ public class EncasedFanBlockEntity extends KineticBlockEntity implements IAirCur super.addBehaviours(behaviours); registerAwardables(behaviours, AllAdvancements.ENCASED_FAN, AllAdvancements.FAN_PROCESSING); } - + @Override protected void read(CompoundTag compound, boolean clientPacket) { super.read(compound, clientPacket); @@ -89,7 +89,7 @@ public class EncasedFanBlockEntity extends KineticBlockEntity implements IAirCur super.remove(); updateChute(); } - + @Override public boolean isSourceRemoved() { return remove; @@ -108,9 +108,8 @@ public class EncasedFanBlockEntity extends KineticBlockEntity implements IAirCur .isVertical()) return; BlockEntity poweredChute = level.getBlockEntity(worldPosition.relative(direction)); - if (!(poweredChute instanceof ChuteBlockEntity)) + if (!(poweredChute instanceof ChuteBlockEntity chuteBE)) return; - ChuteBlockEntity chuteBE = (ChuteBlockEntity) poweredChute; if (direction == Direction.DOWN) chuteBE.updatePull(); else diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanRenderer.java index 58286df27c..0efb5c1aaa 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanRenderer.java @@ -6,11 +6,11 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -37,9 +37,9 @@ public class EncasedFanRenderer extends KineticBlockEntityRenderer { direction = blockState.getValue(FACING); opposite = direction.getOpposite(); - shaft = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT_HALF, opposite)).createInstance(); - fan = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.ENCASED_FAN_INNER, opposite)) + shaft = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT_HALF)) + .createInstance(); + fan = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.ENCASED_FAN_INNER)) .createInstance(); - setup(shaft); - setup(fan, getFanSpeed()); + shaft.setup(blockEntity) + .setPosition(getVisualPosition()) + .rotateToFace(Direction.SOUTH, opposite) + .setChanged(); + + fan.setup(blockEntity, getFanSpeed()) + .setPosition(getVisualPosition()) + .rotateToFace(Direction.SOUTH, opposite) + .setChanged(); } private float getFanSpeed() { @@ -48,9 +56,11 @@ public class FanVisual extends KineticBlockEntityVisual { @Override public void update(float pt) { - updateRotation(shaft); - updateRotation(fan, getFanSpeed()); - } + shaft.setup(blockEntity) + .setChanged(); + fan.setup(blockEntity, getFanSpeed()) + .setChanged(); + } @Override public void updateLight(float partialTick) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlockEntity.java index 3bc5f1d58b..3e2cacabd9 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlockEntity.java @@ -6,9 +6,9 @@ import java.util.List; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; @@ -39,7 +39,8 @@ public class NozzleBlockEntity extends SmartBlockEntity { } @Override - public void addBehaviours(List behaviours) {} + public void addBehaviours(List behaviours) { + } @Override protected void write(CompoundTag compound, boolean clientPacket) { @@ -86,10 +87,10 @@ public class NozzleBlockEntity extends SmartBlockEntity { } } - for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { + for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext(); ) { Entity entity = iterator.next(); Vec3 diff = entity.position() - .subtract(center); + .subtract(center); if (!(entity instanceof Player) && level.isClientSide) continue; @@ -105,7 +106,7 @@ public class NozzleBlockEntity extends SmartBlockEntity { float factor = (entity instanceof ItemEntity) ? 1 / 128f : 1 / 32f; Vec3 pushVec = diff.normalize() - .scale((range - distance) * (pushing ? 1 : -1)); + .scale((range - distance) * (pushing ? 1 : -1)); entity.setDeltaMovement(entity.getDeltaMovement() .add(pushVec.scale(factor))); entity.fallDistance = 0; @@ -123,10 +124,9 @@ public class NozzleBlockEntity extends SmartBlockEntity { private float calcRange() { BlockEntity be = level.getBlockEntity(fanPos); - if (!(be instanceof IAirCurrentSource)) + if (!(be instanceof IAirCurrentSource source)) return 0; - IAirCurrentSource source = (IAirCurrentSource) be; if (source.getAirCurrent() == null) return 0; if (source.getSpeed() == 0) @@ -147,7 +147,7 @@ public class NozzleBlockEntity extends SmartBlockEntity { for (Entity entity : level.getEntitiesOfClass(Entity.class, bb)) { Vec3 diff = entity.position() - .subtract(center); + .subtract(center); double distance = diff.length(); if (distance > range || entity.isShiftKeyDown() || AirCurrent.isPlayerCreativeFlying(entity)) @@ -163,7 +163,7 @@ public class NozzleBlockEntity extends SmartBlockEntity { pushingEntities.add(entity); } - for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { + for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext(); ) { Entity entity = iterator.next(); if (entity.isAlive()) continue; @@ -172,7 +172,7 @@ public class NozzleBlockEntity extends SmartBlockEntity { if (!pushing && pushingEntities.size() > 256 && !level.isClientSide) { level.explode(null, center.x, center.y, center.z, 2, ExplosionInteraction.NONE); - for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { + for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext(); ) { Entity entity = iterator.next(); entity.discard(); iterator.remove(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/AllFanProcessingTypes.java b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/AllFanProcessingTypes.java index 515c892b08..5049b28db1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/AllFanProcessingTypes.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/AllFanProcessingTypes.java @@ -12,17 +12,19 @@ import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllFluidTags; import com.simibubi.create.Create; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe.HauntingWrapper; import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe.SplashingWrapper; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; import com.simibubi.create.foundation.recipe.RecipeApplier; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.DustParticleOptions; @@ -52,11 +54,11 @@ import net.minecraft.world.level.block.CampfireBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.RecipeWrapper; public class AllFanProcessingTypes { - public static final NoneType NONE = register("none", new NoneType()); public static final BlastingType BLASTING = register("blasting", new BlastingType()); public static final HauntingType HAUNTING = register("haunting", new HauntingType()); public static final SmokingType SMOKING = register("smoking", new SmokingType()); @@ -66,7 +68,6 @@ public class AllFanProcessingTypes { static { Object2ReferenceOpenHashMap map = new Object2ReferenceOpenHashMap<>(); - map.put("NONE", NONE); map.put("BLASTING", BLASTING); map.put("HAUNTING", HAUNTING); map.put("SMOKING", SMOKING); @@ -75,9 +76,11 @@ public class AllFanProcessingTypes { LEGACY_NAME_MAP = map; } - private static T register(String id, T type) { - FanProcessingTypeRegistry.register(Create.asResource(id), type); - return type; + private static T register(String name, T type) { + return Registry.register(CreateBuiltInRegistries.FAN_PROCESSING_TYPE, Create.asResource(name), type); + } + + public static void init() { } @Nullable @@ -85,9 +88,7 @@ public class AllFanProcessingTypes { return LEGACY_NAME_MAP.get(name); } - public static void register() { - } - + @Nullable public static FanProcessingType parseLegacy(String str) { FanProcessingType type = ofLegacyName(str); if (type != null) { @@ -142,10 +143,7 @@ public class AllFanProcessingTypes { } BlockState blockState = level.getBlockState(pos); if (AllBlockTags.FAN_PROCESSING_CATALYSTS_BLASTING.matches(blockState)) { - if (blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && !blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) { - return false; - } - return true; + return !blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) || blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING); } return false; } @@ -189,7 +187,7 @@ public class AllFanProcessingTypes { Optional smeltingRecipe = level.getRecipeManager() .getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, level) .filter(AllRecipeTypes.CAN_BE_AUTOMATED); - + if (!smeltingRecipe.isPresent()) { RECIPE_WRAPPER.setItem(0, stack); smeltingRecipe = level.getRecipeManager() @@ -199,7 +197,7 @@ public class AllFanProcessingTypes { if (smeltingRecipe.isPresent()) { RegistryAccess registryAccess = level.registryAccess(); if (!smokingRecipe.isPresent() || !ItemStack.isSameItem(smokingRecipe.get() - .getResultItem(registryAccess), + .getResultItem(registryAccess), smeltingRecipe.get() .getResultItem(registryAccess))) { return RecipeApplier.applyRecipeOn(level, stack, smeltingRecipe.get()); @@ -252,10 +250,7 @@ public class AllFanProcessingTypes { if (blockState.is(BlockTags.CAMPFIRES) && blockState.hasProperty(CampfireBlock.LIT) && !blockState.getValue(CampfireBlock.LIT)) { return false; } - if (blockState.hasProperty(LitBlazeBurnerBlock.FLAME_TYPE) && blockState.getValue(LitBlazeBurnerBlock.FLAME_TYPE) != LitBlazeBurnerBlock.FlameType.SOUL) { - return false; - } - return true; + return !blockState.hasProperty(LitBlazeBurnerBlock.FLAME_TYPE) || blockState.getValue(LitBlazeBurnerBlock.FLAME_TYPE) == LitBlazeBurnerBlock.FlameType.SOUL; } return false; } @@ -375,10 +370,7 @@ public class AllFanProcessingTypes { if (blockState.hasProperty(LitBlazeBurnerBlock.FLAME_TYPE) && blockState.getValue(LitBlazeBurnerBlock.FLAME_TYPE) != LitBlazeBurnerBlock.FlameType.REGULAR) { return false; } - if (blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != BlazeBurnerBlock.HeatLevel.SMOULDERING) { - return false; - } - return true; + return !blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) || blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) == BlazeBurnerBlock.HeatLevel.SMOULDERING; } return false; } @@ -394,7 +386,7 @@ public class AllFanProcessingTypes { Optional recipe = level.getRecipeManager() .getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level) .filter(AllRecipeTypes.CAN_BE_AUTOMATED); - + return recipe.isPresent(); } @@ -451,10 +443,7 @@ public class AllFanProcessingTypes { return true; } BlockState blockState = level.getBlockState(pos); - if (AllBlockTags.FAN_PROCESSING_CATALYSTS_SPLASHING.matches(blockState)) { - return true; - } - return false; + return AllBlockTags.FAN_PROCESSING_CATALYSTS_SPLASHING.matches(blockState); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessing.java b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessing.java index 853ae9f64d..6836ba9157 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessing.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessing.java @@ -3,11 +3,13 @@ package com.simibubi.create.content.kinetics.fan.processing; import java.util.ArrayList; import java.util.List; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -93,7 +95,11 @@ public class FanProcessing { CompoundTag processing = createData.getCompound("Processing"); if (!processing.contains("Type") || AllFanProcessingTypes.parseLegacy(processing.getString("Type")) != type) { - processing.putString("Type", FanProcessingTypeRegistry.getIdOrThrow(type).toString()); + ResourceLocation key = CreateBuiltInRegistries.FAN_PROCESSING_TYPE.getKey(type); + if (key == null) + throw new IllegalArgumentException("Could not get id for FanProcessingType " + type + "!"); + + processing.putString("Type", key.toString()); int timeModifierForStackSize = ((entity.getItem() .getCount() - 1) / 16) + 1; int processingTime = diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingType.java b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingType.java index e0a47d4c56..6ef09a0a42 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingType.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingType.java @@ -4,6 +4,8 @@ import java.util.List; import org.jetbrains.annotations.Nullable; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; + import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.resources.ResourceLocation; @@ -29,25 +31,19 @@ public interface FanProcessingType { void affectEntity(Entity entity, Level level); + @Nullable static FanProcessingType parse(String str) { - ResourceLocation id = ResourceLocation.tryParse(str); - if (id == null) { - return AllFanProcessingTypes.NONE; - } - FanProcessingType type = FanProcessingTypeRegistry.getType(id); - if (type == null) { - return AllFanProcessingTypes.NONE; - } - return type; + return CreateBuiltInRegistries.FAN_PROCESSING_TYPE.get(ResourceLocation.tryParse(str)); } + @Nullable static FanProcessingType getAt(Level level, BlockPos pos) { for (FanProcessingType type : FanProcessingTypeRegistry.getSortedTypesView()) { if (type.isValidAt(level, pos)) { return type; } } - return AllFanProcessingTypes.NONE; + return null; } interface AirFlowParticleAccess { diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingTypeRegistry.java b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingTypeRegistry.java index 0e177a012a..74d7bff5d2 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingTypeRegistry.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/processing/FanProcessingTypeRegistry.java @@ -2,67 +2,29 @@ package com.simibubi.create.content.kinetics.fan.processing; import java.util.Collections; import java.util.List; -import java.util.Map; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; + +import com.simibubi.create.api.registry.CreateBuiltInRegistries; -import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; -import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ReferenceArrayList; -import net.minecraft.resources.ResourceLocation; public class FanProcessingTypeRegistry { - private static final Map TYPES = new Object2ReferenceOpenHashMap<>(); - private static final Map IDS = new Reference2ObjectOpenHashMap<>(); - private static final List SORTED_TYPES = new ReferenceArrayList<>(); - private static final List SORTED_TYPES_VIEW = Collections.unmodifiableList(SORTED_TYPES); - - public static void register(ResourceLocation id, FanProcessingType type) { - if (TYPES.put(id, type) != null) { - throw new IllegalArgumentException("Tried to override FanProcessingType registration for id '" + id + "'. This is not supported!"); - } - ResourceLocation prevId = IDS.put(type, id); - if (prevId != null) { - throw new IllegalArgumentException("Tried to register same FanProcessingType instance for multiple ids '" + prevId + "' and '" + id + "'. This is not supported!"); - } - insertSortedType(type, id); - } - - private static void insertSortedType(FanProcessingType type, ResourceLocation id) { - int index = Collections.binarySearch(SORTED_TYPES, type, (type1, type2) -> type2.getPriority() - type1.getPriority()); - if (index >= 0) { - throw new IllegalStateException(); - } - SORTED_TYPES.add(-index - 1, type); - } - - @Nullable - public static FanProcessingType getType(ResourceLocation id) { - return TYPES.get(id); - } - - public static FanProcessingType getTypeOrThrow(ResourceLocation id) { - FanProcessingType type = getType(id); - if (type == null) { - throw new IllegalArgumentException("Could not get FanProcessingType for id '" + id + "'!"); - } - return type; - } - - @Nullable - public static ResourceLocation getId(FanProcessingType type) { - return IDS.get(type); - } - - public static ResourceLocation getIdOrThrow(FanProcessingType type) { - ResourceLocation id = getId(type); - if (id == null) { - throw new IllegalArgumentException("Could not get id for FanProcessingType " + type + "!"); - } - return id; - } + private static List sortedTypes = null; + @UnmodifiableView + private static List sortedTypesView = null; + @UnmodifiableView public static List getSortedTypesView() { - return SORTED_TYPES_VIEW; + if (sortedTypes == null) { + sortedTypes = new ReferenceArrayList<>(); + + CreateBuiltInRegistries.FAN_PROCESSING_TYPE.forEach(sortedTypes::add); + sortedTypes.sort((t1, t2) -> t2.getPriority() - t1.getPriority()); + + sortedTypesView = Collections.unmodifiableList(sortedTypes); + } + + return sortedTypesView; } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlockEntity.java index 63afa38e66..85e17589ee 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlockEntity.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.kinetics.flywheel; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.entity.BlockEntityType; diff --git a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelRenderer.java index 047f649c3e..ba9bfbf2f8 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelRenderer.java @@ -3,11 +3,11 @@ package com.simibubi.create.content.kinetics.flywheel; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -38,7 +38,7 @@ public class FlywheelRenderer extends KineticBlockEntityRenderer implements SimpleDynamicVisual { @@ -24,14 +26,32 @@ public class FlywheelVisual extends KineticBlockEntityVisual tooltip, boolean isPlayerSneaking) { - Lang.translate("gui.gauge.info_header").forGoggles(tooltip); + CreateLang.translate("gui.gauge.info_header").forGoggles(tooltip); return true; } diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeRenderer.java index fad7ef4125..9d23c235af 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeRenderer.java @@ -5,12 +5,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.ShaftRenderer; import com.simibubi.create.content.kinetics.gauge.GaugeBlock.Type; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -46,8 +46,8 @@ public class GaugeRenderer extends ShaftRenderer { PartialModel partialModel = (type == Type.SPEED ? AllPartialModels.GAUGE_HEAD_SPEED : AllPartialModels.GAUGE_HEAD_STRESS); SuperByteBuffer headBuffer = - CachedBufferer.partial(partialModel, gaugeState); - SuperByteBuffer dialBuffer = CachedBufferer.partial(AllPartialModels.GAUGE_DIAL, gaugeState); + CachedBuffers.partial(partialModel, gaugeState); + SuperByteBuffer dialBuffer = CachedBuffers.partial(AllPartialModels.GAUGE_DIAL, gaugeState); float dialPivot = 5.75f / 16; float progress = Mth.lerp(partialTicks, be.prevDialState, be.dialState); diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeShaper.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeShaper.java index e149f11254..6f9f59520c 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeShaper.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeShaper.java @@ -3,8 +3,8 @@ package com.simibubi.create.content.kinetics.gauge; import java.util.Arrays; import com.simibubi.create.AllShapes; -import com.simibubi.create.foundation.utility.VoxelShaper; +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.Direction; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; @@ -29,4 +29,4 @@ public class GaugeShaper extends VoxelShaper { public VoxelShape get(Direction direction, boolean axisAlong) { return (axisAlong ? axisTrue : axisFalse).get(direction); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeVisual.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeVisual.java index 4b4b0404e8..ede4ceeb6d 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeVisual.java @@ -6,9 +6,6 @@ import java.util.function.Consumer; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.ShaftVisual; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.Instancer; @@ -20,6 +17,9 @@ import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.transform.TransformStack; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.Direction; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/SpeedGaugeBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/SpeedGaugeBlockEntity.java index 0a59523a38..3b483818db 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/gauge/SpeedGaugeBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/SpeedGaugeBlockEntity.java @@ -9,10 +9,10 @@ import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.theme.Color; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -26,7 +26,7 @@ import net.minecraftforge.common.util.LazyOptional; public class SpeedGaugeBlockEntity extends GaugeBlockEntity { public AbstractComputerBehaviour computerBehaviour; - + public SpeedGaugeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } @@ -72,7 +72,7 @@ public class SpeedGaugeBlockEntity extends GaugeBlockEntity { @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { super.addToGoggleTooltip(tooltip, isPlayerSneaking); - Lang.translate("gui.speedometer.title") + CreateLang.translate("gui.speedometer.title") .style(ChatFormatting.GRAY) .forGoggles(tooltip); SpeedLevel.getFormattedSpeedText(speed, isOverStressed()) diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/StressGaugeBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/StressGaugeBlockEntity.java index b0251d0584..881ba243e7 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/gauge/StressGaugeBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/StressGaugeBlockEntity.java @@ -12,10 +12,10 @@ import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.LangBuilder; +import net.createmod.catnip.theme.Color; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -30,7 +30,7 @@ import net.minecraftforge.common.util.LazyOptional; public class StressGaugeBlockEntity extends GaugeBlockEntity { public AbstractComputerBehaviour computerBehaviour; - + static BlockPos lastSent; public StressGaugeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { @@ -92,33 +92,33 @@ public class StressGaugeBlockEntity extends GaugeBlockEntity { double capacity = getNetworkCapacity(); double stressFraction = getNetworkStress() / (capacity == 0 ? 1 : capacity); - Lang.translate("gui.stressometer.title") + CreateLang.translate("gui.stressometer.title") .style(ChatFormatting.GRAY) .forGoggles(tooltip); if (getTheoreticalSpeed() == 0) - Lang.text(TooltipHelper.makeProgressBar(3, 0)) + CreateLang.text(TooltipHelper.makeProgressBar(3, 0)) .translate("gui.stressometer.no_rotation") .style(ChatFormatting.DARK_GRAY) .forGoggles(tooltip); else { StressImpact.getFormattedStressText(stressFraction) .forGoggles(tooltip); - Lang.translate("gui.stressometer.capacity") + CreateLang.translate("gui.stressometer.capacity") .style(ChatFormatting.GRAY) .forGoggles(tooltip); double remainingCapacity = capacity - getNetworkStress(); - LangBuilder su = Lang.translate("generic.unit.stress"); - LangBuilder stressTip = Lang.number(remainingCapacity) + LangBuilder su = CreateLang.translate("generic.unit.stress"); + LangBuilder stressTip = CreateLang.number(remainingCapacity) .add(su) .style(StressImpact.of(stressFraction) .getRelativeColor()); if (remainingCapacity != capacity) stressTip.text(ChatFormatting.GRAY, " / ") - .add(Lang.number(capacity) + .add(CreateLang.number(capacity) .add(su) .style(ChatFormatting.DARK_GRAY)); diff --git a/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxRenderer.java index 4f0f4854d0..efb3917ddd 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxRenderer.java @@ -3,12 +3,12 @@ package com.simibubi.create.content.kinetics.gearbox; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -37,7 +37,7 @@ public class GearboxRenderer extends KineticBlockEntityRenderer { - protected final EnumMap keys; - protected Direction sourceFacing; + protected final EnumMap keys = new EnumMap<>(Direction.class); + protected Direction sourceFacing; - public GearboxVisual(VisualizationContext context, GearboxBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); + public GearboxVisual(VisualizationContext context, GearboxBlockEntity blockEntity, float partialTick) { + super(context, blockEntity, partialTick); - keys = new EnumMap<>(Direction.class); + final Direction.Axis boxAxis = blockState.getValue(BlockStateProperties.AXIS); - final Direction.Axis boxAxis = blockState.getValue(BlockStateProperties.AXIS); + updateSourceFacing(); - int blockLight = level.getBrightness(LightLayer.BLOCK, pos); - int skyLight = level.getBrightness(LightLayer.SKY, pos); - updateSourceFacing(); + var instancer = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT_HALF)); - for (Direction direction : Iterate.directions) { + for (Direction direction : Iterate.directions) { final Direction.Axis axis = direction.getAxis(); - if (boxAxis == axis) + if (boxAxis == axis) { continue; + } - RotatingInstance key = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT_HALF, direction)) - .createInstance(); + RotatingInstance instance = instancer.createInstance(); - key.setRotationAxis(axis) - .setRotationalSpeed(getSpeed(direction)) - .setRotationOffset(getRotationOffset(axis)).setColor(blockEntity) - .setPosition(getVisualPosition()) - .light(blockLight, skyLight) - .setChanged(); + instance.setup(blockEntity, axis, getSpeed(direction)) + .setPosition(getVisualPosition()) + .rotateToFace(Direction.SOUTH, direction) + .setChanged(); - keys.put(direction, key); - } - } + keys.put(direction, instance); + } + } - private float getSpeed(Direction direction) { - float speed = blockEntity.getSpeed(); + private float getSpeed(Direction direction) { + float speed = blockEntity.getSpeed(); - if (speed != 0 && sourceFacing != null) { - if (sourceFacing.getAxis() == direction.getAxis()) - speed *= sourceFacing == direction ? 1 : -1; - else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) - speed *= -1; - } - return speed; - } + if (speed != 0 && sourceFacing != null) { + if (sourceFacing.getAxis() == direction.getAxis()) + speed *= sourceFacing == direction ? 1 : -1; + else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) + speed *= -1; + } + return speed; + } - protected void updateSourceFacing() { - if (blockEntity.hasSource()) { - BlockPos source = blockEntity.source.subtract(pos); - sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ()); - } else { - sourceFacing = null; - } - } + protected void updateSourceFacing() { + if (blockEntity.hasSource()) { + BlockPos source = blockEntity.source.subtract(pos); + sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ()); + } else { + sourceFacing = null; + } + } - @Override - public void update(float pt) { - updateSourceFacing(); - for (Map.Entry key : keys.entrySet()) { - Direction direction = key.getKey(); - Direction.Axis axis = direction.getAxis(); + @Override + public void update(float pt) { + updateSourceFacing(); + for (Map.Entry key : keys.entrySet()) { + Direction direction = key.getKey(); + Direction.Axis axis = direction.getAxis(); - updateRotation(key.getValue(), axis, getSpeed(direction)); - } - } + key.getValue() + .setup(blockEntity, axis, getSpeed(direction)) + .setChanged(); + } + } - @Override - public void updateLight(float partialTick) { - relight(keys.values().toArray(FlatLit[]::new)); - } + @Override + public void updateLight(float partialTick) { + relight(keys.values().toArray(FlatLit[]::new)); + } - @Override - protected void _delete() { - keys.values().forEach(AbstractInstance::delete); - keys.clear(); - } + @Override + protected void _delete() { + keys.values().forEach(AbstractInstance::delete); + keys.clear(); + } @Override public void collectCrumblingInstances(Consumer consumer) { keys.values() - .forEach(consumer); + .forEach(consumer); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/gearbox/VerticalGearboxItem.java b/src/main/java/com/simibubi/create/content/kinetics/gearbox/VerticalGearboxItem.java index 6f59a1215e..faa684ecb2 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/gearbox/VerticalGearboxItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gearbox/VerticalGearboxItem.java @@ -4,8 +4,8 @@ import java.util.Map; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.kinetics.base.IRotate; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -23,7 +23,7 @@ public class VerticalGearboxItem extends BlockItem { public VerticalGearboxItem(Properties builder) { super(AllBlocks.GEARBOX.get(), builder); } - + @Override public String getDescriptionId() { return "item.create.vertical_gearbox"; diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/AllArmInteractionPointTypes.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/AllArmInteractionPointTypes.java index d6d7c6c0c6..fae3af7fdf 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/AllArmInteractionPointTypes.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/AllArmInteractionPointTypes.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.kinetics.mechanicalArm; import java.util.Optional; -import java.util.function.Function; import javax.annotation.Nullable; @@ -9,6 +8,7 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltBlock; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; @@ -32,16 +32,15 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.Registry; import net.minecraft.core.Vec3i; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Containers; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.WorldlyContainer; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.RecordItem; @@ -58,44 +57,42 @@ import net.minecraft.world.level.block.entity.JukeboxBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.wrapper.SidedInvWrapper; public class AllArmInteractionPointTypes { + static { + register("basin", new BasinType()); + register("belt", new BeltType()); + register("blaze_burner", new BlazeBurnerType()); + register("chute", new ChuteType()); + register("crafter", new CrafterType()); + register("crushing_wheels", new CrushingWheelsType()); + register("deployer", new DeployerType()); + register("depot", new DepotType()); + register("funnel", new FunnelType()); + register("millstone", new MillstoneType()); + register("packager", new PackagerType()); + register("saw", new SawType()); - public static final BasinType BASIN = register("basin", BasinType::new); - public static final BeltType BELT = register("belt", BeltType::new); - public static final BlazeBurnerType BLAZE_BURNER = register("blaze_burner", BlazeBurnerType::new); - public static final ChuteType CHUTE = register("chute", ChuteType::new); - public static final CrafterType CRAFTER = register("crafter", CrafterType::new); - public static final CrushingWheelsType CRUSHING_WHEELS = register("crushing_wheels", CrushingWheelsType::new); - public static final DeployerType DEPLOYER = register("deployer", DeployerType::new); - public static final DepotType DEPOT = register("depot", DepotType::new); - public static final FunnelType FUNNEL = register("funnel", FunnelType::new); - public static final MillstoneType MILLSTONE = register("millstone", MillstoneType::new); - public static final SawType SAW = register("saw", SawType::new); - - public static final CampfireType CAMPFIRE = register("campfire", CampfireType::new); - public static final ComposterType COMPOSTER = register("composter", ComposterType::new); - public static final JukeboxType JUKEBOX = register("jukebox", JukeboxType::new); - public static final RespawnAnchorType RESPAWN_ANCHOR = register("respawn_anchor", RespawnAnchorType::new); - - private static T register(String id, Function factory) { - T type = factory.apply(Create.asResource(id)); - ArmInteractionPointType.register(type); - return type; + register("campfire", new CampfireType()); + register("composter", new ComposterType()); + register("jukebox", new JukeboxType()); + register("respawn_anchor", new RespawnAnchorType()); } - public static void register() {} + private static void register(String name, T type) { + Registry.register(CreateBuiltInRegistries.ARM_INTERACTION_POINT_TYPE, Create.asResource(name), type); + } + + public static void init() { + } // public static class BasinType extends ArmInteractionPointType { - public BasinType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return BasinBlock.isBasin(level, pos); @@ -108,10 +105,6 @@ public class AllArmInteractionPointTypes { } public static class BeltType extends ArmInteractionPointType { - public BeltType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.BELT.has(state) && !(level.getBlockState(pos.above()) @@ -125,10 +118,6 @@ public class AllArmInteractionPointTypes { } public static class BlazeBurnerType extends ArmInteractionPointType { - public BlazeBurnerType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.BLAZE_BURNER.has(state); @@ -141,10 +130,6 @@ public class AllArmInteractionPointTypes { } public static class ChuteType extends ArmInteractionPointType { - public ChuteType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AbstractChuteBlock.isChute(state); @@ -157,10 +142,6 @@ public class AllArmInteractionPointTypes { } public static class CrafterType extends ArmInteractionPointType { - public CrafterType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.MECHANICAL_CRAFTER.has(state); @@ -173,10 +154,6 @@ public class AllArmInteractionPointTypes { } public static class CrushingWheelsType extends ArmInteractionPointType { - public CrushingWheelsType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(state); @@ -189,10 +166,6 @@ public class AllArmInteractionPointTypes { } public static class DeployerType extends ArmInteractionPointType { - public DeployerType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.DEPLOYER.has(state); @@ -205,10 +178,6 @@ public class AllArmInteractionPointTypes { } public static class DepotType extends ArmInteractionPointType { - public DepotType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.DEPOT.has(state) || AllBlocks.WEIGHTED_EJECTOR.has(state) @@ -222,16 +191,12 @@ public class AllArmInteractionPointTypes { } public static class FunnelType extends ArmInteractionPointType { - public FunnelType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return state.getBlock() instanceof AbstractFunnelBlock && !(state.hasProperty(FunnelBlock.EXTRACTING) && state.getValue(FunnelBlock.EXTRACTING)) && !(state.hasProperty(BeltFunnelBlock.SHAPE) - && state.getValue(BeltFunnelBlock.SHAPE) == Shape.PUSHING); + && state.getValue(BeltFunnelBlock.SHAPE) == Shape.PUSHING); } @Override @@ -241,10 +206,6 @@ public class AllArmInteractionPointTypes { } public static class MillstoneType extends ArmInteractionPointType { - public MillstoneType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.MILLSTONE.has(state); @@ -256,11 +217,19 @@ public class AllArmInteractionPointTypes { } } - public static class SawType extends ArmInteractionPointType { - public SawType(ResourceLocation id) { - super(id); + public static class PackagerType extends ArmInteractionPointType { + @Override + public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { + return AllBlocks.PACKAGER.has(state) || AllBlocks.REPACKAGER.has(state); } + @Override + public ArmInteractionPoint createPoint(Level level, BlockPos pos, BlockState state) { + return new ArmInteractionPoint(this, level, pos, state); + } + } + + public static class SawType extends ArmInteractionPointType { @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.MECHANICAL_SAW.has(state) && state.getValue(SawBlock.FACING) == Direction.UP @@ -274,10 +243,6 @@ public class AllArmInteractionPointTypes { } public static class CampfireType extends ArmInteractionPointType { - public CampfireType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return state.getBlock() instanceof CampfireBlock; @@ -290,10 +255,6 @@ public class AllArmInteractionPointTypes { } public static class ComposterType extends ArmInteractionPointType { - public ComposterType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return state.is(Blocks.COMPOSTER); @@ -306,10 +267,6 @@ public class AllArmInteractionPointTypes { } public static class JukeboxType extends ArmInteractionPointType { - public JukeboxType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return state.is(Blocks.JUKEBOX); @@ -322,10 +279,6 @@ public class AllArmInteractionPointTypes { } public static class RespawnAnchorType extends ArmInteractionPointType { - public RespawnAnchorType(ResourceLocation id) { - super(id); - } - @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return state.is(Blocks.RESPAWN_ANCHOR); @@ -341,12 +294,13 @@ public class AllArmInteractionPointTypes { public static class DepositOnlyArmInteractionPoint extends ArmInteractionPoint { public DepositOnlyArmInteractionPoint(ArmInteractionPointType type, Level level, BlockPos pos, - BlockState state) { + BlockState state) { super(type, level, pos, state); } @Override - public void cycleMode() {} + public void cycleMode() { + } @Override public ItemStack extract(int slot, int amount, boolean simulate) { @@ -447,9 +401,8 @@ public class AllArmInteractionPointTypes { @Override public ItemStack extract(int slot, int amount, boolean simulate) { BlockEntity be = level.getBlockEntity(pos); - if (!(be instanceof MechanicalCrafterBlockEntity)) + if (!(be instanceof MechanicalCrafterBlockEntity crafter)) return ItemStack.EMPTY; - MechanicalCrafterBlockEntity crafter = (MechanicalCrafterBlockEntity) be; SmartInventory inventory = crafter.getInventory(); inventory.allowExtraction(); ItemStack extract = super.extract(slot, amount, simulate); @@ -541,8 +494,7 @@ public class AllArmInteractionPointTypes { ItemStack insert = inserter.insert(stack); if (!simulate && insert.getCount() != stack.getCount()) { BlockEntity blockEntity = level.getBlockEntity(pos); - if (blockEntity instanceof FunnelBlockEntity) { - FunnelBlockEntity funnelBlockEntity = (FunnelBlockEntity) blockEntity; + if (blockEntity instanceof FunnelBlockEntity funnelBlockEntity) { funnelBlockEntity.onTransfer(stack); if (funnelBlockEntity.hasFlap()) funnelBlockEntity.flap(true); @@ -707,7 +659,7 @@ public class AllArmInteractionPointTypes { @Override protected Vec3 getInteractionPositionVector() { return Vec3.atLowerCornerOf(pos) - .add(.5f, 1, .5f); + .add(.5f, 1, .5f); } } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmAngleTarget.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmAngleTarget.java index 59bc62aa2c..ac2922f0f1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmAngleTarget.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmAngleTarget.java @@ -1,8 +1,7 @@ package com.simibubi.create.content.kinetics.mechanicalArm; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java index 81a60f8682..e71c9c4289 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java @@ -6,7 +6,7 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.mechanicalArm.AllArmInteractionPointTypes.JukeboxPoint; @@ -18,14 +18,15 @@ import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIc import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.SectionPos; @@ -38,17 +39,20 @@ import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.JukeboxBlock; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; -public class ArmBlockEntity extends KineticBlockEntity implements ITransformableBlockEntity { +public class ArmBlockEntity extends KineticBlockEntity implements TransformableBlockEntity { // Server List inputs; @@ -111,8 +115,8 @@ public class ArmBlockEntity extends KineticBlockEntity implements ITransformable public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); - selectionMode = new ScrollOptionBehaviour(SelectionMode.class, - Lang.translateDirect("logistics.when_multiple_outputs_available"), this, new SelectionModeValueBox()); + selectionMode = new ScrollOptionBehaviour<>(SelectionMode.class, + CreateLang.translateDirect("logistics.when_multiple_outputs_available"), this, new SelectionModeValueBox()); behaviours.add(selectionMode); registerAwardables(behaviours, AllAdvancements.ARM_BLAZE_BURNER, AllAdvancements.ARM_MANY_TARGETS, @@ -258,7 +262,8 @@ public class ArmBlockEntity extends KineticBlockEntity implements ITransformable if (scanRange > inputs.size()) scanRange = inputs.size(); - InteractionPoints: for (int i = startIndex; i < scanRange; i++) { + InteractionPoints: + for (int i = startIndex; i < scanRange; i++) { ArmInteractionPoint armInteractionPoint = inputs.get(i); if (!armInteractionPoint.isValid()) continue; @@ -417,7 +422,7 @@ public class ArmBlockEntity extends KineticBlockEntity implements ITransformable } @Override - public void transform(StructureTransform transform) { + public void transform(BlockEntity be, StructureTransform transform) { if (interactionPointTag == null) return; @@ -613,7 +618,7 @@ public class ArmBlockEntity extends KineticBlockEntity implements ITransformable } @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { int yPos = state.getValue(ArmBlock.CEILING) ? 16 - 3 : 3; Vec3 location = VecHelper.voxelSpace(8, yPos, 15.5); location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Direction.Axis.Y); diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPoint.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPoint.java index a0f5e849e8..690b4ebec2 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPoint.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPoint.java @@ -2,10 +2,11 @@ package com.simibubi.create.content.kinetics.mechanicalArm; import javax.annotation.Nullable; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.content.contraptions.StructureTransform; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -16,6 +17,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; @@ -88,7 +90,8 @@ public class ArmInteractionPoint { return type.canCreatePoint(level, pos, cachedState); } - public void keepAlive() {} + public void keepAlive() { + } @Nullable protected IItemHandler getHandler() { @@ -135,8 +138,12 @@ public class ArmInteractionPoint { } public final CompoundTag serialize(BlockPos anchor) { + ResourceLocation key = CreateBuiltInRegistries.ARM_INTERACTION_POINT_TYPE.getKey(type); + if (key == null) + throw new IllegalArgumentException("Could not get id for ArmInteractionPointType " + type + "!"); + CompoundTag nbt = new CompoundTag(); - nbt.putString("Type", type.getId().toString()); + nbt.putString("Type", key.toString()); nbt.put("Pos", NbtUtils.writeBlockPos(pos.subtract(anchor))); serialize(nbt, anchor); return nbt; @@ -147,7 +154,7 @@ public class ArmInteractionPoint { ResourceLocation id = ResourceLocation.tryParse(nbt.getString("Type")); if (id == null) return null; - ArmInteractionPointType type = ArmInteractionPointType.get(id); + ArmInteractionPointType type = CreateBuiltInRegistries.ARM_INTERACTION_POINT_TYPE.get(id); if (type == null) return null; BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos")).offset(anchor); diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointHandler.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointHandler.java index 24cf515bea..36850a4f9c 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointHandler.java @@ -8,10 +8,10 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPoint.Mode; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -25,6 +25,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -64,8 +65,8 @@ public class ArmInteractionPointHandler { selected.cycleMode(); if (player != null) { Mode mode = selected.getMode(); - Lang.builder() - .translate(mode.getTranslationKey(), Lang.blockName(state) + CreateLang.builder() + .translate(mode.getTranslationKey(), CreateLang.blockName(state) .style(ChatFormatting.WHITE)) .color(mode.getColor()) .sendStatus(player); @@ -93,7 +94,7 @@ public class ArmInteractionPointHandler { return; int removed = 0; - for (Iterator iterator = currentSelection.iterator(); iterator.hasNext();) { + for (Iterator iterator = currentSelection.iterator(); iterator.hasNext(); ) { ArmInteractionPoint point = iterator.next(); if (point.getPos() .closerThan(pos, ArmBlockEntity.getRange())) @@ -104,7 +105,7 @@ public class ArmInteractionPointHandler { LocalPlayer player = Minecraft.getInstance().player; if (removed > 0) { - Lang.builder() + CreateLang.builder() .translate("mechanical_arm.points_outside_range", removed) .style(ChatFormatting.RED) .sendStatus(player); @@ -118,7 +119,7 @@ public class ArmInteractionPointHandler { inputs++; } if (inputs + outputs > 0) - Lang.builder() + CreateLang.builder() .translate("mechanical_arm.summary", inputs, outputs) .style(ChatFormatting.WHITE) .sendStatus(player); @@ -156,11 +157,10 @@ public class ArmInteractionPointHandler { } HitResult objectMouseOver = Minecraft.getInstance().hitResult; - if (!(objectMouseOver instanceof BlockHitResult)) { + if (!(objectMouseOver instanceof BlockHitResult result)) { return; } - BlockHitResult result = (BlockHitResult) objectMouseOver; BlockPos pos = result.getBlockPos(); BlockEntity be = Minecraft.getInstance().level.getBlockEntity(pos); @@ -184,7 +184,7 @@ public class ArmInteractionPointHandler { } private static void drawOutlines(Collection selection) { - for (Iterator iterator = selection.iterator(); iterator.hasNext();) { + for (Iterator iterator = selection.iterator(); iterator.hasNext(); ) { ArmInteractionPoint point = iterator.next(); if (!point.isValid()) { @@ -201,8 +201,8 @@ public class ArmInteractionPointHandler { int color = point.getMode() .getColor(); - CreateClient.OUTLINER.showAABB(point, shape.bounds() - .move(pos)) + Outliner.getInstance().showAABB(point, shape.bounds() + .move(pos)) .colored(color) .lineWidth(1 / 16f); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointType.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointType.java index 6e345f4c4c..13d33331f8 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointType.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointType.java @@ -1,59 +1,51 @@ package com.simibubi.create.content.kinetics.mechanicalArm; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.function.Consumer; import javax.annotation.Nullable; +import org.jetbrains.annotations.UnmodifiableView; + +import com.simibubi.create.api.registry.CreateBuiltInRegistries; + +import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; public abstract class ArmInteractionPointType { - - private static final Map TYPES = new HashMap<>(); - private static final List SORTED_TYPES = new ArrayList<>(); - - protected final ResourceLocation id; - - public ArmInteractionPointType(ResourceLocation id) { - this.id = id; - } - - public static void register(ArmInteractionPointType type) { - ResourceLocation id = type.getId(); - if (TYPES.containsKey(id)) - throw new IllegalArgumentException("Tried to override ArmInteractionPointType registration for id '" + id + "'. This is not supported!"); - TYPES.put(id, type); - SORTED_TYPES.add(type); - SORTED_TYPES.sort((t1, t2) -> t2.getPriority() - t1.getPriority()); - } - - @Nullable - public static ArmInteractionPointType get(ResourceLocation id) { - return TYPES.get(id); - } + private static List sortedTypes = null; + @UnmodifiableView + private static List sortedTypesView = null; public static void forEach(Consumer action) { - SORTED_TYPES.forEach(action); + getSorted().forEach(action); + } + + @UnmodifiableView + public static List getSorted() { + if (sortedTypes == null) { + sortedTypes = new ReferenceArrayList<>(); + + CreateBuiltInRegistries.ARM_INTERACTION_POINT_TYPE.forEach(sortedTypes::add); + sortedTypes.sort((t1, t2) -> t2.getPriority() - t1.getPriority()); + + sortedTypesView = Collections.unmodifiableList(sortedTypes); + } + + return sortedTypesView; } @Nullable public static ArmInteractionPointType getPrimaryType(Level level, BlockPos pos, BlockState state) { - for (ArmInteractionPointType type : SORTED_TYPES) + for (ArmInteractionPointType type : getSorted()) if (type.canCreatePoint(level, pos, state)) return type; return null; } - public final ResourceLocation getId() { - return id; - } - public abstract boolean canCreatePoint(Level level, BlockPos pos, BlockState state); @Nullable @@ -62,5 +54,4 @@ public abstract class ArmInteractionPointType { public int getPriority() { return 0; } - } diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmPlacementPacket.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmPlacementPacket.java index 8e33af2ec8..baf8b6ab76 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmPlacementPacket.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmPlacementPacket.java @@ -12,6 +12,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.network.NetworkEvent.Context; @@ -55,10 +56,9 @@ public class ArmPlacementPacket extends SimplePacketBase { if (world == null || !world.isLoaded(pos)) return; BlockEntity blockEntity = world.getBlockEntity(pos); - if (!(blockEntity instanceof ArmBlockEntity)) + if (!(blockEntity instanceof ArmBlockEntity arm)) return; - ArmBlockEntity arm = (ArmBlockEntity) blockEntity; arm.interactionPointTag = receivedTag; }); return true; diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmRenderer.java index 9ddf901dc0..e9db7e8261 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmRenderer.java @@ -5,14 +5,14 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.content.kinetics.mechanicalArm.ArmBlockEntity.Phase; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -111,19 +111,19 @@ public class ArmRenderer extends KineticBlockEntityRenderer { private void renderArm(VertexConsumer builder, PoseStack ms, PoseStack msLocal, TransformStack msr, BlockState blockState, int color, float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle, boolean goggles, boolean inverted, boolean hasItem, boolean isBlockItem, int light) { - SuperByteBuffer base = CachedBufferer.partial(AllPartialModels.ARM_BASE, blockState) + SuperByteBuffer base = CachedBuffers.partial(AllPartialModels.ARM_BASE, blockState) .light(light); - SuperByteBuffer lowerBody = CachedBufferer.partial(AllPartialModels.ARM_LOWER_BODY, blockState) + SuperByteBuffer lowerBody = CachedBuffers.partial(AllPartialModels.ARM_LOWER_BODY, blockState) .light(light); - SuperByteBuffer upperBody = CachedBufferer.partial(AllPartialModels.ARM_UPPER_BODY, blockState) + SuperByteBuffer upperBody = CachedBuffers.partial(AllPartialModels.ARM_UPPER_BODY, blockState) .light(light); - SuperByteBuffer claw = CachedBufferer + SuperByteBuffer claw = CachedBuffers .partial(goggles ? AllPartialModels.ARM_CLAW_BASE_GOGGLES : AllPartialModels.ARM_CLAW_BASE, blockState) .light(light); - SuperByteBuffer upperClawGrip = CachedBufferer.partial(AllPartialModels.ARM_CLAW_GRIP_UPPER, + SuperByteBuffer upperClawGrip = CachedBuffers.partial(AllPartialModels.ARM_CLAW_GRIP_UPPER, blockState) .light(light); - SuperByteBuffer lowerClawGrip = CachedBufferer.partial(AllPartialModels.ARM_CLAW_GRIP_LOWER, blockState) + SuperByteBuffer lowerClawGrip = CachedBuffers.partial(AllPartialModels.ARM_CLAW_GRIP_LOWER, blockState) .light(light); transformBase(msr, baseAngle); @@ -200,7 +200,7 @@ public class ArmRenderer extends KineticBlockEntityRenderer { @Override protected SuperByteBuffer getRotatedModel(ArmBlockEntity be, BlockState state) { - return CachedBufferer.partial(AllPartialModels.ARM_COG, state); + return CachedBuffers.partial(AllPartialModels.ARM_COG, state); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmVisual.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmVisual.java index 91cb6cb814..bc0852a06c 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmVisual.java @@ -4,15 +4,10 @@ import java.util.ArrayList; import java.util.function.Consumer; import com.google.common.collect.Lists; -import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.content.kinetics.base.SingleAxisRotatingVisual; import dev.engine_room.flywheel.api.instance.Instance; -import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.AbstractInstance; @@ -21,33 +16,38 @@ import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.transform.TransformStack; +import dev.engine_room.flywheel.lib.util.RecyclingPoseStack; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.util.Mth; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; -public class ArmVisual extends SingleRotatingVisual implements SimpleDynamicVisual { +public class ArmVisual extends SingleAxisRotatingVisual implements SimpleDynamicVisual { final TransformedInstance base; final TransformedInstance lowerBody; final TransformedInstance upperBody; - TransformedInstance claw; + final TransformedInstance claw; private final ArrayList clawGrips; private final ArrayList models; - private final Boolean ceiling; + private final boolean ceiling; - private boolean firstRender = true; + private final RecyclingPoseStack poseStack = new RecyclingPoseStack(); + private boolean wasDancing = false; private float baseAngle = Float.NaN; private float lowerArmAngle = Float.NaN; private float upperArmAngle = Float.NaN; private float headAngle = Float.NaN; public ArmVisual(VisualizationContext context, ArmBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); + super(context, blockEntity, partialTick, Models.partial(AllPartialModels.ARM_COG)); base = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.ARM_BASE)) .createInstance(); @@ -67,19 +67,28 @@ public class ArmVisual extends SingleRotatingVisual implements S models = Lists.newArrayList(base, lowerBody, upperBody, claw, clawGrip1, clawGrip2); ceiling = blockState.getValue(ArmBlock.CEILING); - animateArm(); + var msr = TransformStack.of(poseStack); + msr.translate(getVisualPosition()); + msr.center(); + + if (ceiling) + msr.rotateXDegrees(180); + + animate(partialTick); } @Override public void beginFrame(DynamicVisual.Context ctx) { + animate(ctx.partialTick()); + } + + private void animate(float pt) { if (blockEntity.phase == ArmBlockEntity.Phase.DANCING && blockEntity.getSpeed() != 0) { - animateRave(ctx.partialTick()); - firstRender = true; + animateRave(pt); + wasDancing = true; return; } - float pt = ctx.partialTick(); - float baseAngleNow = blockEntity.baseAngle.getValue(pt); float lowerArmAngleNow = blockEntity.lowerArmAngle.getValue(pt); float upperArmAngleNow = blockEntity.upperArmAngle.getValue(pt); @@ -93,11 +102,11 @@ public class ArmVisual extends SingleRotatingVisual implements S this.upperArmAngle = upperArmAngleNow; this.headAngle = headAngleNow; - if (!settled || firstRender) + // Need to reset the animation if the arm is dancing. We'd very likely be settled + if (!settled || wasDancing) animateArm(); - if (firstRender) - firstRender = false; + wasDancing = false; } private void animateRave(float partialTick) { @@ -111,32 +120,28 @@ public class ArmVisual extends SingleRotatingVisual implements S int color = Color.rainbowColor(ticks * 100) .getRGB(); updateAngles(baseAngle, lowerArmAngle, upperArmAngle, headAngle, color); - } + } private void animateArm() { - updateAngles(this.baseAngle, this.lowerArmAngle - 135, this.upperArmAngle - 90, this.headAngle, 0xFFFFFF); + updateAngles(this.baseAngle, this.lowerArmAngle - 135, this.upperArmAngle - 90, this.headAngle, 0xFFFFFF); } private void updateAngles(float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle, int color) { - PoseStack msLocal = new PoseStack(); - var msr = TransformStack.of(msLocal); - msr.translate(getVisualPosition()); - msr.center(); + poseStack.pushPose(); - if (ceiling) - msr.rotateXDegrees(180); + var msr = TransformStack.of(poseStack); ArmRenderer.transformBase(msr, baseAngle); - base.setTransform(msLocal) + base.setTransform(poseStack) .setChanged(); ArmRenderer.transformLowerArm(msr, lowerArmAngle); - lowerBody.setTransform(msLocal) + lowerBody.setTransform(poseStack) .colorRgb(color) .setChanged(); ArmRenderer.transformUpperArm(msr, upperArmAngle); - upperBody.setTransform(msLocal) + upperBody.setTransform(poseStack) .colorRgb(color) .setChanged(); @@ -145,7 +150,7 @@ public class ArmVisual extends SingleRotatingVisual implements S if (ceiling && blockEntity.goggles) msr.rotateZDegrees(180); - claw.setTransform(msLocal) + claw.setTransform(poseStack) .setChanged(); if (ceiling && blockEntity.goggles) @@ -157,29 +162,26 @@ public class ArmVisual extends SingleRotatingVisual implements S boolean hasItem = !item.isEmpty(); boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) && itemRenderer.getModel(item, Minecraft.getInstance().level, null, 0) - .isGui3d(); + .isGui3d(); for (int index : Iterate.zeroAndOne) { - msLocal.pushPose(); + poseStack.pushPose(); int flip = index * 2 - 1; ArmRenderer.transformClawHalf(msr, hasItem, isBlockItem, flip); clawGrips.get(index) - .setTransform(msLocal) + .setTransform(poseStack) .setChanged(); - msLocal.popPose(); + poseStack.popPose(); } + + poseStack.popPose(); } @Override public void update(float pt) { super.update(pt); - models.remove(claw); - claw.delete(); - claw = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(blockEntity.goggles ? AllPartialModels.ARM_CLAW_BASE_GOGGLES : AllPartialModels.ARM_CLAW_BASE)) - .createInstance(); - models.add(claw); - updateLight(pt); - animateArm(); + instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(blockEntity.goggles ? AllPartialModels.ARM_CLAW_BASE_GOGGLES : AllPartialModels.ARM_CLAW_BASE)) + .stealInstance(claw); } @Override @@ -190,12 +192,7 @@ public class ArmVisual extends SingleRotatingVisual implements S } @Override - protected Model model() { - return Models.partial(AllPartialModels.ARM_COG); - } - - @Override - protected void _delete() { + protected void _delete() { super._delete(); models.forEach(AbstractInstance::delete); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlock.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlock.java index 63c685251f..99c69568f5 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlock.java @@ -5,8 +5,8 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.content.kinetics.base.KineticBlock; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -25,6 +25,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; @@ -49,7 +50,7 @@ public class MillstoneBlock extends KineticBlock implements IBE capability = millstone.getCapability(ForgeCapabilities.ITEM_HANDLER); if (!capability.isPresent()) return; diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlockEntity.java index 2b3e5bcaae..e56086073a 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlockEntity.java @@ -11,8 +11,8 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.sound.SoundScapes; import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -121,7 +121,7 @@ public class MillstoneBlockEntity extends KineticBlockEntity { super.invalidate(); capability.invalidate(); } - + @Override public void destroy() { super.destroy(); @@ -145,7 +145,7 @@ public class MillstoneBlockEntity extends KineticBlockEntity { lastRecipe.rollResults() .forEach(stack -> ItemHandlerHelper.insertItemStacked(outputInv, stack, false)); award(AllAdvancements.MILLSTONE); - + sendData(); setChanged(); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneCogVisual.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneCogVisual.java deleted file mode 100644 index cc2a6aea18..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneCogVisual.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.simibubi.create.content.kinetics.millstone; - -import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; - -import dev.engine_room.flywheel.api.model.Model; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.model.Models; - -public class MillstoneCogVisual extends SingleRotatingVisual { - - public MillstoneCogVisual(VisualizationContext context, MillstoneBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - } - - @Override - protected Model model() { - return Models.partial(AllPartialModels.MILLSTONE_COG); - } -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneRenderer.java index 5f3f344da1..57bedbd36a 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneRenderer.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.kinetics.millstone; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.world.level.block.state.BlockState; @@ -16,7 +16,7 @@ public class MillstoneRenderer extends KineticBlockEntityRenderer implements SimpleDynamicVisual { private final RotatingInstance mixerHead; private final OrientedInstance mixerPole; private final MechanicalMixerBlockEntity mixer; public MixerVisual(VisualizationContext context, MechanicalMixerBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, false, partialTick); + super(context, blockEntity, partialTick, Models.partial(AllPartialModels.SHAFTLESS_COGWHEEL)); this.mixer = blockEntity; mixerHead = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.MECHANICAL_MIXER_HEAD)) @@ -33,16 +32,11 @@ public class MixerVisual extends EncasedCogVisual implements SimpleDynamicVisual mixerHead.setRotationAxis(Direction.Axis.Y); mixerPole = instancerProvider().instancer(InstanceTypes.ORIENTED, Models.partial(AllPartialModels.MECHANICAL_MIXER_POLE)) - .createInstance(); + .createInstance(); animate(partialTick); } - @Override - protected Model getCogModel() { - return Models.partial(AllPartialModels.SHAFTLESS_COGWHEEL); - } - @Override public void beginFrame(DynamicVisual.Context ctx) { animate(ctx.partialTick()); @@ -59,15 +53,15 @@ public class MixerVisual extends EncasedCogVisual implements SimpleDynamicVisual float speed = mixer.getRenderedHeadRotationSpeed(pt); mixerHead.setPosition(getVisualPosition()) - .nudge(0, -renderedHeadOffset, 0) - .setRotationalSpeed(speed * 2) - .setChanged(); + .nudge(0, -renderedHeadOffset, 0) + .setRotationalSpeed(speed * 2 * RotatingInstance.SPEED_MULTIPLIER) + .setChanged(); } private void transformPole(float renderedHeadOffset) { mixerPole.position(getVisualPosition()) - .translatePosition(0, -renderedHeadOffset, 0) - .setChanged(); + .translatePosition(0, -renderedHeadOffset, 0) + .setChanged(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlockEntity.java index 9de85be0f7..cdd04d0d41 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlockEntity.java @@ -8,14 +8,15 @@ import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -35,7 +36,7 @@ public class CreativeMotorBlockEntity extends GeneratingKineticBlockEntity { public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); int max = MAX_SPEED; - generatedSpeed = new KineticScrollValueBehaviour(Lang.translateDirect("kinetics.creative_motor.rotation_speed"), + generatedSpeed = new KineticScrollValueBehaviour(CreateLang.translateDirect("kinetics.creative_motor.rotation_speed"), this, new MotorValueBox()); generatedSpeed.between(-max, max); generatedSpeed.value = DEFAULT_SPEED; @@ -65,15 +66,15 @@ public class CreativeMotorBlockEntity extends GeneratingKineticBlockEntity { } @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Direction facing = state.getValue(CreativeMotorBlock.FACING); - return super.getLocalOffset(state).add(Vec3.atLowerCornerOf(facing.getNormal()) + return super.getLocalOffset(level, pos, state).add(Vec3.atLowerCornerOf(facing.getNormal()) .scale(-1 / 16f)); } @Override - public void rotate(BlockState state, PoseStack ms) { - super.rotate(state, ms); + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { + super.rotate(level, pos, state, ms); Direction facing = state.getValue(CreativeMotorBlock.FACING); if (facing.getAxis() == Axis.Y) return; diff --git a/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorRenderer.java index 452d088ef6..f05371940f 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorRenderer.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.kinetics.motor; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.world.level.block.state.BlockState; @@ -16,7 +16,7 @@ public class CreativeMotorRenderer extends KineticBlockEntityRenderer rows = ImmutableList.of(Components.literal("\u27f3") + ImmutableList rows = ImmutableList.of(Component.literal("\u27f3") .withStyle(ChatFormatting.BOLD), - Components.literal("\u27f2") + Component.literal("\u27f2") .withStyle(ChatFormatting.BOLD)); ValueSettingsFormatter formatter = new ValueSettingsFormatter(this::formatSettings); return new ValueSettingsBoard(label, 256, 32, rows, formatter); @@ -46,15 +45,15 @@ public class KineticScrollValueBehaviour extends ScrollValueBehaviour { } public MutableComponent formatSettings(ValueSettings settings) { - return Lang.number(Math.max(1, Math.abs(settings.value()))) - .add(Lang.text(settings.row() == 0 ? "\u27f3" : "\u27f2") + return CreateLang.number(Math.max(1, Math.abs(settings.value()))) + .add(CreateLang.text(settings.row() == 0 ? "\u27f3" : "\u27f2") .style(ChatFormatting.BOLD)) .component(); } - + @Override public String getClipboardKey() { return "Speed"; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/BeltPressingCallbacks.java b/src/main/java/com/simibubi/create/content/kinetics/press/BeltPressingCallbacks.java index 900aab84b3..2ae6407f11 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/press/BeltPressingCallbacks.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/BeltPressingCallbacks.java @@ -49,6 +49,8 @@ public class BeltPressingCallbacks { boolean bulk = behaviour.specifics.canProcessInBulk() || transported.stack.getCount() == 1; + transported.clearFanProcessingData(); + List collect = results.stream() .map(stack -> { TransportedItemStack copy = transported.copy(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlockEntity.java index a0095a5870..78bb465a5a 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlockEntity.java @@ -19,9 +19,9 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.SmartInventory; import com.simibubi.create.foundation.recipe.RecipeApplier; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressRenderer.java index 8f80fe23bb..b41111f380 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressRenderer.java @@ -5,10 +5,10 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -38,7 +38,7 @@ public class MechanicalPressRenderer extends KineticBlockEntityRenderer implements SimpleDynamicVisual { diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/PressingBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/press/PressingBehaviour.java index 38efd70aa3..487becd06b 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/press/PressingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/PressingBehaviour.java @@ -10,9 +10,9 @@ import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.content.processing.basin.BasinBlock; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ItemParticleOption; import net.minecraft.core.particles.ParticleTypes; diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/PressingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/press/PressingRecipe.java index 5c6f8c5215..f5fb538614 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/press/PressingRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/PressingRecipe.java @@ -12,7 +12,7 @@ import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemb import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.Component; import net.minecraft.world.item.crafting.Ingredient; @@ -53,14 +53,14 @@ public class PressingRecipe extends ProcessingRecipe implements I @Override @OnlyIn(Dist.CLIENT) public Component getDescriptionForAssembly() { - return Lang.translateDirect("recipe.assembly.pressing"); + return CreateLang.translateDirect("recipe.assembly.pressing"); } - + @Override public void addRequiredMachines(Set list) { list.add(AllBlocks.MECHANICAL_PRESS.get()); } - + @Override public Supplier> getJEISubCategory() { return () -> SequencedAssemblySubCategory.AssemblyPressing::new; diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/CuttingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/saw/CuttingRecipe.java index 709dbe37d8..3252b5ecaf 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/CuttingRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/CuttingRecipe.java @@ -12,7 +12,7 @@ import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemb import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.Component; import net.minecraft.world.item.crafting.Ingredient; @@ -58,14 +58,14 @@ public class CuttingRecipe extends ProcessingRecipe implements IA @Override @OnlyIn(Dist.CLIENT) public Component getDescriptionForAssembly() { - return Lang.translateDirect("recipe.assembly.cutting"); + return CreateLang.translateDirect("recipe.assembly.cutting"); } - + @Override public void addRequiredMachines(Set list) { list.add(AllBlocks.MECHANICAL_SAW.get()); } - + @Override public Supplier> getJEISubCategory() { return () -> SequencedAssemblySubCategory.AssemblyCutting::new; diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawActorVisual.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawActorVisual.java new file mode 100644 index 0000000000..bed637b9eb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawActorVisual.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.kinetics.saw; + +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorVisual; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; +import com.simibubi.create.content.kinetics.base.RotatingInstance; +import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; + +import dev.engine_room.flywheel.api.visualization.VisualizationContext; + +public class SawActorVisual extends ActorVisual { + private final RotatingInstance shaft; + + public SawActorVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld, MovementContext movementContext) { + super(visualizationContext, simulationWorld, movementContext); + + var state = movementContext.state; + var localPos = movementContext.localPos; + shaft = SawVisual.shaft(instancerProvider, state); + + var axis = KineticBlockEntityVisual.rotationAxis(state); + shaft.setRotationAxis(axis) + .setRotationOffset(KineticBlockEntityVisual.rotationOffset(state, axis, localPos)) + .setPosition(localPos) + .light(localBlockLight(), 0) + .setChanged(); + } + + @Override + protected void _delete() { + shaft.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlock.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlock.java index cae5dd582b..24bd53bcd4 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlock.java @@ -12,10 +12,10 @@ import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; import com.simibubi.create.content.kinetics.drill.DrillBlock; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlockEntity.java index 72d38608bd..50cdd73d60 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlockEntity.java @@ -16,6 +16,7 @@ import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.kinetics.base.BlockBreakingKineticBlockEntity; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.logistics.box.PackageItem; import com.simibubi.create.content.processing.recipe.ProcessingInventory; import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; import com.simibubi.create.foundation.advancement.AllAdvancements; @@ -25,10 +26,9 @@ import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.recipe.RecipeConditions; import com.simibubi.create.foundation.recipe.RecipeFinder; import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; -import com.simibubi.create.foundation.utility.TreeCutter; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -61,12 +61,14 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.registries.ForgeRegistries; @ParametersAreNonnullByDefault @@ -325,6 +327,22 @@ public class SawBlockEntity extends BlockBreakingKineticBlockEntity { } private void applyRecipe() { + ItemStack input = inventory.getStackInSlot(0); + List list = new ArrayList<>(); + + if (PackageItem.isPackage(input)) { + inventory.clear(); + ItemStackHandler results = PackageItem.getContents(input); + for (int i = 0; i < results.getSlots(); i++) { + ItemStack stack = results.getStackInSlot(i); + if (!stack.isEmpty()) + ItemHelper.addToList(stack, list); + } + for (int slot = 0; slot < list.size() && slot + 1 < inventory.getSlots(); slot++) + inventory.setStackInSlot(slot + 1, list.get(slot)); + return; + } + List> recipes = getRecipes(); if (recipes.isEmpty()) return; @@ -333,21 +351,18 @@ public class SawBlockEntity extends BlockBreakingKineticBlockEntity { Recipe recipe = recipes.get(recipeIndex); - int rolls = inventory.getStackInSlot(0) - .getCount(); + int rolls = input.getCount(); inventory.clear(); - List list = new ArrayList<>(); for (int roll = 0; roll < rolls; roll++) { - List results = new LinkedList(); + List results = new LinkedList<>(); if (recipe instanceof CuttingRecipe) results = ((CuttingRecipe) recipe).rollResults(); else if (recipe instanceof StonecutterRecipe || recipe.getType() == woodcuttingRecipeType.get()) results.add(recipe.getResultItem(level.registryAccess()) .copy()); - for (int i = 0; i < results.size(); i++) { - ItemStack stack = results.get(i); + for (ItemStack stack : results) { ItemHelper.addToList(stack, list); } } @@ -366,8 +381,7 @@ public class SawBlockEntity extends BlockBreakingKineticBlockEntity { return ImmutableList.of(assemblyRecipe.get()); Predicate> types = RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType(), - AllConfigs.server().recipes.allowStonecuttingOnSaw.get() ? RecipeType.STONECUTTING : null, - AllConfigs.server().recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.get() : null); + AllConfigs.server().recipes.allowStonecuttingOnSaw.get() ? RecipeType.STONECUTTING : null); List> startedSearch = RecipeFinder.get(cuttingRecipesKey, level, types); return startedSearch.stream() diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawFilterSlot.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawFilterSlot.java index dfa8ed72db..8afeb3f0ff 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/SawFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawFilterSlot.java @@ -2,17 +2,19 @@ package com.simibubi.create.content.kinetics.saw; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; public class SawFilterSlot extends ValueBoxTransform { @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { if (state.getValue(SawBlock.FACING) != Direction.UP) return null; int offset = state.getValue(SawBlock.FLIPPED) ? -3 : 3; @@ -22,7 +24,7 @@ public class SawFilterSlot extends ValueBoxTransform { } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { int yRot = (state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 90 : 0) + (state.getValue(SawBlock.FLIPPED) ? 0 : 180); TransformStack.of(ms) diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java index 4f47756047..ec3486470f 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java @@ -2,15 +2,18 @@ package com.simibubi.create.content.kinetics.saw; import java.util.Optional; +import org.jetbrains.annotations.Nullable; + import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorVisual; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; import com.simibubi.create.foundation.damageTypes.CreateDamageSources; import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; -import com.simibubi.create.foundation.utility.TreeCutter; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -21,6 +24,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.ItemHandlerHelper; @@ -78,7 +82,7 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { } public void dropItemFromCutTree(MovementContext context, BlockPos pos, ItemStack stack) { - ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false); + ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.getStorage().getAllItems(), stack, false); if (remainder.isEmpty()) return; @@ -95,6 +99,11 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { return true; } + @Override + public @Nullable ActorVisual createVisual(VisualizationContext visualizationContext, VirtualRenderWorld simulationWorld, MovementContext movementContext) { + return new SawActorVisual(visualizationContext, simulationWorld, movementContext); + } + @Override @OnlyIn(value = Dist.CLIENT) public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawRenderer.java index 4b680bf0f5..72f50b0ff8 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/SawRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawRenderer.java @@ -9,16 +9,18 @@ import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.logistics.box.PackageItem; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; @@ -36,8 +38,7 @@ import net.minecraft.world.phys.Vec3; public class SawRenderer extends SafeBlockEntityRenderer { - public SawRenderer(BlockEntityRendererProvider.Context context) { - } + public SawRenderer(BlockEntityRendererProvider.Context context) {} @Override protected void renderSafe(SawBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, @@ -79,7 +80,7 @@ public class SawRenderer extends SafeBlockEntityRenderer { rotate = true; } - SuperByteBuffer superBuffer = CachedBufferer.partialFacing(partial, blockState); + SuperByteBuffer superBuffer = CachedBuffers.partialFacing(partial, blockState); if (rotate) { superBuffer.rotateCentered(AngleHelper.rad(90), Direction.UP); } @@ -93,53 +94,82 @@ public class SawRenderer extends SafeBlockEntityRenderer { buffer.getBuffer(RenderType.solid()), light); } - protected void renderItems(SawBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - boolean processingMode = be.getBlockState() - .getValue(SawBlock.FACING) == Direction.UP; - if (processingMode && !be.inventory.isEmpty()) { - boolean alongZ = !be.getBlockState() - .getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); + protected void renderItems(SawBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + if (be.getBlockState() + .getValue(SawBlock.FACING) != Direction.UP) + return; + if (be.inventory.isEmpty()) + return; + + boolean alongZ = !be.getBlockState() + .getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); + + float duration = be.inventory.recipeDuration; + boolean moving = duration != 0; + float offset = moving ? (float) (be.inventory.remainingTime) / duration : 0; + float processingSpeed = Mth.clamp(Math.abs(be.getSpeed()) / 32, 1, 128); + if (moving) { + offset = Mth.clamp(offset + ((-partialTicks + .5f) * processingSpeed) / duration, 0.125f, 1f); + if (!be.inventory.appliedRecipe) + offset += 1; + offset /= 2; + } + + if (be.getSpeed() == 0) + offset = .5f; + if (be.getSpeed() < 0 ^ alongZ) + offset = 1 - offset; + + int outputs = 0; + for (int i = 1; i < be.inventory.getSlots(); i++) + if (!be.inventory.getStackInSlot(i) + .isEmpty()) + outputs++; + + ms.pushPose(); + if (alongZ) + ms.mulPose(Axis.YP.rotationDegrees(90)); + ms.translate(outputs <= 1 ? .5 : .25, 0, offset); + ms.translate(alongZ ? -1 : 0, 0, 0); + + int renderedI = 0; + for (int i = 0; i < be.inventory.getSlots(); i++) { + ItemStack stack = be.inventory.getStackInSlot(i); + if (stack.isEmpty()) + continue; + + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + BakedModel modelWithOverrides = itemRenderer.getModel(stack, be.getLevel(), null, 0); + boolean blockItem = modelWithOverrides.isGui3d(); + ms.pushPose(); + ms.translate(0, blockItem ? .925f : 13f / 16f, 0); - boolean moving = be.inventory.recipeDuration != 0; - float offset = moving ? (float) (be.inventory.remainingTime) / be.inventory.recipeDuration : 0; - float processingSpeed = Mth.clamp(Math.abs(be.getSpeed()) / 32, 1, 128); - if (moving) { - offset = Mth - .clamp(offset + ((-partialTicks + .5f) * processingSpeed) / be.inventory.recipeDuration, 0.125f, 1f); - if (!be.inventory.appliedRecipe) - offset += 1; - offset /= 2; + if (i > 0 && outputs > 1) { + ms.translate((0.5 / (outputs - 1)) * renderedI, 0, 0); + TransformStack.of(ms) + .nudge(i * 133); } - if (be.getSpeed() == 0) - offset = .5f; - if (be.getSpeed() < 0 ^ alongZ) - offset = 1 - offset; - - for (int i = 0; i < be.inventory.getSlots(); i++) { - ItemStack stack = be.inventory.getStackInSlot(i); - if (stack.isEmpty()) - continue; - - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - BakedModel modelWithOverrides = itemRenderer.getModel(stack, be.getLevel(), null, 0); - boolean blockItem = modelWithOverrides.isGui3d(); - - ms.translate(alongZ ? offset : .5, blockItem ? .925f : 13f / 16f, alongZ ? .5 : offset); - + boolean box = PackageItem.isPackage(stack); + if (box) { + ms.translate(0, 4 / 16f, 0); + ms.scale(1.5f, 1.5f, 1.5f); + } else ms.scale(.5f, .5f, .5f); - if (alongZ) - ms.mulPose(Axis.YP.rotationDegrees(90)); + + if (!box) ms.mulPose(Axis.XP.rotationDegrees(90)); - itemRenderer.render(stack, ItemDisplayContext.FIXED, false, ms, buffer, light, overlay, modelWithOverrides); - break; - } + + itemRenderer.render(stack, ItemDisplayContext.FIXED, false, ms, buffer, light, overlay, modelWithOverrides); + renderedI++; ms.popPose(); } + + ms.popPose(); } protected SuperByteBuffer getRotatedModel(KineticBlockEntity be) { @@ -147,10 +177,9 @@ public class SawRenderer extends SafeBlockEntityRenderer { if (state.getValue(FACING) .getAxis() .isHorizontal()) - return CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, + return CachedBuffers.partialFacing(AllPartialModels.SHAFT_HALF, state.rotate(be.getLevel(), be.getBlockPos(), Rotation.CLOCKWISE_180)); - return CachedBufferer.block(KineticBlockEntityRenderer.KINETIC_BLOCK, - getRenderedBlockState(be)); + return CachedBuffers.block(KineticBlockEntityRenderer.KINETIC_BLOCK, getRenderedBlockState(be)); } protected BlockState getRenderedBlockState(KineticBlockEntity be) { @@ -178,14 +207,14 @@ public class SawRenderer extends SafeBlockEntityRenderer { SuperByteBuffer superBuffer; if (SawBlock.isHorizontal(state)) { if (shouldAnimate) - superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_HORIZONTAL_ACTIVE, state); + superBuffer = CachedBuffers.partial(AllPartialModels.SAW_BLADE_HORIZONTAL_ACTIVE, state); else - superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_HORIZONTAL_INACTIVE, state); + superBuffer = CachedBuffers.partial(AllPartialModels.SAW_BLADE_HORIZONTAL_INACTIVE, state); } else { if (shouldAnimate) - superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_VERTICAL_ACTIVE, state); + superBuffer = CachedBuffers.partial(AllPartialModels.SAW_BLADE_VERTICAL_ACTIVE, state); else - superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_VERTICAL_INACTIVE, state); + superBuffer = CachedBuffers.partial(AllPartialModels.SAW_BLADE_VERTICAL_INACTIVE, state); } superBuffer.transform(matrices.getModel()) diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawVisual.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawVisual.java index fc6a29aab7..66f91c37c1 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/SawVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawVisual.java @@ -1,33 +1,68 @@ package com.simibubi.create.content.kinetics.saw; -import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; -import com.simibubi.create.foundation.render.VirtualRenderHelper; +import java.util.function.Consumer; -import dev.engine_room.flywheel.api.model.Model; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; +import com.simibubi.create.content.kinetics.base.RotatingInstance; +import com.simibubi.create.foundation.render.AllInstanceTypes; + +import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.instance.InstancerProvider; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.model.Models; import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Rotation; +import net.minecraft.core.Direction.Axis; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -public class SawVisual extends SingleRotatingVisual { +public class SawVisual extends KineticBlockEntityVisual { + + protected final RotatingInstance rotatingModel; public SawVisual(VisualizationContext context, SawBlockEntity blockEntity, float partialTick) { super(context, blockEntity, partialTick); + rotatingModel = shaft(instancerProvider(), blockState) + .setup(blockEntity) + .setPosition(getVisualPosition()); + rotatingModel.setChanged(); + } + + public static RotatingInstance shaft(InstancerProvider instancerProvider, BlockState state) { + var facing = state.getValue(BlockStateProperties.FACING); + var axis = facing + .getAxis(); + // We could change this to return either an Oriented- or SingleAxisRotatingVisual + if (axis.isHorizontal()) { + Direction align = facing.getOpposite(); + return instancerProvider.instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT_HALF)) + .createInstance() + .rotateTo(0, 0, 1, align.getStepX(), align.getStepY(), align.getStepZ()); + } else { + return instancerProvider.instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.SHAFT)) + .createInstance() + .rotateToFace(state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? Axis.X : Axis.Z); + } } @Override - protected Model model() { - if (blockState.getValue(BlockStateProperties.FACING) - .getAxis() - .isHorizontal()) { - BlockState referenceState = blockState.rotate(blockEntity.getLevel(), blockEntity.getBlockPos(), Rotation.CLOCKWISE_180); - Direction facing = referenceState.getValue(BlockStateProperties.FACING); - return Models.partial(AllPartialModels.SHAFT_HALF, facing); - } else { - return VirtualRenderHelper.blockModel(shaft()); - } + public void update(float pt) { + rotatingModel.setup(blockEntity) + .setChanged(); + } + + @Override + public void updateLight(float partialTick) { + relight(rotatingModel); + } + + @Override + protected void _delete() { + rotatingModel.delete(); + } + + @Override + public void collectCrumblingInstances(Consumer consumer) { + consumer.accept(rotatingModel); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java b/src/main/java/com/simibubi/create/content/kinetics/saw/TreeCutter.java similarity index 94% rename from src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java rename to src/main/java/com/simibubi/create/content/kinetics/saw/TreeCutter.java index 9025ec074d..36fa036441 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/TreeCutter.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.content.kinetics.saw; import java.util.ArrayList; import java.util.Collections; @@ -18,7 +18,9 @@ import com.simibubi.create.AllTags; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.compat.Mods; import com.simibubi.create.compat.dynamictrees.DynamicTree; +import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.tags.BlockTags; @@ -37,6 +39,7 @@ import net.minecraft.world.level.block.KelpPlantBlock; import net.minecraft.world.level.block.LeavesBlock; import net.minecraft.world.level.block.SugarCaneBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.Property; @@ -57,16 +60,11 @@ public class TreeCutter { return Optional.empty(); } - @Deprecated(forRemoval = true) - public static Tree findTree(@Nullable BlockGetter reader, BlockPos pos) { - return findTree(reader, pos, Blocks.AIR.defaultBlockState()); - } - /** * Finds a tree at the given pos. Block at the position should be air * - * @param reader the level that will be searched for a tree - * @param pos position that the saw cut at + * @param reader the level that will be searched for a tree + * @param pos position that the saw cut at * @param brokenState block state what was broken by the saw */ @Nonnull @@ -291,14 +289,14 @@ public class TreeCutter { } private static void forNeighbours(BlockPos pos, Set visited, SearchDirection direction, - Consumer acceptor) { + Consumer acceptor) { BlockPos.betweenClosedStream(pos.offset(-1, direction.minY, -1), pos.offset(1, direction.maxY, 1)) .filter(((Predicate) visited::contains).negate()) .forEach(acceptor); } public static boolean isRoot(BlockState state) { - return state.is(AllBlockTags.ROOTS.tag); + return AllBlockTags.ROOTS.matches(state); } public static boolean isLog(BlockState state) { @@ -317,10 +315,8 @@ public class TreeCutter { } private static boolean isLeaf(BlockState state) { - for (Property property : state.getValues() - .keySet()) - if (property instanceof IntegerProperty && property.getName() - .equals("distance")) + for (Property property : state.getValues().keySet()) + if (property instanceof IntegerProperty && property.getName().equals("distance") && property != BlockStateProperties.STABILITY_DISTANCE) return true; return false; } @@ -338,7 +334,7 @@ public class TreeCutter { @Override public void destroyBlocks(Level world, ItemStack toDamage, @Nullable Player playerEntity, - BiConsumer drop) { + BiConsumer drop) { attachments.forEach(makeCallbackFor(world, 1 / 32f, toDamage, playerEntity, drop)); logs.forEach(makeCallbackFor(world, 1 / 2f, toDamage, playerEntity, drop)); leaves.forEach(makeCallbackFor(world, 1 / 8f, toDamage, playerEntity, drop)); diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntity.java index ad1191d6d6..9490c98105 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntity.java @@ -2,16 +2,17 @@ package com.simibubi.create.content.kinetics.simpleRelays; import java.util.List; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -public class BracketedKineticBlockEntity extends SimpleKineticBlockEntity implements ITransformableBlockEntity { +public class BracketedKineticBlockEntity extends SimpleKineticBlockEntity implements TransformableBlockEntity { public BracketedKineticBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -25,7 +26,7 @@ public class BracketedKineticBlockEntity extends SimpleKineticBlockEntity implem } @Override - public void transform(StructureTransform transform) { + public void transform(BlockEntity be, StructureTransform transform) { BracketedBlockEntityBehaviour bracketBehaviour = getBehaviour(BracketedBlockEntityBehaviour.TYPE); if (bracketBehaviour != null) { bracketBehaviour.transformBracket(transform); diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityRenderer.java index 3232a05f2d..9b1cd661e2 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityRenderer.java @@ -5,11 +5,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; @@ -43,12 +44,12 @@ public class BracketedKineticBlockEntityRenderer extends KineticBlockEntityRende Axis axis = getRotationAxisOf(be); Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); renderRotatingBuffer(be, - CachedBufferer.partialFacingVertical(AllPartialModels.SHAFTLESS_LARGE_COGWHEEL, be.getBlockState(), facing), + CachedBuffers.partialFacingVertical(AllPartialModels.SHAFTLESS_LARGE_COGWHEEL, be.getBlockState(), facing), ms, vc, light); float angle = getAngleForLargeCogShaft(be, axis); SuperByteBuffer shaft = - CachedBufferer.partialFacingVertical(AllPartialModels.COGWHEEL_SHAFT, be.getBlockState(), facing); + CachedBuffers.partialFacingVertical(AllPartialModels.COGWHEEL_SHAFT, be.getBlockState(), facing); kineticRotationTransform(shaft, be, axis, angle, light); shaft.renderInto(ms, vc); @@ -63,12 +64,11 @@ public class BracketedKineticBlockEntityRenderer extends KineticBlockEntityRende } public static float getShaftAngleOffset(Axis axis, BlockPos pos) { - float offset = 0; - double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY()) - + ((axis == Axis.Z) ? 0 : pos.getZ())) % 2; - if (d == 0) - offset = 22.5f; - return offset; + if (KineticBlockEntityVisual.shouldOffset(axis, pos)) { + return 22.5f; + } else { + return 0; + } } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityVisual.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityVisual.java index 0b6b5b7fa0..734e0ed8ab 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityVisual.java @@ -2,97 +2,81 @@ package com.simibubi.create.content.kinetics.simpleRelays; import java.util.function.Consumer; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.content.kinetics.base.RotatingInstance; -import com.simibubi.create.content.kinetics.base.SingleRotatingVisual; +import com.simibubi.create.content.kinetics.base.SingleAxisRotatingVisual; import com.simibubi.create.foundation.render.AllInstanceTypes; import dev.engine_room.flywheel.api.instance.Instance; -import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.api.visual.BlockEntityVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.model.Models; -import dev.engine_room.flywheel.lib.transform.TransformStack; -import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.Direction.AxisDirection; -public class BracketedKineticBlockEntityVisual extends SingleRotatingVisual { +public class BracketedKineticBlockEntityVisual { - protected RotatingInstance additionalShaft; - - public BracketedKineticBlockEntityVisual(VisualizationContext context, BracketedKineticBlockEntity blockEntity, float partialTick) { - super(context, blockEntity, partialTick); - init(); - } - - public void init() { - if (ICogWheel.isLargeCog(blockEntity.getBlockState())) { - // Large cogs sometimes have to offset their teeth by 11.25 degrees in order to - // mesh properly - - float speed = blockEntity.getSpeed(); - Direction.Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); - BlockPos pos = blockEntity.getBlockPos(); - float offset = BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos); - var model = Models.partial(AllPartialModels.COGWHEEL_SHAFT, axis, BracketedKineticBlockEntityVisual::rotateToAxis); - Instancer half = instancerProvider().instancer(AllInstanceTypes.ROTATING, model); - - additionalShaft = setup(half.createInstance(), speed); - additionalShaft.setRotationOffset(offset) - .setChanged(); - } - } - - @Override - protected Model model() { - if (!ICogWheel.isLargeCog(blockEntity.getBlockState())) - return super.model(); - - Direction.Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); - return Models.partial(AllPartialModels.SHAFTLESS_LARGE_COGWHEEL, axis, BracketedKineticBlockEntityVisual::rotateToAxis); - } - - private static void rotateToAxis(Direction.Axis axis, PoseStack ms) { - Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); - TransformStack.of(ms) - .center() - .rotateToFace(facing) - .rotate(Axis.XN.rotationDegrees(-90)) - .uncenter(); - } - - @Override - public void update(float pt) { - super.update(pt); - if (additionalShaft != null) { - updateRotation(additionalShaft); - additionalShaft.setRotationOffset(BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos)) - .setChanged(); + public static BlockEntityVisual create(VisualizationContext context, BracketedKineticBlockEntity blockEntity, float partialTick) { + if (ICogWheel.isLargeCog(blockEntity.getBlockState())) { + return new LargeCogVisual(context, blockEntity, partialTick); + } else { + Model model; + if (AllBlocks.COGWHEEL.is(blockEntity.getBlockState().getBlock())) { + model = Models.partial(AllPartialModels.COGWHEEL); + } else { + model = Models.partial(AllPartialModels.SHAFT); + } + return new SingleAxisRotatingVisual<>(context, blockEntity, partialTick, model); } } - @Override - public void updateLight(float partialTick) { - super.updateLight(partialTick); - if (additionalShaft != null) + // Large cogs sometimes have to offset their teeth by 11.25 degrees in order to + // mesh properly + public static class LargeCogVisual extends SingleAxisRotatingVisual { + + protected final RotatingInstance additionalShaft; + + private LargeCogVisual(VisualizationContext context, BracketedKineticBlockEntity blockEntity, float partialTick) { + super(context, blockEntity, partialTick, Models.partial(AllPartialModels.SHAFTLESS_LARGE_COGWHEEL)); + + Direction.Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); + + additionalShaft = instancerProvider().instancer(AllInstanceTypes.ROTATING, Models.partial(AllPartialModels.COGWHEEL_SHAFT)) + .createInstance(); + + additionalShaft.rotateToFace(axis) + .setup(blockEntity) + .setRotationOffset(BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos)) + .setPosition(getVisualPosition()) + .setChanged(); + } + + @Override + public void update(float pt) { + super.update(pt); + additionalShaft.setup(blockEntity) + .setRotationOffset(BracketedKineticBlockEntityRenderer.getShaftAngleOffset(rotationAxis(), pos)) + .setChanged(); + } + + @Override + public void updateLight(float partialTick) { + super.updateLight(partialTick); relight(additionalShaft); - } + } - @Override - protected void _delete() { - super._delete(); - if (additionalShaft != null) + @Override + protected void _delete() { + super._delete(); additionalShaft.delete(); - } + } - @Override - public void collectCrumblingInstances(Consumer consumer) { - super.collectCrumblingInstances(consumer); - if (additionalShaft != null) + @Override + public void collectCrumblingInstances(Consumer consumer) { + super.collectCrumblingInstances(consumer); consumer.accept(additionalShaft); + } } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockModel.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockModel.java index de8c36df0e..02518d8633 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockModel.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockModel.java @@ -5,8 +5,8 @@ import java.util.List; import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.render.VirtualRenderHelper; +import net.createmod.ponder.render.VirtualRenderHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -16,6 +16,7 @@ import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.client.model.BakedModelWrapper; import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.client.model.data.ModelProperty; diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogWheelBlock.java index c3be8c85c6..0f9e5eaf22 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogWheelBlock.java @@ -8,8 +8,8 @@ import com.simibubi.create.content.decoration.encasing.EncasableBlock; import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogwheelBlockItem.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogwheelBlockItem.java index a63c7aa68e..acf45bc4a6 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogwheelBlockItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogwheelBlockItem.java @@ -10,11 +10,11 @@ import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ShaftBlock.java index 4a5686f49c..0c9a5f7e82 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ShaftBlock.java @@ -9,11 +9,11 @@ import com.simibubi.create.content.decoration.encasing.EncasableBlock; import com.simibubi.create.content.decoration.girder.GirderEncasedShaftBlock; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.steamEngine.PoweredShaftBlock; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.foundation.placement.PoleHelper; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -124,11 +124,12 @@ public class ShaftBlock extends AbstractSimpleShaftBlock implements EncasableBlo @Override public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, - BlockHitResult ray) { + BlockHitResult ray) { PlacementOffset offset = super.getOffset(player, world, state, pos, ray); if (offset.isSuccessful()) offset.withTransform(offset.getTransform() - .andThen(s -> ShaftBlock.pickCorrectShaftType(s, world, offset.getBlockPos()))); + .andThen(s -> world.isClientSide() ? s + : ShaftBlock.pickCorrectShaftType(s, world, offset.getBlockPos()))); return offset; } diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogCTBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogCTBehaviour.java index 69ca1253b3..057f3a9276 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogCTBehaviour.java @@ -8,8 +8,8 @@ import com.simibubi.create.content.decoration.encasing.EncasedCTBehaviour; import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogRenderer.java index a2d40e7929..a8549c2c37 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogRenderer.java @@ -6,11 +6,11 @@ import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer; import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -40,16 +40,15 @@ public class EncasedCogRenderer extends KineticBlockEntityRenderer { @@ -38,37 +32,48 @@ public class EncasedCogVisual extends KineticBlockEntityVisual consumer) { consumer.accept(rotatingModel); diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogwheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogwheelBlock.java index b4d83eeca9..3f9c158acb 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogwheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogwheelBlock.java @@ -4,21 +4,22 @@ import java.util.function.Supplier; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.decoration.encasing.EncasedBlock; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VoxelShaper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -44,7 +45,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; public class EncasedCogwheelBlock extends RotatedPillarKineticBlock - implements ICogWheel, IBE, ISpecialBlockItemRequirement, ITransformableBlock, EncasedBlock { + implements ICogWheel, IBE, SpecialBlockItemRequirement, TransformableBlock, EncasedBlock { public static final BooleanProperty TOP_SHAFT = BooleanProperty.create("top_shaft"); public static final BooleanProperty BOTTOM_SHAFT = BooleanProperty.create("bottom_shaft"); @@ -70,8 +71,8 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock if (target instanceof BlockHitResult) return ((BlockHitResult) target).getDirection() .getAxis() != getRotationAxis(state) - ? isLarge ? AllBlocks.LARGE_COGWHEEL.asStack() : AllBlocks.COGWHEEL.asStack() - : getCasing().asItem().getDefaultInstance(); + ? isLarge ? AllBlocks.LARGE_COGWHEEL.asStack() : AllBlocks.COGWHEEL.asStack() + : getCasing().asItem().getDefaultInstance(); return super.getCloneItemStack(state, target, world, pos, player); } @@ -107,7 +108,7 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock BlockPos pos = context.getClickedPos(); KineticBlockEntity.switchToBlockState(level, pos, state.cycle(context.getClickedFace() .getAxisDirection() == AxisDirection.POSITIVE ? TOP_SHAFT : BOTTOM_SHAFT)); - playRotateSound(level, pos); + IWrenchable.playRotateSound(level, pos); return InteractionResult.SUCCESS; } @@ -196,18 +197,18 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock boolean clockwise = rotation == Rotation.CLOCKWISE_90; if (rotationAxis == Direction.Axis.X) { - if ( axis == Direction.Axis.Z && !clockwise - || axis == Direction.Axis.Y && clockwise) { + if (axis == Direction.Axis.Z && !clockwise + || axis == Direction.Axis.Y && clockwise) { return swapShafts(state); } } else if (rotationAxis == Direction.Axis.Y) { - if ( axis == Direction.Axis.X && !clockwise - || axis == Direction.Axis.Z && clockwise) { + if (axis == Direction.Axis.X && !clockwise + || axis == Direction.Axis.Z && clockwise) { return swapShafts(state); } } else if (rotationAxis == Direction.Axis.Z) { - if ( axis == Direction.Axis.Y && !clockwise - || axis == Direction.Axis.X && clockwise) { + if (axis == Direction.Axis.Y && !clockwise + || axis == Direction.Axis.X && clockwise) { return swapShafts(state); } } @@ -219,7 +220,7 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock public BlockState mirror(BlockState state, Mirror mirror) { Direction.Axis axis = state.getValue(AXIS); if (axis == Direction.Axis.X && mirror == Mirror.FRONT_BACK - || axis == Direction.Axis.Z && mirror == Mirror.LEFT_RIGHT) { + || axis == Direction.Axis.Z && mirror == Mirror.LEFT_RIGHT) { return swapShafts(state); } return state; @@ -269,20 +270,19 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock @Override public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand, - BlockHitResult ray) { + BlockHitResult ray) { BlockState encasedState = defaultBlockState() - .setValue(AXIS, state.getValue(AXIS)); + .setValue(AXIS, state.getValue(AXIS)); for (Direction d : Iterate.directionsInAxis(state.getValue(AXIS))) { BlockState adjacentState = level.getBlockState(pos.relative(d)); - if (!(adjacentState.getBlock() instanceof IRotate)) + if (!(adjacentState.getBlock() instanceof IRotate def)) continue; - IRotate def = (IRotate) adjacentState.getBlock(); if (!def.hasShaftTowards(level, pos.relative(d), adjacentState, d.getOpposite())) continue; encasedState = encasedState.cycle(d.getAxisDirection() == AxisDirection.POSITIVE ? EncasedCogwheelBlock.TOP_SHAFT - : EncasedCogwheelBlock.BOTTOM_SHAFT); + : EncasedCogwheelBlock.BOTTOM_SHAFT); } KineticBlockEntity.switchToBlockState(level, pos, encasedState); diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedShaftBlock.java index 584bc197c5..8d5d8a7972 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedShaftBlock.java @@ -4,11 +4,11 @@ import java.util.function.Supplier; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.decoration.encasing.EncasedBlock; import com.simibubi.create.content.kinetics.base.AbstractEncasedShaftBlock; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.block.IBE; @@ -28,7 +28,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; public class EncasedShaftBlock extends AbstractEncasedShaftBlock - implements IBE, ISpecialBlockItemRequirement, EncasedBlock { + implements IBE, SpecialBlockItemRequirement, EncasedBlock { private final Supplier casing; diff --git a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlock.java b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlock.java index b446287849..db75cdc052 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlock.java @@ -11,10 +11,10 @@ import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; @@ -110,7 +110,7 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements public Class getBlockEntityClass() { return SpeedControllerBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.ROTATION_SPEED_CONTROLLER.get(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlockEntity.java index b76ecf9742..dcb869b5ba 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlockEntity.java @@ -16,10 +16,10 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -52,7 +52,7 @@ public class SpeedControllerBlockEntity extends KineticBlockEntity { super.addBehaviours(behaviours); Integer max = AllConfigs.server().kinetics.maxRotationSpeed.get(); - targetSpeed = new KineticScrollValueBehaviour(Lang.translateDirect("kinetics.speed_controller.rotation_speed"), + targetSpeed = new KineticScrollValueBehaviour(CreateLang.translateDirect("kinetics.speed_controller.rotation_speed"), this, new ControllerValueBoxTransform()); targetSpeed.between(-max, max); targetSpeed.value = DEFAULT_SPEED; diff --git a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerRenderer.java index d785cdfda3..89288ff734 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerRenderer.java @@ -5,10 +5,10 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.Sheets; @@ -43,7 +43,7 @@ public class SpeedControllerRenderer extends SmartBlockEntityRenderer BlockHelper.copyProperties(s, AllBlocks.POWERED_SHAFT.getDefaultState()) + s -> BlockHelper + .copyProperties(s, + (world.isClientSide ? AllBlocks.SHAFT : AllBlocks.POWERED_SHAFT).getDefaultState()) .setValue(PoweredShaftBlock.AXIS, axis)); } } - + public static Couple getSpeedRange() { return Couple.create(16, 64); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlockEntity.java index e98030091c..13c5f651ab 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlockEntity.java @@ -6,9 +6,8 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlockEntity.RotationDirection; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; import com.simibubi.create.content.kinetics.base.IRotate; @@ -17,23 +16,22 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -54,7 +52,7 @@ public class SteamEngineBlockEntity extends SmartBlockEntity implements IHaveGog @Override public void addBehaviours(List behaviours) { movementDirection = new ScrollOptionBehaviour<>(RotationDirection.class, - Lang.translateDirect("contraptions.windmill.rotation_direction"), this, new SteamEngineValueBox()); + CreateLang.translateDirect("contraptions.windmill.rotation_direction"), this, new SteamEngineValueBox()); movementDirection.onlyActiveWhen(() -> { PoweredShaftBlockEntity shaft = getShaft(); return shaft == null || !shaft.hasSource(); @@ -65,7 +63,8 @@ public class SteamEngineBlockEntity extends SmartBlockEntity implements IHaveGog registerAwardables(behaviours, AllAdvancements.STEAM_ENGINE); } - private void onDirectionChanged() {} + private void onDirectionChanged() { + } @Override public void tick() { @@ -93,7 +92,7 @@ public class SteamEngineBlockEntity extends SmartBlockEntity implements IHaveGog boolean verticalTarget = false; BlockState shaftState = shaft.getBlockState(); Axis targetAxis = Axis.X; - if (shaftState.getBlock()instanceof IRotate ir) + if (shaftState.getBlock() instanceof IRotate ir) targetAxis = ir.getRotationAxis(shaftState); verticalTarget = targetAxis == Axis.Y; @@ -208,11 +207,7 @@ public class SteamEngineBlockEntity extends SmartBlockEntity implements IHaveGog if (sourceBE != null) { FluidTankBlockEntity controller = sourceBE.getControllerBE(); if (controller != null && controller.boiler != null) { - float volume = 3f / Math.max(2, controller.boiler.attachedEngines / 6); - float pitch = 1.18f - level.random.nextFloat() * .25f; - level.playLocalSound(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(), - SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, volume, pitch, false); - AllSoundEvents.STEAM.playAt(level, worldPosition, volume / 16, .8f, false); + controller.boiler.queueSoundOnSide(worldPosition, SteamEngineBlock.getFacing(getBlockState())); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineRenderer.java index e797a611e0..201b5f21c3 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineRenderer.java @@ -5,12 +5,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -75,7 +75,7 @@ public class SteamEngineRenderer extends SafeBlockEntityRenderer DESERIALIZER = - new ParticleOptions.Deserializer() { + new ParticleOptions.Deserializer<>() { public SteamJetParticleData fromCommand(ParticleType particleTypeIn, - StringReader reader) throws CommandSyntaxException { + StringReader reader) throws CommandSyntaxException { reader.expect(' '); float speed = reader.readFloat(); return new SteamJetParticleData(speed); } public SteamJetParticleData fromNetwork(ParticleType particleTypeIn, - FriendlyByteBuf buffer) { + FriendlyByteBuf buffer) { return new SteamJetParticleData(buffer.readFloat()); } }; @@ -79,4 +80,4 @@ public class SteamJetParticleData implements ParticleOptions, ICustomParticleDat return SteamJetParticle.Factory::new; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlock.java index b67d01d474..307772c282 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlock.java @@ -38,12 +38,12 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements IBE getBlockEntityClass() { return SplitShaftBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.GEARSHIFT.get(); @@ -72,15 +72,14 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements IBE getOptions() { List options = new ArrayList<>(); for (InstructionSpeedModifiers entry : values()) - options.add(Lang.translateDirect(entry.translationKey)); + options.add(CreateLang.translateDirect(entry.translationKey)); return options; } diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlock.java index 0963f530b0..ae2ead23d2 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlock.java @@ -2,14 +2,14 @@ package com.simibubi.create.content.kinetics.transmission.sequencer; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; import com.simibubi.create.content.kinetics.base.KineticBlock; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.gui.ScreenOpener; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -33,11 +33,12 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.phys.BlockHitResult; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; -public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implements IBE, ITransformableBlock { +public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implements IBE, TransformableBlock { public static final BooleanProperty VERTICAL = BooleanProperty.create("vertical"); public static final IntegerProperty STATE = IntegerProperty.create("state", 0, 5); @@ -52,18 +53,18 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen } @Override - public boolean shouldCheckWeakPower(BlockState state, SignalGetter level, BlockPos pos, Direction side) { - return false; - } + public boolean shouldCheckWeakPower(BlockState state, SignalGetter level, BlockPos pos, Direction side) { + return false; + } @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - if (worldIn.isClientSide) + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, + boolean isMoving) { + if (level.isClientSide) return; - if (!worldIn.getBlockTicks() + if (!level.getBlockTicks() .willTickThisTick(pos, this)) - worldIn.scheduleTick(pos, this, 0); + level.scheduleTick(pos, this, 1); } @Override @@ -88,12 +89,11 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen @Override public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { + BlockHitResult hit) { ItemStack held = player.getMainHandItem(); if (AllItems.WRENCH.isIn(held)) return InteractionResult.PASS; - if (held.getItem() instanceof BlockItem) { - BlockItem blockItem = (BlockItem) held.getItem(); + if (held.getItem() instanceof BlockItem blockItem) { if (blockItem.getBlock() instanceof KineticBlock && hasShaftTowards(worldIn, pos, state, hit.getDirection())) return InteractionResult.PASS; } @@ -151,7 +151,7 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen public Class getBlockEntityClass() { return SequencedGearshiftBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.SEQUENCED_GEARSHIFT.get(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlockEntity.java index a114c37283..5112f821bf 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlockEntity.java @@ -12,8 +12,8 @@ import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.transmission.SplitShaftBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -31,7 +31,7 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity { float currentInstructionProgress; int timer; boolean poweredPreviously; - + public AbstractComputerBehaviour computerBehaviour; public record SequenceContext(SequencerInstructions instruction, double relativeValue) { @@ -190,7 +190,7 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity { @Override protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {} - + @Override public void write(CompoundTag compound, boolean clientPacket) { compound.putInt("InstructionIndex", currentInstruction); diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftScreen.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftScreen.java index 6afcf0696a..7a67f21037 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftScreen.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftScreen.java @@ -5,16 +5,15 @@ import java.util.Vector; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; import com.simibubi.create.compat.computercraft.ComputerScreen; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.nbt.ListTag; import net.minecraft.network.chat.Component; @@ -33,7 +32,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { private Vector> inputs; public SequencedGearshiftScreen(SequencedGearshiftBlockEntity be) { - super(Lang.translateDirect("gui.sequenced_gearshift.title")); + super(CreateLang.translateDirect("gui.sequenced_gearshift.title")); this.instructions = be.instructions; this.be = be; compareTag = Instruction.serializeAll(instructions); @@ -45,7 +44,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { minecraft.setScreen( new ComputerScreen(title, this::renderAdditional, this, be.computerBehaviour::hasAttachedComputer)); - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); setWindowOffset(-20, 0); super.init(); @@ -59,7 +58,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { for (int row = 0; row < instructions.size(); row++) initInputsOfRow(row, x, y); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { onClose(); }); @@ -81,13 +80,13 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { new SelectionScrollInput(x, y + rowHeight * row, 50, 18).forOptions(SequencerInstructions.getOptions()) .calling(state -> instructionUpdated(index, state)) .setState(instruction.instruction.ordinal()) - .titled(Lang.translateDirect("gui.sequenced_gearshift.instruction")); + .titled(CreateLang.translateDirect("gui.sequenced_gearshift.instruction")); ScrollInput value = new ScrollInput(x + 58, y + rowHeight * row, 28, 18).calling(state -> instruction.value = state); ScrollInput direction = new SelectionScrollInput(x + 88, y + rowHeight * row, 28, 18) .forOptions(InstructionSpeedModifiers.getOptions()) .calling(state -> instruction.speedModifier = InstructionSpeedModifiers.values()[state]) - .titled(Lang.translateDirect("gui.sequenced_gearshift.speed")); + .titled(CreateLang.translateDirect("gui.sequenced_gearshift.speed")); rowInputs.add(type); rowInputs.add(value); @@ -108,7 +107,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { value.active = value.visible = hasValue; if (hasValue) value.withRange(1, def.maxValue + 1) - .titled(Lang.translateDirect(def.parameterKey)) + .titled(CreateLang.translateDirect(def.parameterKey)) .withShiftStep(def.shiftStep) .setState(instruction.value) .onChanged(); @@ -148,14 +147,14 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { for (int row = 0; row < instructions.capacity(); row++) { AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; - int yOffset = toDraw.height * row; + int yOffset = toDraw.getHeight() * row; toDraw.render(graphics, x, y + 16 + yOffset); } for (int row = 0; row < instructions.capacity(); row++) { AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; - int yOffset = toDraw.height * row; + int yOffset = toDraw.getHeight() * row; if (row >= instructions.size()) { toDraw.render(graphics, x, y + 16 + yOffset); continue; @@ -165,24 +164,24 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { SequencerInstructions def = instruction.instruction; def.background.render(graphics, x, y + 16 + yOffset); - label(graphics, 36, yOffset - 1, Lang.translateDirect(def.translationKey)); + label(graphics, 36, yOffset - 1, CreateLang.translateDirect(def.translationKey)); if (def.hasValueParameter) { String text = def.formatValue(instruction.value); int stringWidth = font.width(text); - label(graphics, 90 + (12 - stringWidth / 2), yOffset - 1, Components.literal(text)); + label(graphics, 90 + (12 - stringWidth / 2), yOffset - 1, Component.literal(text)); } if (def.hasSpeedParameter) label(graphics, 127, yOffset - 1, instruction.speedModifier.label); } - graphics.drawString(font, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, 0x592424, false); + graphics.drawString(font, title, x + (background.getWidth() - 8) / 2 - font.width(title) / 2, y + 4, 0x592424, false); renderAdditional(graphics, mouseX, mouseY, partialTicks, x, y, background); } private void renderAdditional(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, - AllGuiTextures background) { + AllGuiTextures background) { GuiGameElement.of(renderedItem).at(guiLeft + background.width + 6, guiTop + background.height - 56, 100) + .GuiRenderBuilder>at(guiLeft + background.getWidth() + 6, guiTop + background.getHeight() - 56, 100) .scale(5) .render(graphics); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencerInstructions.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencerInstructions.java index 6ba463772e..575e5b7b50 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencerInstructions.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencerInstructions.java @@ -4,8 +4,9 @@ import java.util.ArrayList; import java.util.List; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.Lang; import net.minecraft.network.chat.Component; public enum SequencerInstructions { @@ -44,7 +45,7 @@ public enum SequencerInstructions { descriptiveTranslationKey = translationKey + ".descriptive"; parameterKey = translationKey + "." + parameterName; } - + public boolean needsPropagation() { return this == TURN_ANGLE || this == TURN_DISTANCE; } @@ -52,13 +53,13 @@ public enum SequencerInstructions { static List getOptions() { List options = new ArrayList<>(); for (SequencerInstructions entry : values()) - options.add(Lang.translateDirect(entry.descriptiveTranslationKey)); + options.add(CreateLang.translateDirect(entry.descriptiveTranslationKey)); return options; } String formatValue(int value) { if (this == TURN_ANGLE) - return value + Lang.translateDirect("generic.unit.degrees").getString(); + return value + CreateLang.translateDirect("generic.unit.degrees").getString(); if (this == TURN_DISTANCE) return value + "m"; if (this == DELAY) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlock.java b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlock.java index 3480404c94..8b06993513 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlock.java @@ -5,8 +5,8 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.content.kinetics.base.KineticBlock; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -102,12 +102,12 @@ public class TurntableBlock extends KineticBlock implements IBE getBlockEntityClass() { return TurntableBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.TURNTABLE.get(); } - + @Override public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { return false; diff --git a/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableHandler.java b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableHandler.java index 349adbb0c0..cdebcda673 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableHandler.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.kinetics.turntable; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; @@ -26,20 +26,19 @@ public class TurntableHandler { return; BlockEntity blockEntity = mc.level.getBlockEntity(pos); - if (!(blockEntity instanceof TurntableBlockEntity)) + if (!(blockEntity instanceof TurntableBlockEntity turnTable)) return; - - TurntableBlockEntity turnTable = (TurntableBlockEntity) blockEntity; - float speed = turnTable.getSpeed() * 3/10; + + float speed = turnTable.getSpeed() * 3 / 10; if (speed == 0) return; - + Vec3 origin = VecHelper.getCenterOf(pos); Vec3 offset = mc.player.position().subtract(origin); - - if (offset.length() > 1/4f) - speed *= Mth.clamp((1/2f - offset.length()) * 2, 0, 1); + + if (offset.length() > 1 / 4f) + speed *= Mth.clamp((1 / 2f - offset.length()) * 2, 0, 1); mc.player.setYRot(mc.player.yRotO - speed * AnimationTickHolder.getPartialTicks()); mc.player.yBodyRot = mc.player.getYRot(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlock.java index 8d7296ea3a..a2701b9f10 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlock.java @@ -4,9 +4,8 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -164,10 +163,6 @@ public class LargeWaterWheelBlock extends RotatedPillarKineticBlock implements I return 2.25f; } - public static Couple getSpeedRange() { - return Couple.create(4, 4); - } - @Override public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { return false; diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockItem.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockItem.java index 9fb7e0e44f..0e51e2ed0e 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockItem.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.kinetics.waterwheel; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -15,6 +15,7 @@ import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.Block; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -48,10 +49,10 @@ public class LargeWaterWheelBlockItem extends BlockItem { .getNormal()); if (!(context.getPlayer()instanceof LocalPlayer localPlayer)) return; - CreateClient.OUTLINER.showAABB(Pair.of("waterwheel", pos), new AABB(pos).inflate(1) + Outliner.getInstance().showAABB(Pair.of("waterwheel", pos), new AABB(pos).inflate(1) .deflate(contract.x, contract.y, contract.z)) .colored(0xFF_ff5d6c); - Lang.translate("large_water_wheel.not_enough_space") + CreateLang.translate("large_water_wheel.not_enough_space") .color(0xFF_ff5d6c) .sendStatus(localPlayer); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlock.java index 6a520c7e38..cffe2b78b4 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlock.java @@ -4,10 +4,9 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.levelWrappers.WrappedLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -57,7 +56,7 @@ public class WaterWheelBlock extends DirectionalKineticBlock implements IBE getSpeedRange() { - return Couple.create(8, 8); - } - @Override public boolean isFlammable(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { return false; diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlockEntity.java index 31e1b450e2..8eba206796 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlockEntity.java @@ -11,9 +11,9 @@ import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -199,6 +199,12 @@ public class WaterWheelBlockEntity extends GeneratingKineticBlockEntity { redraw(); } + @Override + public void writeSafe(CompoundTag tag) { + super.writeSafe(tag); + tag.put("Material", NbtUtils.writeBlockState(material)); + } + @Override public void write(CompoundTag compound, boolean clientPacket) { super.write(compound, clientPacket); diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelModelKey.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelModelKey.java deleted file mode 100644 index 4999cb96db..0000000000 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelModelKey.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.simibubi.create.content.kinetics.waterwheel; - -import net.minecraft.world.level.block.state.BlockState; - -public record WaterWheelModelKey(boolean large, BlockState state, BlockState material) { -} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelRenderer.java index a19694ea44..a76dd26df6 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelRenderer.java @@ -8,17 +8,17 @@ import javax.annotation.Nullable; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.foundation.model.BakedModelHelper; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.StitchedSprite; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.SuperByteBufferCache.Compartment; -import com.simibubi.create.foundation.render.VirtualRenderHelper; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import dev.engine_room.flywheel.lib.model.baked.PartialModel; import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.StitchedSprite; +import net.createmod.catnip.render.SuperBufferFactory; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.render.SuperByteBufferCache; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; @@ -36,7 +36,7 @@ import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.registries.ForgeRegistries; public class WaterWheelRenderer extends KineticBlockEntityRenderer { - public static final Compartment WATER_WHEEL = new Compartment<>(); + public static final SuperByteBufferCache.Compartment WATER_WHEEL = new SuperByteBufferCache.Compartment<>(); public static final StitchedSprite OAK_PLANKS_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_planks")); public static final StitchedSprite OAK_LOG_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_log")); @@ -59,8 +59,8 @@ public class WaterWheelRenderer extends Kinetic @Override protected SuperByteBuffer getRotatedModel(T be, BlockState state) { - WaterWheelModelKey key = new WaterWheelModelKey(large, state, be.material); - return CreateClient.BUFFER_CACHE.get(WATER_WHEEL, key, () -> { + ModelKey key = new ModelKey(large, state, be.material); + return SuperByteBufferCache.getInstance().get(WATER_WHEEL, key, () -> { BakedModel model = generateModel(key); BlockState state1 = key.state(); Direction dir; @@ -69,31 +69,22 @@ public class WaterWheelRenderer extends Kinetic } else { dir = state1.getValue(WaterWheelBlock.FACING); } - PoseStack transform = CachedBufferer.rotateToFaceVertical(dir).get(); - return VirtualRenderHelper.bufferModel(model, Blocks.AIR.defaultBlockState(), transform); + PoseStack transform = CachedBuffers.rotateToFaceVertical(dir).get(); + return SuperBufferFactory.getInstance().createForBlock(model, Blocks.AIR.defaultBlockState(), transform); }); } - public static BakedModel generateModel(WaterWheelModelKey key) { - BakedModel template; - if (key.large()) { - boolean extension = key.state() - .getValue(LargeWaterWheelBlock.EXTENSION); - if (extension) { - template = AllPartialModels.LARGE_WATER_WHEEL_EXTENSION.get(); - } else { - template = AllPartialModels.LARGE_WATER_WHEEL.get(); - } - } else { - template = AllPartialModels.WATER_WHEEL.get(); - } + public static BakedModel generateModel(ModelKey key) { + return generateModel(Variant.of(key.large(), key.state()), key.material()); + } - return generateModel(template, key.material()); + public static BakedModel generateModel(Variant variant, BlockState material) { + return generateModel(variant.model(), material); } public static BakedModel generateModel(BakedModel template, BlockState planksBlockState) { Block planksBlock = planksBlockState.getBlock(); - ResourceLocation id = RegisteredObjects.getKeyOrThrow(planksBlock); + ResourceLocation id = CatnipServices.REGISTRIES.getKeyOrThrow(planksBlock); String wood = plankStateToWoodName(planksBlockState); if (wood == null) @@ -113,7 +104,7 @@ public class WaterWheelRenderer extends Kinetic @Nullable private static String plankStateToWoodName(BlockState planksBlockState) { Block planksBlock = planksBlockState.getBlock(); - ResourceLocation id = RegisteredObjects.getKeyOrThrow(planksBlock); + ResourceLocation id = CatnipServices.REGISTRIES.getKeyOrThrow(planksBlock); String path = id.getPath(); if (path.endsWith("_planks")) // Covers most wood types @@ -169,4 +160,36 @@ public class WaterWheelRenderer extends Kinetic return model.getParticleIcon(ModelData.EMPTY); } + public enum Variant { + SMALL(AllPartialModels.WATER_WHEEL), + LARGE(AllPartialModels.LARGE_WATER_WHEEL), + LARGE_EXTENSION(AllPartialModels.LARGE_WATER_WHEEL_EXTENSION), + ; + + private final PartialModel partial; + + Variant(PartialModel partial) { + this.partial = partial; + } + + public BakedModel model() { + return partial.get(); + } + + public static Variant of(boolean large, BlockState blockState) { + if (large) { + boolean extension = blockState.getValue(LargeWaterWheelBlock.EXTENSION); + if (extension) { + return LARGE_EXTENSION; + } else { + return LARGE; + } + } else { + return SMALL; + } + } + } + + public record ModelKey(boolean large, BlockState state, BlockState material) { + } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelStructuralBlock.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelStructuralBlock.java index 8d9b0b8bdc..15f7790786 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelStructuralBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelStructuralBlock.java @@ -7,7 +7,7 @@ import java.util.function.Consumer; import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.equipment.goggles.IProxyHoveringInformation; +import com.simibubi.create.api.equipment.goggles.IProxyHoveringInformation; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.render.MultiPosDestructionHandler; @@ -35,6 +35,7 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientBlockExtensions; @@ -88,10 +89,10 @@ public class WaterWheelStructuralBlock extends DirectionalBlock implements IWren @Override public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, - BlockHitResult pHit) { + BlockHitResult pHit) { if (!stillValid(pLevel, pPos, pState, false)) return InteractionResult.FAIL; - if (!(pLevel.getBlockEntity(getMaster(pLevel, pPos, pState))instanceof WaterWheelBlockEntity wwt)) + if (!(pLevel.getBlockEntity(getMaster(pLevel, pPos, pState)) instanceof WaterWheelBlockEntity wwt)) return InteractionResult.FAIL; return wwt.applyMaterialIfValid(pPlayer.getItemInHand(pHand)); } @@ -114,7 +115,7 @@ public class WaterWheelStructuralBlock extends DirectionalBlock implements IWren @Override public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, - BlockPos pCurrentPos, BlockPos pFacingPos) { + BlockPos pCurrentPos, BlockPos pFacingPos) { if (stillValid(pLevel, pCurrentPos, pState, false)) { BlockPos masterPos = getMaster(pLevel, pCurrentPos, pState); if (!pLevel.getBlockTicks() @@ -166,7 +167,7 @@ public class WaterWheelStructuralBlock extends DirectionalBlock implements IWren @Override public boolean addLandingEffects(BlockState state1, ServerLevel level, BlockPos pos, BlockState state2, - LivingEntity entity, int numberOfParticles) { + LivingEntity entity, int numberOfParticles) { return true; } diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelVisual.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelVisual.java index e53f651bec..886e808221 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelVisual.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelVisual.java @@ -2,24 +2,21 @@ package com.simibubi.create.content.kinetics.waterwheel; import java.util.function.Consumer; -import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.kinetics.base.KineticBlockEntityVisual; import com.simibubi.create.content.kinetics.base.RotatingInstance; +import com.simibubi.create.content.kinetics.waterwheel.WaterWheelRenderer.Variant; import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.render.CachedBufferer; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder; -import dev.engine_room.flywheel.lib.util.ResourceReloadCache; +import dev.engine_room.flywheel.lib.util.RendererReloadCache; import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.AxisDirection; import net.minecraft.world.level.block.state.BlockState; public class WaterWheelVisual extends KineticBlockEntityVisual { - private static final ResourceReloadCache MODEL_CACHE = new ResourceReloadCache<>(WaterWheelVisual::createModel); + private static final RendererReloadCache MODEL_CACHE = new RendererReloadCache<>(WaterWheelVisual::createModel); protected final boolean large; protected BlockState lastMaterial; @@ -42,9 +39,12 @@ public class WaterWheelVisual extends KineticBl private void setupInstance() { lastMaterial = blockEntity.material; - rotatingModel = instancerProvider().instancer(AllInstanceTypes.ROTATING, MODEL_CACHE.get(new WaterWheelModelKey(large, blockState, blockEntity.material))) + rotatingModel = instancerProvider().instancer(AllInstanceTypes.ROTATING, MODEL_CACHE.get(new ModelKey(Variant.of(large, blockState), blockEntity.material))) .createInstance(); - setup(rotatingModel); + rotatingModel.setup(blockEntity) + .setPosition(getVisualPosition()) + .rotateToFace(rotationAxis()) + .setChanged(); } @Override @@ -52,9 +52,10 @@ public class WaterWheelVisual extends KineticBl if (lastMaterial != blockEntity.material) { rotatingModel.delete(); setupInstance(); + } else { + rotatingModel.setup(blockEntity) + .setChanged(); } - - updateRotation(rotatingModel); } @Override @@ -72,18 +73,13 @@ public class WaterWheelVisual extends KineticBl consumer.accept(rotatingModel); } - private static Model createModel(WaterWheelModelKey key) { - BakedModel model = WaterWheelRenderer.generateModel(key); - BlockState state = key.state(); - Direction dir; - if (key.large()) { - dir = Direction.fromAxisAndDirection(state.getValue(LargeWaterWheelBlock.AXIS), AxisDirection.POSITIVE); - } else { - dir = state.getValue(WaterWheelBlock.FACING); - } - PoseStack transform = CachedBufferer.rotateToFaceVertical(dir).get(); + private static Model createModel(ModelKey key) { + BakedModel model = WaterWheelRenderer.generateModel(key.variant(), key.material()); return BakedModelBuilder.create(model) - .poseStack(transform) .build(); } + + public record ModelKey(WaterWheelRenderer.Variant variant, BlockState material) { + + } } diff --git a/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundColor.java b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundColor.java index 6d00c28a16..47e0a05bcc 100644 --- a/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundColor.java +++ b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundColor.java @@ -1,8 +1,7 @@ package com.simibubi.create.content.legacy; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; - +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.color.item.ItemColor; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundItem.java b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundItem.java index 6c68e346b6..6a372ae9a0 100644 --- a/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundItem.java +++ b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundItem.java @@ -7,11 +7,11 @@ import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackH import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CRecipes; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; @@ -135,11 +135,9 @@ public class ChromaticCompoundItem extends Item { if (state.getBlock() == Blocks.BEACON) { BlockEntity be = world.getBlockEntity(testPos); - if (!(be instanceof BeaconBlockEntity)) + if (!(be instanceof BeaconBlockEntity bte)) break; - BeaconBlockEntity bte = (BeaconBlockEntity) be; - if (!bte.beamSections.isEmpty()) isOverBeacon = true; @@ -180,10 +178,9 @@ public class ChromaticCompoundItem extends Item { behaviour.handleProcessingOnAllItems(ts -> { ItemStack heldStack = ts.stack; - if (!(heldStack.getItem() instanceof BlockItem)) + if (!(heldStack.getItem() instanceof BlockItem blockItem)) return TransportedResult.doNothing(); - BlockItem blockItem = (BlockItem) heldStack.getItem(); if (blockItem.getBlock() == null) return TransportedResult.doNothing(); @@ -207,7 +204,7 @@ public class ChromaticCompoundItem extends Item { } public boolean checkLight(ItemStack stack, ItemEntity entity, Level world, CompoundTag itemData, Vec3 positionVec, - BlockPos randomOffset, BlockState state) { + BlockPos randomOffset, BlockState state) { if (state.getLightEmission(world, randomOffset) == 0) return false; if (state.getDestroySpeed(world, randomOffset) == -1) diff --git a/src/main/java/com/simibubi/create/content/legacy/NoGravMagicalDohickyItem.java b/src/main/java/com/simibubi/create/content/legacy/NoGravMagicalDohickyItem.java index 2fc2de2128..82c65b9c75 100644 --- a/src/main/java/com/simibubi/create/content/legacy/NoGravMagicalDohickyItem.java +++ b/src/main/java/com/simibubi/create/content/legacy/NoGravMagicalDohickyItem.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.legacy; -import com.simibubi.create.foundation.utility.VecHelper; - +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/logistics/AddressEditBox.java b/src/main/java/com/simibubi/create/content/logistics/AddressEditBox.java new file mode 100644 index 0000000000..d978c8917c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/AddressEditBox.java @@ -0,0 +1,153 @@ +package com.simibubi.create.content.logistics; + +import java.util.List; +import java.util.function.Consumer; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.trains.schedule.DestinationSuggestions; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; + +public class AddressEditBox extends EditBox { + + private DestinationSuggestions destinationSuggestions; + private Consumer mainResponder; + private String prevValue = "=)"; + + public AddressEditBox(Screen screen, Font pFont, int pX, int pY, int pWidth, int pHeight, boolean anchorToBottom) { + this(screen, pFont, pX, pY, pWidth, pHeight, anchorToBottom, null); + } + + public AddressEditBox(Screen screen, Font pFont, int pX, int pY, int pWidth, int pHeight, boolean anchorToBottom, String localAddress) { + super(pFont, pX, pY, pWidth, pHeight, Component.empty()); + destinationSuggestions = AddressEditBoxHelper.createSuggestions(screen, this, anchorToBottom, localAddress); + destinationSuggestions.setAllowSuggestions(true); + destinationSuggestions.updateCommandInfo(); + mainResponder = t -> { + if (!t.equals(prevValue)) + destinationSuggestions.updateCommandInfo(); + prevValue = t; + }; + setResponder(mainResponder); + setBordered(false); + setFocused(false); + mouseClicked(0, 0, 0); + setMaxLength(25); + } + + @Override + public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { + if (destinationSuggestions.keyPressed(pKeyCode, pScanCode, pModifiers)) + return true; + if (isFocused() && pKeyCode == GLFW.GLFW_KEY_ENTER) { + setFocused(false); + moveCursorToEnd(); + mouseClicked(0, 0, 0); + return true; + } + return super.keyPressed(pKeyCode, pScanCode, pModifiers); + } + + @Override + public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) { + if (destinationSuggestions.mouseScrolled(Mth.clamp(pDelta, -1.0D, 1.0D))) + return true; + return super.mouseScrolled(pMouseX, pMouseY, pDelta); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + if (pButton == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { + if (isMouseOver(pMouseX, pMouseY)) { + setValue(""); + return true; + } + } + + boolean wasFocused = isFocused(); + if (super.mouseClicked(pMouseX, pMouseY, pButton)) { + if (!wasFocused) { + setHighlightPos(0); + setCursorPosition(getValue().length()); + } + return true; + } + if (destinationSuggestions.mouseClicked((int) pMouseX, (int) pMouseY, pButton)) + return true; + return false; + } + + @Override + public void setValue(String text) { + super.setValue(text); + } + + @Override + public void setFocused(boolean focused) { + super.setFocused(focused); + } + + @Override + public void renderWidget(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + super.renderWidget(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + PoseStack matrixStack = pGuiGraphics.pose(); + matrixStack.pushPose(); + matrixStack.translate(0, 0, 500); + destinationSuggestions.render(pGuiGraphics, pMouseX, pMouseY); + matrixStack.popPose(); + + if (!destinationSuggestions.isEmpty()) + return; + + int itemX = getX() + width + 4; + int itemY = getY() - 4; + pGuiGraphics.renderItem(AllBlocks.CLIPBOARD.asStack(), itemX, itemY); + if (pMouseX >= itemX && pMouseX < itemX + 16 && pMouseY >= itemY && pMouseY < itemY + 16) { + List promiseTip = List.of(); + promiseTip = List.of(CreateLang.translate("gui.address_box.clipboard_tip") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.address_box.clipboard_tip_1") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.address_box.clipboard_tip_2") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.address_box.clipboard_tip_3") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.address_box.clipboard_tip_4") + .style(ChatFormatting.DARK_GRAY) + .component()); + pGuiGraphics.renderComponentTooltip(Minecraft.getInstance().font, promiseTip, pMouseX, pMouseY); + } + } + + @Override + public void setResponder(Consumer pResponder) { + super.setResponder(pResponder == mainResponder ? mainResponder : mainResponder.andThen(pResponder)); + } + + @Override + public void tick() { + super.tick(); + if (!isFocused()) + destinationSuggestions.hide(); + if (isFocused() && destinationSuggestions.suggestions == null) + destinationSuggestions.updateCommandInfo(); + destinationSuggestions.tick(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/AddressEditBoxHelper.java b/src/main/java/com/simibubi/create/content/logistics/AddressEditBoxHelper.java new file mode 100644 index 0000000000..47f159f980 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/AddressEditBoxHelper.java @@ -0,0 +1,93 @@ +package com.simibubi.create.content.logistics; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.google.common.cache.Cache; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.equipment.clipboard.ClipboardBlockEntity; +import com.simibubi.create.content.equipment.clipboard.ClipboardEntry; +import com.simibubi.create.content.trains.schedule.DestinationSuggestions; +import com.simibubi.create.foundation.utility.TickBasedCache; + +import net.createmod.catnip.data.IntAttached; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +public class AddressEditBoxHelper { + + private static final Cache> NEARBY_CLIPBOARDS = new TickBasedCache<>(20, false); + + public static void advertiseClipboard(ClipboardBlockEntity blockEntity) { + Minecraft mc = Minecraft.getInstance(); + Player player = mc.player; + if (player == null) + return; + BlockPos blockPos = blockEntity.getBlockPos(); + if (player.distanceToSqr(Vec3.atCenterOf(blockPos)) > 32 * 32) + return; + NEARBY_CLIPBOARDS.put(blockPos, new WeakReference<>(blockEntity)); + } + + public static DestinationSuggestions createSuggestions(Screen screen, EditBox pInput, boolean anchorToBottom, String localAddress) { + Minecraft mc = Minecraft.getInstance(); + Player player = mc.player; + List> options = new ArrayList<>(); + Set alreadyAdded = new HashSet<>(); + + DestinationSuggestions destinationSuggestions = new DestinationSuggestions(mc, screen, pInput, mc.font, options, + anchorToBottom, -72 + pInput.getY() + (anchorToBottom ? 0 : pInput.getHeight())); + + if (player == null) + return destinationSuggestions; + + if (localAddress != null) { + options.add(IntAttached.with(-1, localAddress)); + alreadyAdded.add(localAddress); + } + + for (int i = 0; i < Inventory.INVENTORY_SIZE; i++) + appendAddresses(options, alreadyAdded, player.getInventory() + .getItem(i)); + + for (WeakReference wr : NEARBY_CLIPBOARDS.asMap() + .values()) { + ClipboardBlockEntity cbe = wr.get(); + if (cbe != null) + appendAddresses(options, alreadyAdded, cbe.dataContainer); + } + + return destinationSuggestions; + } + + private static void appendAddresses(List> options, Set alreadyAdded, ItemStack item) { + if (item == null || !AllBlocks.CLIPBOARD.isIn(item)) + return; + + List> pages = ClipboardEntry.readAll(item); + pages.forEach(page -> page.forEach(entry -> { + String string = entry.text.getString(); + if (entry.checked) + return; + if (!string.startsWith("#") || string.length() <= 1) + return; + String address = string.substring(1); + if (address.isBlank()) + return; + String trim = address.trim(); + if (!alreadyAdded.add(trim)) + return; + options.add(IntAttached.withZero(trim)); + })); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/BigItemStack.java b/src/main/java/com/simibubi/create/content/logistics/BigItemStack.java new file mode 100644 index 0000000000..c6517e1e7a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/BigItemStack.java @@ -0,0 +1,78 @@ +package com.simibubi.create.content.logistics; + +import java.util.Comparator; +import java.util.Objects; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; + +public class BigItemStack { + + public static final int INF = 1_000_000_000; + + public ItemStack stack; + public int count; + + public BigItemStack(ItemStack stack) { + this(stack, 1); + } + + public BigItemStack(ItemStack stack, int count) { + this.stack = stack; + this.count = count; + } + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + tag.put("Item", stack.serializeNBT()); + tag.putInt("Amount", count); + return tag; + } + + public static BigItemStack read(CompoundTag tag) { + return new BigItemStack(ItemStack.of(tag.getCompound("Item")), tag.getInt("Amount")); + } + + public void send(FriendlyByteBuf buffer) { + buffer.writeItem(stack); + buffer.writeVarInt(count); + } + + public boolean isInfinite() { + return count >= INF; + } + + public static BigItemStack receive(FriendlyByteBuf buffer) { + return new BigItemStack(buffer.readItem(), buffer.readVarInt()); + } + + public static Comparator comparator() { + return (i1, i2) -> Integer.compare(i2.count, i1.count); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) + return true; + if (obj instanceof BigItemStack other) + return Objects.equals(stack, other.stack) && count == other.count; + return false; + } + + @Override + public int hashCode() { + return (nullHash(stack) * 31) ^ Integer.hashCode(count); + } + + int nullHash(Object o) { + return o == null ? 0 : o.hashCode(); + } + + @Override + public String toString() { + return "(" + stack.getHoverName() + .getString() + " x" + count + ")"; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/FlapStuffs.java b/src/main/java/com/simibubi/create/content/logistics/FlapStuffs.java new file mode 100644 index 0000000000..dce0621803 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/FlapStuffs.java @@ -0,0 +1,127 @@ +package com.simibubi.create.content.logistics; + +import java.util.function.Consumer; + +import org.joml.Matrix4f; +import org.joml.Matrix4fc; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.instance.InstancerProvider; +import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.lib.instance.InstanceTypes; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.transform.TransformStack; +import dev.engine_room.flywheel.lib.transform.Translate; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; + +public class FlapStuffs { + public static final int FLAP_COUNT = 4; + public static final float X_OFFSET = 0.075f / 16f; + public static final float SEGMENT_STEP = -3.05f / 16f; + public static final Vec3 TUNNEL_PIVOT = VecHelper.voxelSpace(0, 10, 1f); + public static final Vec3 FUNNEL_PIVOT = VecHelper.voxelSpace(0, 10, 9.5f); + + public static void renderFlaps(PoseStack ms, VertexConsumer vb, SuperByteBuffer flapBuffer, Vec3 pivot, Direction funnelFacing, float flapness, float zOffset, int light) { + float horizontalAngle = AngleHelper.horizontalAngle(funnelFacing.getOpposite()); + + var msr = TransformStack.of(ms); + ms.pushPose(); + msr.center() + .rotateYDegrees(horizontalAngle) + .uncenter(); + ms.translate(X_OFFSET, 0, zOffset); + + for (int segment = 0; segment < FLAP_COUNT; segment++) { + ms.pushPose(); + + msr.translate(pivot) + .rotateXDegrees(flapAngle(flapness, segment)) + .translateBack(pivot); + + flapBuffer.light(light) + .renderInto(ms, vb); + + ms.popPose(); + ms.translate(SEGMENT_STEP, 0, 0); + } + ms.popPose(); + } + + public static float flapAngle(float flapness, int segment) { + float intensity = segment == 3 ? 1.5f : segment + 1; + float abs = Math.abs(flapness); + float flapAngle = Mth.sin((float) ((1 - abs) * Math.PI * intensity)) * 30 * flapness; + if (flapness < 0) + flapAngle *= .5f; + return flapAngle; + } + + public static Matrix4f commonTransform(BlockPos visualPosition, Direction side, float baseZOffset) { + float horizontalAngle = AngleHelper.horizontalAngle(side.getOpposite()); + + return new Matrix4f() + .translate(visualPosition.getX(), visualPosition.getY(), visualPosition.getZ()) + .translate(Translate.CENTER, Translate.CENTER, Translate.CENTER) + .rotateY(Mth.DEG_TO_RAD * horizontalAngle) + .translate(-Translate.CENTER, -Translate.CENTER, -Translate.CENTER) + .translate(X_OFFSET, 0, baseZOffset); + } + + public static class Visual { + private final TransformedInstance[] flaps; + + private final Matrix4f commonTransform = new Matrix4f(); + private final Vec3 pivot; + + public Visual(InstancerProvider instancerProvider, Matrix4fc commonTransform, Vec3 pivot, Model flapModel) { + this.pivot = pivot; + this.commonTransform.set(commonTransform) + .translate((float) pivot.x, (float) pivot.y, (float) pivot.z); + + flaps = new TransformedInstance[FLAP_COUNT]; + + instancerProvider.instancer(InstanceTypes.TRANSFORMED, flapModel) + .createInstances(flaps); + } + + public void update(float f) { + for (int segment = 0; segment < FLAP_COUNT; segment++) { + var flap = flaps[segment]; + + flap.setTransform(commonTransform) + .rotateXDegrees(flapAngle(f, segment)) + .translateBack(pivot) + .translate(segment * SEGMENT_STEP, 0, 0) + .setChanged(); + } + } + + public void delete() { + for (TransformedInstance flap : flaps) { + flap.delete(); + } + } + + public void updateLight(int light) { + for (TransformedInstance flap : flaps) { + flap.light(light) + .setChanged(); + } + } + + public void collectCrumblingInstances(Consumer consumer) { + for (TransformedInstance flap : flaps) { + consumer.accept(flap); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/box/PackageClientInteractionHandler.java b/src/main/java/com/simibubi/create/content/logistics/box/PackageClientInteractionHandler.java new file mode 100644 index 0000000000..8ed57dce67 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/box/PackageClientInteractionHandler.java @@ -0,0 +1,34 @@ +package com.simibubi.create.content.logistics.box; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.util.ObfuscationReflectionHelper; + +@EventBusSubscriber(value = Dist.CLIENT) +public class PackageClientInteractionHandler { + + // In vanilla, punching an entity doesnt reset the attack timer. This leads to + // accidentally breaking blocks behind an armorstand or package when punching it + // in creative mode + + @SubscribeEvent + @OnlyIn(Dist.CLIENT) + public static void onPlayerPunchPackage(AttackEntityEvent event) { + Player attacker = event.getEntity(); + if (!attacker.level() + .isClientSide()) + return; + Minecraft mc = Minecraft.getInstance(); + if (attacker != mc.player) + return; + if (!(event.getTarget() instanceof PackageEntity)) + return; + ObfuscationReflectionHelper.setPrivateValue(Minecraft.class, mc, 10, "f_91078_"); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/box/PackageDestroyPacket.java b/src/main/java/com/simibubi/create/content/logistics/box/PackageDestroyPacket.java new file mode 100644 index 0000000000..2842f0c019 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/box/PackageDestroyPacket.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.logistics.box; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.createmod.catnip.math.VecHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkEvent.Context; + +public class PackageDestroyPacket extends SimplePacketBase { + + protected Vec3 location; + private ItemStack box; + + public PackageDestroyPacket(FriendlyByteBuf buffer) { + location = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); + box = buffer.readItem(); + } + + public PackageDestroyPacket(Vec3 location, ItemStack box) { + this.location = location; + this.box = box.copy(); + this.box.setTag(null); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeDouble(location.x); + buffer.writeDouble(location.y); + buffer.writeDouble(location.z); + buffer.writeItem(box); + } + + @Override + public boolean handle(Context ctx) { + ctx.enqueueWork(() -> { + for (int i = 0; i < 20; i++) { + ClientLevel level = Minecraft.getInstance().level; + Vec3 motion = VecHelper.offsetRandomly(Vec3.ZERO, level.getRandom(), .125f); + Vec3 pos = location.add(motion.scale(4)); + level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, box), pos.x, pos.y, + pos.z, motion.x, motion.y, motion.z); + } + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/box/PackageEntity.java b/src/main/java/com/simibubi/create/content/logistics/box/PackageEntity.java new file mode 100644 index 0000000000..e4701772f5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/box/PackageEntity.java @@ -0,0 +1,480 @@ +package com.simibubi.create.content.logistics.box; + +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.logistics.chute.ChuteBlock; + +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.ponder.api.level.PonderLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.DamageTypeTags; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.entity.IEntityAdditionalSpawnData; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.network.NetworkHooks; +import net.minecraftforge.network.PacketDistributor; +import net.minecraftforge.network.PlayMessages.SpawnEntity; + +public class PackageEntity extends LivingEntity implements IEntityAdditionalSpawnData { + + private Entity originalEntity; + public ItemStack box; + + public int insertionDelay; + + public Vec3 clientPosition, vec2 = Vec3.ZERO, vec3 = Vec3.ZERO; + + public WeakReference tossedBy = new WeakReference<>(null); + + @SuppressWarnings("unchecked") + public PackageEntity(EntityType entityTypeIn, Level worldIn) { + super((EntityType) entityTypeIn, worldIn); + box = ItemStack.EMPTY; + setYRot(this.random.nextFloat() * 360.0F); + setYHeadRot(getYRot()); + yRotO = getYRot(); + insertionDelay = 30; + } + + public PackageEntity(Level worldIn, double x, double y, double z) { + this(AllEntityTypes.PACKAGE.get(), worldIn); + this.setPos(x, y, z); + this.refreshDimensions(); + } + + public static PackageEntity fromDroppedItem(Level world, Entity originalEntity, ItemStack itemstack) { + PackageEntity packageEntity = AllEntityTypes.PACKAGE.get() + .create(world); + + Vec3 position = originalEntity.position(); + packageEntity.setPos(position); + packageEntity.setBox(itemstack); + packageEntity.setDeltaMovement(originalEntity.getDeltaMovement() + .scale(1.5f)); + packageEntity.originalEntity = originalEntity; + + if (world != null && !world.isClientSide) + if (ChuteBlock.isChute(world.getBlockState(BlockPos.containing(position.x, position.y + .5f, position.z)))) + packageEntity.setYRot(((int) packageEntity.getYRot()) / 90 * 90); + + return packageEntity; + } + + public static PackageEntity fromItemStack(Level world, Vec3 position, ItemStack itemstack) { + PackageEntity packageEntity = AllEntityTypes.PACKAGE.get() + .create(world); + packageEntity.setPos(position); + packageEntity.setBox(itemstack); + return packageEntity; + } + + @Override + public ItemStack getPickedResult(HitResult target) { + return box.copy(); + } + + public static AttributeSupplier.Builder createPackageAttributes() { + return LivingEntity.createLivingAttributes() + .add(Attributes.MAX_HEALTH, 5f) + .add(Attributes.MOVEMENT_SPEED, 1f); + } + + public static EntityType.Builder build(EntityType.Builder builder) { + @SuppressWarnings("unchecked") + EntityType.Builder boxBuilder = (EntityType.Builder) builder; + return boxBuilder.setCustomClientFactory(PackageEntity::spawn) + .sized(1, 1); + } + + @Override + public void travel(Vec3 p_213352_1_) { + super.travel(p_213352_1_); + + if (!level().isClientSide) + return; + if (getDeltaMovement().length() < 1 / 128f) + return; + if (tickCount >= 20) + return; + + Vec3 motion = getDeltaMovement().scale(.75f); + AABB bb = getBoundingBox(); + List entityStream = level().getEntityCollisions(this, bb.expandTowards(motion)); + motion = collideBoundingBox(this, motion, bb, level(), entityStream); + + Vec3 clientPos = position().add(motion); + if (lerpSteps != 0) + clientPos = VecHelper.lerp(Math.min(1, tickCount / 20f), clientPos, new Vec3(lerpX, lerpY, lerpZ)); + if (tickCount < 5) + setPos(clientPos.x, clientPos.y, clientPos.z); + if (tickCount < 20) + lerpTo(clientPos.x, clientPos.y, clientPos.z, getYRot(), getXRot(), lerpSteps == 0 ? 3 : lerpSteps, true); + } + + @Override + public void lerpMotion(double x, double y, double z) { + setDeltaMovement(getDeltaMovement().add(x, y, z) + .scale(.5f)); + } + + public String getAddress() { + return box.getTag() + .getString("Address"); + } + + @Override + public void tick() { + if (firstTick) { + verifyInitialEntity(); + originalEntity = null; + } + + if (level() instanceof PonderLevel) { + setDeltaMovement(getDeltaMovement().add(0, -0.06, 0)); + if (position().y < 0.125) + discard(); + } + + insertionDelay = Math.min(insertionDelay + 1, 30); + super.tick(); + + if (!PackageItem.isPackage(box)) + discard(); + } + + /* + * Forge created package entities even when an ItemEntity is spawned as 'fake'. + * See: GiveCommand#giveItem. This method discards the package if it originated + * from such a fake item + */ + protected void verifyInitialEntity() { + if (!(originalEntity instanceof ItemEntity itemEntity)) + return; + CompoundTag nbt = new CompoundTag(); + itemEntity.addAdditionalSaveData(nbt); + if (nbt.getInt("PickupDelay") != 32767) // See: ItemEntity#makeFakeItem + return; + discard(); + } + + @Override + public EntityDimensions getDimensions(Pose pPose) { + if (box == null) + return super.getDimensions(pPose); + return new EntityDimensions(PackageItem.getWidth(box), PackageItem.getHeight(box), true); + } + + public static PackageEntity spawn(SpawnEntity spawnEntity, Level world) { + PackageEntity packageEntity = + new PackageEntity(world, spawnEntity.getPosX(), spawnEntity.getPosY(), spawnEntity.getPosZ()); + packageEntity.setDeltaMovement(spawnEntity.getVelX(), spawnEntity.getVelY(), spawnEntity.getVelZ()); + packageEntity.clientPosition = packageEntity.position(); + return packageEntity; + } + + public ItemStack getBox() { + return box; + } + + public static boolean centerPackage(Entity entity, Vec3 target) { + if (!(entity instanceof PackageEntity packageEntity)) + return true; + return packageEntity.decreaseInsertionTimer(target); + } + + public boolean decreaseInsertionTimer(@Nullable Vec3 targetSpot) { + if (targetSpot != null) { + setDeltaMovement(getDeltaMovement().scale(.75f) + .multiply(1, .25f, 1)); + Vec3 pos = position().add(targetSpot.subtract(position()) + .scale(.2f)); + setPos(pos.x, pos.y, pos.z); + float yawTarget = ((int) getYRot()) / 90 * 90; + setYRot(AngleHelper.angleLerp(.5f, getYRot(), yawTarget)); + } + insertionDelay = Math.max(insertionDelay - 3, 0); + return insertionDelay == 0; + } + + public void setBox(ItemStack box) { + this.box = box.copy(); + refreshDimensions(); + } + + @Override + public boolean isPushable() { + return true; + } + + @Override + public boolean canCollideWith(Entity pEntity) { + return pEntity instanceof PackageEntity && pEntity.getBoundingBox().maxY < getBoundingBox().minY + .125f; + } + + @Override + public boolean canBeCollidedWith() { + return false; + } + + @Override + public InteractionResult interact(Player pPlayer, InteractionHand pHand) { + if (!pPlayer.getItemInHand(pHand) + .isEmpty()) + return super.interact(pPlayer, pHand); + if (pPlayer.level().isClientSide) + return InteractionResult.SUCCESS; + pPlayer.setItemInHand(pHand, box); + level().playSound(null, blockPosition(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f, + .75f + level().random.nextFloat()); + remove(RemovalReason.DISCARDED); + return InteractionResult.SUCCESS; + } + + @Override + public void push(Entity entityIn) { + boolean isOtherPackage = entityIn instanceof PackageEntity; + + if (!isOtherPackage && tossedBy.get() != null) + tossedBy = new WeakReference<>(null); // no nudging + + if (isOtherPackage) { + if (entityIn.getBoundingBox().minY < this.getBoundingBox().maxY) + super.push(entityIn); + } else if (entityIn.getBoundingBox().minY <= this.getBoundingBox().minY) { + super.push(entityIn); + } + } + + @Override + public double getPassengersRidingOffset() { + return this.getDimensions(getPose()).height; + } + + @Override + protected void onInsideBlock(BlockState state) { + super.onInsideBlock(state); + if (!isAlive()) + return; + if (state.getBlock() == Blocks.WATER) { + destroy(damageSources().drown()); + remove(RemovalReason.KILLED); + } + } + + @Override + public boolean hurt(DamageSource source, float amount) { + if (!ForgeHooks.onLivingAttack(this, source, amount)) + return false; + + if (level().isClientSide || !this.isAlive()) + return false; + + if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + this.remove(RemovalReason.KILLED); + return false; + } + + if (source.equals(damageSources().inWall()) && (isPassenger() || insertionDelay < 20)) + return false; + + if (source.is(DamageTypeTags.IS_FALL)) + return false; + + if (this.isInvulnerableTo(source)) + return false; + + if (source.is(DamageTypeTags.IS_EXPLOSION)) { + this.destroy(source); + this.remove(RemovalReason.KILLED); + return false; + } + + if (source.is(DamageTypeTags.IS_FIRE)) { + if (this.isOnFire()) { + this.takeDamage(source, 0.15F); + } else { + this.setSecondsOnFire(5); + } + return false; + } + + boolean wasShot = source.getDirectEntity() instanceof AbstractArrow; + boolean shotCanPierce = wasShot && ((AbstractArrow) source.getDirectEntity()).getPierceLevel() > 0; + + if (source.getEntity() instanceof Player && !((Player) source.getEntity()).getAbilities().mayBuild) + return false; + + this.destroy(source); + this.remove(RemovalReason.KILLED); + return shotCanPierce; + } + + private void takeDamage(DamageSource source, float amount) { + float hp = this.getHealth(); + hp = hp - amount; + if (hp <= 0.5F) { + this.destroy(source); + this.remove(RemovalReason.KILLED); + } else { + this.setHealth(hp); + } + } + + private void destroy(DamageSource source) { + AllPackets.getChannel() + .send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + new PackageDestroyPacket(getBoundingBox().getCenter(), box)); + AllSoundEvents.PACKAGE_POP.playOnServer(level(), blockPosition()); + this.dropAllDeathLoot(source); + } + + @Override + protected void dropAllDeathLoot(DamageSource pDamageSource) { + super.dropAllDeathLoot(pDamageSource); + ItemStackHandler contents = PackageItem.getContents(box); + for (int i = 0; i < contents.getSlots(); i++) { + ItemStack itemstack = contents.getStackInSlot(i); + + if (itemstack.getItem() instanceof SpawnEggItem sei && level() instanceof ServerLevel sl) { + EntityType entitytype = sei.getType(itemstack.getTag()); + Entity entity = + entitytype.spawn(sl, itemstack, null, blockPosition(), MobSpawnType.SPAWN_EGG, false, false); + if (entity != null) + itemstack.shrink(1); + } + + if (itemstack.isEmpty()) + continue; + ItemEntity entityIn = new ItemEntity(level(), getX(), getY(), getZ(), itemstack); + level().addFreshEntity(entityIn); + } + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + box = ItemStack.of(compound.getCompound("Box")); + refreshDimensions(); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); + compound.put("Box", box.serializeNBT()); + } + + @Override + public Packet getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public Iterable getArmorSlots() { + return Collections.emptyList(); + } + + @Override + public ItemStack getItemBySlot(EquipmentSlot pSlot) { + if (pSlot == EquipmentSlot.MAINHAND) + return getBox(); + return ItemStack.EMPTY; + } + + @Override + public void setItemSlot(EquipmentSlot pSlot, ItemStack pStack) { + if (pSlot == EquipmentSlot.MAINHAND) + setBox(pStack); + } + + @Override + public HumanoidArm getMainArm() { + return HumanoidArm.RIGHT; + } + + @Override + public InteractionHand getUsedItemHand() { + return InteractionHand.MAIN_HAND; + } + + @Override + public void writeSpawnData(FriendlyByteBuf buffer) { + buffer.writeItem(getBox()); + Vec3 motion = getDeltaMovement(); + buffer.writeFloat((float) motion.x); + buffer.writeFloat((float) motion.y); + buffer.writeFloat((float) motion.z); + } + + @Override + public void readSpawnData(FriendlyByteBuf additionalData) { + setBox(additionalData.readItem()); + setDeltaMovement(additionalData.readFloat(), additionalData.readFloat(), additionalData.readFloat()); + } + + @Override + public float getVoicePitch() { + return 1.5f; + } + + @Override + public Fallsounds getFallSounds() { + return new LivingEntity.Fallsounds(SoundEvents.CHISELED_BOOKSHELF_FALL, SoundEvents.CHISELED_BOOKSHELF_FALL); + } + + @Nullable + protected SoundEvent getHurtSound(DamageSource damageSourceIn) { + return null; + } + + @Nullable + protected SoundEvent getDeathSound() { + return null; + } + + @Override + public boolean isAffectedByPotions() { + return false; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/box/PackageItem.java b/src/main/java/com/simibubi/create/content/logistics/box/PackageItem.java new file mode 100644 index 0000000000..1757f1003e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/box/PackageItem.java @@ -0,0 +1,396 @@ +package com.simibubi.create.content.logistics.box; + +import java.lang.ref.WeakReference; +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.box.PackageStyles.PackageStyle; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; + +import net.createmod.catnip.data.Glob; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.UseAnim; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +public class PackageItem extends Item { + + public static final int SLOTS = 9; + + public PackageStyle style; + + public PackageItem(Properties properties, PackageStyle style) { + super(properties); + this.style = style; + PackageStyles.ALL_BOXES.add(this); + (style.rare() ? PackageStyles.RARE_BOXES : PackageStyles.STANDARD_BOXES).add(this); + } + + @Override + public String getDescriptionId() { + return "item." + Create.ID + (style.rare() ? ".rare_package" : ".package"); + } + + public static boolean isPackage(ItemStack stack) { + return stack.getItem() instanceof PackageItem; + } + + @Override + public boolean canFitInsideContainerItems() { + return false; + } + + @Override + public boolean hasCustomEntity(ItemStack stack) { + return true; + } + + @Override + public Entity createEntity(Level world, Entity location, ItemStack itemstack) { + return PackageEntity.fromDroppedItem(world, location, itemstack); + } + + public static ItemStack containing(List stacks) { + ItemStackHandler newInv = new ItemStackHandler(9); + stacks.forEach(s -> ItemHandlerHelper.insertItemStacked(newInv, s, false)); + return containing(newInv); + } + + public static ItemStack containing(ItemStackHandler stacks) { + ItemStack box = PackageStyles.getRandomBox(); + CompoundTag compound = new CompoundTag(); + compound.put("Items", stacks.serializeNBT()); + box.setTag(compound); + return box; + } + + public static void clearAddress(ItemStack box) { + if (box.hasTag()) + box.getTag() + .remove("Address"); + } + + public static void addAddress(ItemStack box, String address) { + box.getOrCreateTag() + .putString("Address", address); + } + + public static void setOrder(ItemStack box, int orderId, int linkIndex, boolean isFinalLink, int fragmentIndex, + boolean isFinal, @Nullable PackageOrder orderContext) { + CompoundTag tag = new CompoundTag(); + tag.putInt("OrderId", orderId); + tag.putInt("LinkIndex", linkIndex); + tag.putBoolean("IsFinalLink", isFinalLink); + tag.putInt("Index", fragmentIndex); + tag.putBoolean("IsFinal", isFinal); + if (orderContext != null) + tag.put("OrderContext", orderContext.write()); + box.getOrCreateTag() + .put("Fragment", tag); + } + + public static int getOrderId(ItemStack box) { + CompoundTag tag = box.getTag(); + if (tag == null || !tag.contains("Fragment")) + return -1; + return tag.getCompound("Fragment") + .getInt("OrderId"); + } + + public static PackageOrder getOrderContext(ItemStack box) { + CompoundTag tag = box.getTag(); + if (tag == null || !tag.contains("Fragment")) + return null; + CompoundTag frag = tag.getCompound("Fragment"); + if (!frag.contains("OrderContext")) + return null; + return PackageOrder.read(frag.getCompound("OrderContext")); + } + + public static void addOrderContext(ItemStack box, PackageOrder orderContext) { + CompoundTag tag = box.getOrCreateTagElement("Fragment"); + if (orderContext != null) + tag.put("OrderContext", orderContext.write()); + box.getOrCreateTag() + .put("Fragment", tag); + } + + public static boolean matchAddress(ItemStack box, String address) { + return matchAddress(getAddress(box), address); + } + + public static boolean matchAddress(String boxAddress, String address) { + if (address.isBlank()) + return boxAddress.isBlank(); + if (address.equals("*") || boxAddress.equals("*")) + return true; + String matcher = Glob.toRegexPattern(address, ""); + String boxMatcher = Glob.toRegexPattern(boxAddress, ""); + return address.matches(boxMatcher) || boxAddress.matches(matcher); + } + + public static String getAddress(ItemStack box) { + String boxAddress = !box.hasTag() ? "" + : box.getTag() + .getString("Address"); + return boxAddress; + } + + public static float getWidth(ItemStack box) { + if (box.getItem() instanceof PackageItem pi) + return pi.style.width() / 16f; + return 1; + } + + public static float getHeight(ItemStack box) { + if (box.getItem() instanceof PackageItem pi) + return pi.style.height() / 16f; + return 1; + } + + public static float getHookDistance(ItemStack box) { + if (box.getItem() instanceof PackageItem pi) + return pi.style.riggingOffset() / 16f; + return 1; + } + + public static ItemStackHandler getContents(ItemStack box) { + ItemStackHandler newInv = new ItemStackHandler(9); + CompoundTag invNBT = box.getOrCreateTagElement("Items"); + if (!invNBT.isEmpty()) + newInv.deserializeNBT(invNBT); + return newInv; + } + + @Override + public void appendHoverText(ItemStack pStack, Level pLevel, List pTooltipComponents, + TooltipFlag pIsAdvanced) { + super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced); + CompoundTag compoundnbt = pStack.getOrCreateTag(); + + if (compoundnbt.contains("Address", Tag.TAG_STRING) && !compoundnbt.getString("Address") + .isBlank()) { + pTooltipComponents.add(Component.literal("\u2192 " + compoundnbt.getString("Address")) + .withStyle(ChatFormatting.GOLD)); + } + + /* + * Debug Fragmentation Data if (compoundnbt.contains("Fragment")) { CompoundTag + * fragTag = compoundnbt.getCompound("Fragment"); + * pTooltipComponents.add(Component.literal("Order Information (Temporary)") + * .withStyle(ChatFormatting.GREEN)); pTooltipComponents.add(Components + * .literal(" Link " + fragTag.getInt("LinkIndex") + + * (fragTag.getBoolean("IsFinalLink") ? " Final" : "") + " | Fragment " + + * fragTag.getInt("Index") + (fragTag.getBoolean("IsFinal") ? " Final" : "")) + * .withStyle(ChatFormatting.DARK_GREEN)); if (fragTag.contains("OrderContext")) + * pTooltipComponents.add(Component.literal("Has Context!") + * .withStyle(ChatFormatting.DARK_GREEN)); } + */ + + if (!compoundnbt.contains("Items", Tag.TAG_COMPOUND)) + return; + + int visibleNames = 0; + int skippedNames = 0; + ItemStackHandler contents = getContents(pStack); + for (int i = 0; i < contents.getSlots(); i++) { + ItemStack itemstack = contents.getStackInSlot(i); + if (itemstack.isEmpty()) + continue; + if (itemstack.getItem() instanceof SpawnEggItem) + continue; + if (visibleNames > 2) { + skippedNames++; + continue; + } + + visibleNames++; + pTooltipComponents.add(itemstack.getHoverName() + .copy() + .append(" x") + .append(String.valueOf(itemstack.getCount())) + .withStyle(ChatFormatting.GRAY)); + } + + if (skippedNames > 0) + pTooltipComponents.add(Component.translatable("container.shulkerBox.more", skippedNames) + .withStyle(ChatFormatting.ITALIC)); + } + + // Throwing stuff + + @Override + public int getUseDuration(ItemStack p_77626_1_) { + return 72000; + } + + @Override + public UseAnim getUseAnimation(ItemStack pStack) { + return UseAnim.BOW; + } + + public InteractionResultHolder open(Level worldIn, Player playerIn, InteractionHand handIn) { + ItemStack box = playerIn.getItemInHand(handIn); + ItemStackHandler contents = getContents(box); + ItemStack particle = box.copy(); + + playerIn.setItemInHand(handIn, box.getCount() <= 1 ? ItemStack.EMPTY : box.copyWithCount(box.getCount() - 1)); + + if (!worldIn.isClientSide()) { + for (int i = 0; i < contents.getSlots(); i++) { + ItemStack itemstack = contents.getStackInSlot(i); + if (itemstack.isEmpty()) + continue; + + if (itemstack.getItem() instanceof SpawnEggItem sei && worldIn instanceof ServerLevel sl) { + EntityType entitytype = sei.getType(itemstack.getTag()); + Entity entity = entitytype.spawn(sl, itemstack, null, BlockPos.containing(playerIn.position() + .add(playerIn.getLookAngle() + .multiply(1, 0, 1) + .normalize())), + MobSpawnType.SPAWN_EGG, false, false); + if (entity != null) + itemstack.shrink(1); + } + + playerIn.getInventory() + .placeItemBackInInventory(itemstack.copy()); + } + } + + Vec3 position = playerIn.position(); + AllSoundEvents.PACKAGE_POP.playOnServer(worldIn, playerIn.blockPosition()); + + if (worldIn.isClientSide()) { + for (int i = 0; i < 10; i++) { + Vec3 motion = VecHelper.offsetRandomly(Vec3.ZERO, worldIn.getRandom(), .125f); + Vec3 pos = position.add(0, 0.5, 0) + .add(playerIn.getLookAngle() + .scale(.5)) + .add(motion.scale(4)); + worldIn.addParticle(new ItemParticleOption(ParticleTypes.ITEM, particle), pos.x, pos.y, pos.z, motion.x, + motion.y, motion.z); + } + } + + return new InteractionResultHolder<>(InteractionResult.SUCCESS, box); + } + + @Override + public InteractionResult useOn(UseOnContext context) { + if (context.getPlayer() + .isShiftKeyDown()) { + return open(context.getLevel(), context.getPlayer(), context.getHand()).getResult(); + } + + Vec3 point = context.getClickLocation(); + float h = style.height() / 16f; + float r = style.width() / 2f / 16f; + + if (context.getClickedFace() == Direction.DOWN) + point = point.subtract(0, h + .25f, 0); + else if (context.getClickedFace() + .getAxis() + .isHorizontal()) + point = point.add(Vec3.atLowerCornerOf(context.getClickedFace() + .getNormal()) + .scale(r)); + + AABB scanBB = new AABB(point, point).inflate(r, 0, r) + .expandTowards(0, h, 0); + Level world = context.getLevel(); + if (!world.getEntities(AllEntityTypes.PACKAGE.get(), scanBB, e -> true) + .isEmpty()) + return super.useOn(context); + + PackageEntity packageEntity = new PackageEntity(world, point.x, point.y, point.z); + ItemStack itemInHand = context.getItemInHand(); + packageEntity.setBox(itemInHand.copy()); + world.addFreshEntity(packageEntity); + itemInHand.shrink(1); + return InteractionResult.SUCCESS; + } + + @Override + public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + if (player.isShiftKeyDown()) + return open(world, player, hand); + ItemStack itemstack = player.getItemInHand(hand); + player.startUsingItem(hand); + return InteractionResultHolder.success(itemstack); + } + + @Override + public void releaseUsing(ItemStack stack, Level world, LivingEntity entity, int ticks) { + if (!(entity instanceof Player player)) + return; + int i = this.getUseDuration(stack) - ticks; + if (i < 0) + return; + + float f = getPackageVelocity(i); + if (f < 0.1D) + return; + if (world.isClientSide) + return; + + world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.SNOWBALL_THROW, + SoundSource.NEUTRAL, 0.5F, 0.5F); + + ItemStack copy = stack.copy(); + if (!player.getAbilities().instabuild) + stack.shrink(1); + + Vec3 vec = new Vec3(entity.getX(), entity.getY() + entity.getBoundingBox() + .getYsize() / 2f, entity.getZ()); + Vec3 motion = entity.getLookAngle() + .scale(f * 2); + vec = vec.add(motion); + + PackageEntity packageEntity = new PackageEntity(world, vec.x, vec.y, vec.z); + packageEntity.setBox(copy); + packageEntity.setDeltaMovement(motion); + packageEntity.tossedBy = new WeakReference<>(player); + world.addFreshEntity(packageEntity); + } + + public static float getPackageVelocity(int p_185059_0_) { + float f = (float) p_185059_0_ / 20.0F; + f = (f * f + f * 2.0F) / 3.0F; + if (f > 1.0F) + f = 1.0F; + return f; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/box/PackageRenderer.java b/src/main/java/com/simibubi/create/content/logistics/box/PackageRenderer.java new file mode 100644 index 0000000000..e2d7410131 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/box/PackageRenderer.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.logistics.box; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; + +import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraftforge.registries.ForgeRegistries; + +public class PackageRenderer extends EntityRenderer { + + public PackageRenderer(Context pContext) { + super(pContext); + shadowRadius = 0.5f; + } + + @Override + public void render(PackageEntity entity, float yaw, float pt, PoseStack ms, MultiBufferSource buffer, int light) { + if (!VisualizationManager.supportsVisualization(entity.level())) { + ItemStack box = entity.box; + if (box.isEmpty() || !PackageItem.isPackage(box)) box = AllBlocks.CARDBOARD_BLOCK.asStack(); + PartialModel model = AllPartialModels.PACKAGES.get(ForgeRegistries.ITEMS.getKey(box.getItem())); + renderBox(entity, yaw, ms, buffer, light, model); + } + super.render(entity, yaw, pt, ms, buffer, light); + } + + public static void renderBox(Entity entity, float yaw, PoseStack ms, MultiBufferSource buffer, int light, + PartialModel model) { + if (model == null) + return; + SuperByteBuffer sbb = CachedBuffers.partial(model, Blocks.AIR.defaultBlockState()); + sbb.translate(-.5, 0, -.5) + .rotateCentered(-AngleHelper.rad(yaw + 90), Direction.UP) + .light(light) + .nudge(entity.getId()); + sbb.renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + + @Override + public ResourceLocation getTextureLocation(PackageEntity pEntity) { + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/box/PackageStyles.java b/src/main/java/com/simibubi/create/content/logistics/box/PackageStyles.java new file mode 100644 index 0000000000..9493390d06 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/box/PackageStyles.java @@ -0,0 +1,74 @@ +package com.simibubi.create.content.logistics.box; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.jetbrains.annotations.ApiStatus.Internal; +import org.jetbrains.annotations.Unmodifiable; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.Create; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +public class PackageStyles { + public record PackageStyle(String type, int width, int height, float riggingOffset, boolean rare) { + public ResourceLocation getItemId() { + String size = "_" + width + "x" + height; + String id = type + "_package" + (rare ? "" : size); + return Create.asResource(id); + } + + public ResourceLocation getRiggingModel() { + String size = width + "x" + height; + return Create.asResource("item/package/rigging_" + size); + } + }; + + /** + * This is used for registration, if you insert into this list, you will be registering items under Create's namespace. + * Instead, you should handle registration yourself + * and use the PackageItem class so your packages end up in the correct lists. + */ + @Internal + @Unmodifiable + public static final List STYLES = ImmutableList.of( + new PackageStyle("cardboard", 12, 12, 23f, false), + new PackageStyle("cardboard", 10, 12, 22f, false), + new PackageStyle("cardboard", 10, 8, 18f, false), + new PackageStyle("cardboard", 12, 10, 21f, false), + + rare("creeper"), + rare("darcy"), + rare("evan"), + rare("jinx"), + rare("kryppers"), + rare("simi"), + rare("starlotte"), + rare("thunder"), + rare("up"), + rare("vector") + ); + + public static final List ALL_BOXES = new ArrayList<>(); + public static final List STANDARD_BOXES = new ArrayList<>(); + public static final List RARE_BOXES = new ArrayList<>(); + + private static final Random STYLE_PICKER = new Random(); + private static final int RARE_CHANCE = 7500; // addons, have mercy + + public static ItemStack getRandomBox() { + List pool = STYLE_PICKER.nextInt(RARE_CHANCE) == 0 ? RARE_BOXES : STANDARD_BOXES; + return new ItemStack(pool.get(STYLE_PICKER.nextInt(pool.size()))); + } + + public static ItemStack getDefaultBox() { + return new ItemStack(ALL_BOXES.get(0)); + } + + private static PackageStyle rare(String name) { + return new PackageStyle("rare_" + name, 12, 10, 21f, true); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/box/PackageVisual.java b/src/main/java/com/simibubi/create/content/logistics/box/PackageVisual.java new file mode 100644 index 0000000000..7401735952 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/box/PackageVisual.java @@ -0,0 +1,67 @@ +package com.simibubi.create.content.logistics.box; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; + +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.instance.InstanceTypes; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.model.Models; +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import dev.engine_room.flywheel.lib.visual.AbstractEntityVisual; +import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.registries.ForgeRegistries; + +public class PackageVisual extends AbstractEntityVisual implements SimpleDynamicVisual { + public final TransformedInstance instance; + + public PackageVisual(VisualizationContext ctx, PackageEntity entity, float partialTick) { + super(ctx, entity, partialTick); + + ItemStack box = entity.box; + if (box.isEmpty() || !PackageItem.isPackage(box)) + box = AllBlocks.CARDBOARD_BLOCK.asStack(); + PartialModel model = AllPartialModels.PACKAGES.get(ForgeRegistries.ITEMS.getKey(box.getItem())); + + instance = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(model)) + .createInstance(); + + animate(partialTick); + } + + @Override + public void beginFrame(Context ctx) { + animate(ctx.partialTick()); + } + + private void animate(float partialTick) { + float yaw = Mth.lerp(partialTick, entity.yRotO, entity.getYRot()); + + Vec3 pos = PackageVisual.this.entity.position(); + var renderOrigin = renderOrigin(); + var x = (float) (Mth.lerp(partialTick, this.entity.xo, pos.x) - renderOrigin.getX()); + var y = (float) (Mth.lerp(partialTick, this.entity.yo, pos.y) - renderOrigin.getY()); + var z = (float) (Mth.lerp(partialTick, this.entity.zo, pos.z) - renderOrigin.getZ()); + + long randomBits = (long) entity.getId() * 31L * 493286711L; + randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L; + float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + + instance.setIdentityTransform() + .translate(x - 0.5 + xNudge, y + yNudge, z - 0.5 + zNudge) + .rotateYCenteredDegrees(-yaw - 90) + .light(computePackedLight(partialTick)) + .setChanged(); + } + + @Override + protected void _delete() { + instance.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/AbstractChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/chute/AbstractChuteBlock.java index aff986cb88..1b24b0d0b7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/chute/AbstractChuteBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/AbstractChuteBlock.java @@ -6,12 +6,15 @@ import javax.annotation.Nullable; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.logistics.box.PackageEntity; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.item.ItemHelper; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -29,6 +32,7 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.api.distmarker.Dist; @@ -85,30 +89,33 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I @Override public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { super.updateEntityAfterFallOn(worldIn, entityIn); - if (!(entityIn instanceof ItemEntity)) + ItemStack stack = ItemHelper.fromItemEntity(entityIn); + if (stack.isEmpty()) return; if (entityIn.level().isClientSide) return; if (!entityIn.isAlive()) return; - DirectBeltInputBehaviour input = BlockEntityBehaviour.get(entityIn.level(), - BlockPos.containing(entityIn.position() - .add(0, 0.5f, 0)) - .below(), - DirectBeltInputBehaviour.TYPE); + BlockPos pos = BlockPos.containing(entityIn.position() + .add(0, 0.5f, 0)) + .below(); + DirectBeltInputBehaviour input = BlockEntityBehaviour.get(entityIn.level(), pos, DirectBeltInputBehaviour.TYPE); if (input == null) return; if (!input.canInsertFromSide(Direction.UP)) return; - - ItemEntity itemEntity = (ItemEntity) entityIn; - ItemStack toInsert = itemEntity.getItem(); - ItemStack remainder = input.handleInsertion(toInsert, Direction.UP, false); - - if (remainder.isEmpty()) - itemEntity.discard(); - if (remainder.getCount() < toInsert.getCount()) - itemEntity.setItem(remainder); + if (!PackageEntity.centerPackage(entityIn, Vec3.atBottomCenterOf(pos.above()))) + return; + ItemStack remainder = input.handleInsertion(stack, Direction.UP, false); + if (remainder.isEmpty()) { + entityIn.discard(); + if (entityIn instanceof PackageEntity box) { + Player player = box.tossedBy.get(); + if (player != null) + AllAdvancements.PACKAGE_CHUTE_THROW.awardTo(player); + } + } else if (remainder.getCount() < stack.getCount() && entityIn instanceof ItemEntity) + ((ItemEntity) entityIn).setItem(remainder); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlock.java index 09cb3490be..f7d6c9f080 100644 --- a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlock.java @@ -7,9 +7,9 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.logistics.funnel.FunnelBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.sounds.SoundEvents; @@ -73,7 +73,7 @@ public class ChuteBlock extends AbstractChuteBlock implements ProperWaterloggedB public boolean isTransparent(BlockState state) { return state.getValue(SHAPE) == Shape.WINDOW; } - + @Override public FluidState getFluidState(BlockState pState) { return fluidState(pState); @@ -128,7 +128,7 @@ public class ChuteBlock extends AbstractChuteBlock implements ProperWaterloggedB } return state; } - + @Override public BlockState updateShape(BlockState state, Direction direction, BlockState above, LevelAccessor world, BlockPos pos, BlockPos p_196271_6_) { diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlockEntity.java index b59d511cb7..ec02d51911 100644 --- a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlockEntity.java @@ -9,7 +9,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; @@ -25,13 +25,12 @@ import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.particle.AirParticleData; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.ChatFormatting; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -50,6 +49,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; @@ -83,7 +83,7 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf int entitySearchCooldown; VersionedInventoryTrackerBehaviour invVersionTracker; - + LazyOptional capAbove; LazyOptional capBelow; @@ -632,8 +632,7 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf if (AllBlocks.ENCASED_FAN.has(blockStateAbove) && blockStateAbove.getValue(EncasedFanBlock.FACING) == Direction.DOWN) { BlockEntity be = level.getBlockEntity(worldPosition.above()); - if (be instanceof EncasedFanBlockEntity && !be.isRemoved()) { - EncasedFanBlockEntity fan = (EncasedFanBlockEntity) be; + if (be instanceof EncasedFanBlockEntity fan && !be.isRemoved()) { return fan.getSpeed(); } } @@ -655,8 +654,7 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf if (AllBlocks.ENCASED_FAN.has(blockStateBelow) && blockStateBelow.getValue(EncasedFanBlock.FACING) == Direction.UP) { BlockEntity be = level.getBlockEntity(worldPosition.below()); - if (be instanceof EncasedFanBlockEntity && !be.isRemoved()) { - EncasedFanBlockEntity fan = (EncasedFanBlockEntity) be; + if (be instanceof EncasedFanBlockEntity fan && !be.isRemoved()) { return fan.getSpeed(); } } @@ -719,29 +717,29 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { boolean downward = getItemMotion() < 0; - Lang.translate("tooltip.chute.header") + CreateLang.translate("tooltip.chute.header") .forGoggles(tooltip); if (pull == 0 && push == 0) - Lang.translate("tooltip.chute.no_fans_attached") + CreateLang.translate("tooltip.chute.no_fans_attached") .style(ChatFormatting.GRAY) .forGoggles(tooltip); if (pull != 0) - Lang.translate("tooltip.chute.fans_" + (pull > 0 ? "pull_up" : "push_down")) + CreateLang.translate("tooltip.chute.fans_" + (pull > 0 ? "pull_up" : "push_down")) .style(ChatFormatting.GRAY) .forGoggles(tooltip); if (push != 0) - Lang.translate("tooltip.chute.fans_" + (push > 0 ? "push_up" : "pull_down")) + CreateLang.translate("tooltip.chute.fans_" + (push > 0 ? "push_up" : "pull_down")) .style(ChatFormatting.GRAY) .forGoggles(tooltip); - Lang.text("-> ") - .add(Lang.translate("tooltip.chute.items_move_" + (downward ? "down" : "up"))) + CreateLang.text("-> ") + .add(CreateLang.translate("tooltip.chute.items_move_" + (downward ? "down" : "up"))) .style(ChatFormatting.YELLOW) .forGoggles(tooltip); if (!item.isEmpty()) - Lang.translate("tooltip.chute.contains", Components.translatable(item.getDescriptionId()) - .getString(), item.getCount()) + CreateLang.translate("tooltip.chute.contains", Component.translatable(item.getDescriptionId()) + .getString(), item.getCount()) .style(ChatFormatting.GREEN) .forGoggles(tooltip); diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItem.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItem.java index 9e3aa1b1e4..5eb7ded5c4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItem.java @@ -38,9 +38,8 @@ public class ChuteItem extends BlockItem { if (blockState.canBeReplaced()) context = BlockPlaceContext.at(context, correctPos, face); else { - if (!(blockState.getBlock() instanceof ChuteBlock) || world.isClientSide) + if (!(blockState.getBlock() instanceof ChuteBlock block) || world.isClientSide) return InteractionResult.FAIL; - AbstractChuteBlock block = (AbstractChuteBlock) blockState.getBlock(); if (block.getFacing(blockState) == Direction.DOWN) { world.setBlockAndUpdate(correctPos, ProperWaterloggedBlock.withWater(world, diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteRenderer.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteRenderer.java index 3b3f2c219e..aa5c950899 100644 --- a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteRenderer.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.logistics.chute; import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.logistics.box.PackageItem; import com.simibubi.create.content.logistics.chute.ChuteBlock.Shape; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; @@ -42,9 +43,13 @@ public class ChuteRenderer extends SafeBlockEntityRenderer { float itemScale = .5f; float itemPosition = be.itemPosition.getValue(partialTicks); ms.translate(0, -.5 + itemPosition, 0); - ms.scale(itemScale, itemScale, itemScale); - msr.rotateXDegrees(itemPosition * 180); - msr.rotateYDegrees(itemPosition * 180); + if (PackageItem.isPackage(be.item)) { + ms.scale(1.5f, 1.5f, 1.5f); + } else { + ms.scale(itemScale, itemScale, itemScale); + msr.rotateXDegrees(itemPosition * 180); + msr.rotateYDegrees(itemPosition * 180); + } itemRenderer.renderStatic(be.item, ItemDisplayContext.FIXED, light, overlay, ms, buffer, be.getLevel(), 0); ms.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlock.java index 5575d68837..8b64939394 100644 --- a/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlock.java @@ -26,14 +26,14 @@ public class SmartChuteBlock extends AbstractChuteBlock { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { - super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving); - if (worldIn.isClientSide) + super.neighborChanged(state, level, pos, block, fromPos, isMoving); + if (level.isClientSide) return; - if (!worldIn.getBlockTicks() + if (!level.getBlockTicks() .willTickThisTick(pos, this)) - worldIn.scheduleTick(pos, this, 0); + level.scheduleTick(pos, this, 1); } @Override @@ -53,7 +53,7 @@ public class SmartChuteBlock extends AbstractChuteBlock { public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { return true; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.SMART_CHUTE.get(); diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteFilterSlotPositioning.java b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteFilterSlotPositioning.java index cbc53fb03f..d63776b695 100644 --- a/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteFilterSlotPositioning.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteFilterSlotPositioning.java @@ -1,18 +1,20 @@ package com.simibubi.create.content.logistics.chute; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; public class SmartChuteFilterSlotPositioning extends ValueBoxTransform.Sided { @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Direction side = getSide(); float horizontalAngle = AngleHelper.horizontalAngle(side); Vec3 southLocation = VecHelper.voxelSpace(8, 11, 15.5f); diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlockEntity.java index d2327aae1e..10a9cd39de 100644 --- a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlockEntity.java @@ -6,11 +6,12 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.transform.TransformStack; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -34,7 +35,7 @@ public class CreativeCrateBlockEntity extends CrateBlockEntity { @Override public void addBehaviours(List behaviours) { behaviours.add(filtering = createFilter()); - filtering.setLabel(Lang.translateDirect("logistics.creative_crate.supply")); + filtering.setLabel(CreateLang.translateDirect("logistics.creative_crate.supply")); } @Override @@ -55,13 +56,13 @@ public class CreativeCrateBlockEntity extends CrateBlockEntity { return new FilteringBehaviour(this, new ValueBoxTransform() { @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { TransformStack.of(ms) .rotateXDegrees(90); } @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { return new Vec3(0.5, 13.5 / 16d, 0.5); } diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorage.java b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorage.java new file mode 100644 index 0000000000..785928cb0c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorage.java @@ -0,0 +1,82 @@ +package com.simibubi.create.content.logistics.crate; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +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; + +public class CreativeCrateMountedStorage extends MountedItemStorage { + public static final Codec CODEC = ItemStack.CODEC.xmap( + CreativeCrateMountedStorage::new, storage -> storage.suppliedStack + ); + + private final ItemStack suppliedStack; + private final ItemStack cachedStackInSlot; + + protected CreativeCrateMountedStorage(MountedItemStorageType type, ItemStack suppliedStack) { + super(type); + this.suppliedStack = suppliedStack; + this.cachedStackInSlot = suppliedStack.copyWithCount(suppliedStack.getMaxStackSize()); + } + + public CreativeCrateMountedStorage(ItemStack suppliedStack) { + this(AllMountedStorageTypes.CREATIVE_CRATE.get(), suppliedStack); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + // no need to do anything here, the supplied item can't change while mounted + } + + @Override + public int getSlots() { + return 2; // 0 holds the supplied stack endlessly, 1 is always empty to accept + } + + @Override + @NotNull + public ItemStack getStackInSlot(int slot) { + return slot == 0 ? this.cachedStackInSlot : ItemStack.EMPTY; + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + } + + @Override + @NotNull + public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return ItemStack.EMPTY; // no remainder, accept any input + } + + @Override + @NotNull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (slot == 0 && !this.suppliedStack.isEmpty()) { + int count = Math.min(amount, this.suppliedStack.getMaxStackSize()); + return this.suppliedStack.copyWithCount(count); + } + + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorageType.java b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorageType.java new file mode 100644 index 0000000000..86b261e1c9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorageType.java @@ -0,0 +1,28 @@ +package com.simibubi.create.content.logistics.crate; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +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; + +public class CreativeCrateMountedStorageType extends MountedItemStorageType { + public CreativeCrateMountedStorageType() { + super(CreativeCrateMountedStorage.CODEC); + } + + @Override + @Nullable + public CreativeCrateMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof CreativeCrateBlockEntity crate) { + ItemStack supplied = crate.filtering.getFilter(); + return new CreativeCrateMountedStorage(supplied); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/DepotBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBehaviour.java index 55493a0a9c..21a7f1ce5e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/DepotBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBehaviour.java @@ -21,9 +21,9 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -59,7 +59,7 @@ public class DepotBehaviour extends BlockEntityBehaviour { public DepotBehaviour(SmartBlockEntity be) { super(be); - maxStackSize = () -> 64; + maxStackSize = () -> heldItem != null ? heldItem.stack.getMaxStackSize() : 64; canAcceptItems = () -> true; canFunnelsPullFrom = $ -> true; acceptedItems = $ -> true; @@ -78,12 +78,12 @@ public class DepotBehaviour extends BlockEntityBehaviour { public void enableMerging() { allowMerge = true; } - + public DepotBehaviour withCallback(Consumer changeListener) { onHeldInserted = changeListener; return this; } - + public DepotBehaviour onlyAccepts(Predicate filter) { acceptedItems = filter; return this; @@ -267,8 +267,9 @@ public class DepotBehaviour extends BlockEntityBehaviour { int cumulativeStackSize = getPresentStackSize(); for (TransportedItemStack transportedItemStack : incoming) cumulativeStackSize += transportedItemStack.stack.getCount(); - int fromGetter = maxStackSize.get(); - return (fromGetter == 0 ? 64 : fromGetter) - cumulativeStackSize; + int fromGetter = + Math.min(maxStackSize.get() == 0 ? 64 : maxStackSize.get(), getHeldItemStack().getMaxStackSize()); + return (fromGetter) - cumulativeStackSize; } public ItemStack insert(TransportedItemStack heldItem, boolean simulate) { @@ -315,7 +316,7 @@ public class DepotBehaviour extends BlockEntityBehaviour { if (simulate) return returned; - + if (this.isEmpty()) { if (heldItem.insertedFrom.getAxis() .isHorizontal()) @@ -328,7 +329,7 @@ public class DepotBehaviour extends BlockEntityBehaviour { heldItem = heldItem.copy(); heldItem.stack.setCount(maxCount); } - + this.heldItem = heldItem; onHeldInserted.accept(heldItem.stack); return returned; @@ -361,7 +362,7 @@ public class DepotBehaviour extends BlockEntityBehaviour { return true; return false; } - + private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) { ItemStack inserted = transportedStack.stack; diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlockEntity.java index c054f9204a..fa715ccb1e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlockEntity.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.logistics.depot; import java.util.List; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; @@ -38,4 +39,12 @@ public class DepotBlockEntity extends SmartBlockEntity { public ItemStack getHeldItem() { return depotBehaviour.getHeldItemStack(); } + + public void setHeldItem(ItemStack item) { + TransportedItemStack newStack = new TransportedItemStack(item); + if (depotBehaviour.heldItem != null) + newStack.angle = depotBehaviour.heldItem.angle; + depotBehaviour.setHeldItem(newStack); + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/DepotRenderer.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotRenderer.java index b1ce049c33..8e21d77705 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/DepotRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotRenderer.java @@ -6,11 +6,12 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.content.kinetics.belt.BeltHelper; import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.box.PackageItem; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -26,8 +27,7 @@ import net.minecraft.world.phys.Vec3; public class DepotRenderer extends SafeBlockEntityRenderer { - public DepotRenderer(BlockEntityRendererProvider.Context context) { - } + public DepotRenderer(BlockEntityRendererProvider.Context context) {} @Override protected void renderSafe(DepotBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, @@ -58,7 +58,8 @@ public class DepotRenderer extends SafeBlockEntityRenderer { if (tis.insertedFrom.getAxis() .isHorizontal()) { Vec3 offsetVec = Vec3.atLowerCornerOf(tis.insertedFrom.getOpposite() - .getNormal()).scale(.5f - offset); + .getNormal()) + .scale(.5f - offset); ms.translate(offsetVec.x, offsetVec.y, offsetVec.z); boolean alongX = tis.insertedFrom.getClockWise() .getAxis() == Direction.Axis.X; @@ -70,7 +71,7 @@ public class DepotRenderer extends SafeBlockEntityRenderer { ItemStack itemStack = tis.stack; int angle = tis.angle; Random r = new Random(0); - renderItem(be.getLevel(), ms, buffer, light, overlay, itemStack, angle, r, itemPosition); + renderItem(be.getLevel(), ms, buffer, light, overlay, itemStack, angle, r, itemPosition, false); ms.popPose(); } @@ -92,22 +93,23 @@ public class DepotRenderer extends SafeBlockEntityRenderer { msr.rotateYDegrees(-(360 / 8f * i)); Random r = new Random(i + 1); int angle = (int) (360 * r.nextFloat()); - renderItem(be.getLevel(), ms, buffer, light, overlay, stack, renderUpright ? angle + 90 : angle, r, itemPosition); + renderItem(be.getLevel(), ms, buffer, light, overlay, stack, renderUpright ? angle + 90 : angle, r, + itemPosition, false); ms.popPose(); } ms.popPose(); } - public static void renderItem(Level level, PoseStack ms, MultiBufferSource buffer, int light, int overlay, ItemStack itemStack, - int angle, Random r, Vec3 itemPosition) { + public static void renderItem(Level level, PoseStack ms, MultiBufferSource buffer, int light, int overlay, + ItemStack itemStack, int angle, Random r, Vec3 itemPosition, boolean alwaysUpright) { ItemRenderer itemRenderer = Minecraft.getInstance() .getItemRenderer(); var msr = TransformStack.of(ms); int count = (int) (Mth.log2((int) (itemStack.getCount()))) / 2; - boolean renderUpright = BeltHelper.isItemUpright(itemStack); BakedModel bakedModel = itemRenderer.getModel(itemStack, null, null, 0); boolean blockItem = bakedModel.isGui3d(); + boolean renderUpright = BeltHelper.isItemUpright(itemStack) || alwaysUpright && !blockItem; ms.pushPose(); msr.rotateYDegrees(angle); @@ -126,9 +128,18 @@ public class DepotRenderer extends SafeBlockEntityRenderer { for (int i = 0; i <= count; i++) { ms.pushPose(); - if (blockItem) + if (blockItem && r != null) ms.translate(r.nextFloat() * .0625f * i, 0, r.nextFloat() * .0625f * i); - ms.scale(.5f, .5f, .5f); + + if (PackageItem.isPackage(itemStack) && !alwaysUpright) { + ms.translate(0, 4 / 16f, 0); + ms.scale(1.5f, 1.5f, 1.5f); + } else if (blockItem && alwaysUpright) { + ms.translate(0, 1 / 16f, 0); + ms.scale(.755f, .755f, .755f); + } else + ms.scale(.5f, .5f, .5f); + if (!blockItem && !renderUpright) { ms.translate(0, -3 / 16f, 0); msr.rotateXDegrees(90); diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlock.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlock.java index 08b0f02b5a..d3c2b05345 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlock.java @@ -11,15 +11,15 @@ import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; import com.simibubi.create.content.logistics.depot.EjectorBlockEntity.State; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.item.ItemHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; @@ -106,7 +106,7 @@ public class EjectorBlock extends HorizontalKineticBlock implements IBE i == 0 ? "*" : String.valueOf(i)); behaviours.add(maxStackSize); @@ -149,6 +151,8 @@ public class EjectorBlockEntity extends KineticBlockEntity { continue; if (entity instanceof ItemEntity) continue; + if (entity instanceof PackageEntity) + continue; if (entity.getPistonPushReaction() == PushReaction.IGNORE) continue; @@ -618,16 +622,16 @@ public class EjectorBlockEntity extends KineticBlockEntity { private class EjectorSlot extends ValueBoxTransform.Sided { @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { if (direction != Direction.UP) - return super.getLocalOffset(state); + return super.getLocalOffset(level, pos, state); return new Vec3(.5, 10.5 / 16f, .5).add(VecHelper.rotate(VecHelper.voxelSpace(0, 0, -5), angle(state), Axis.Y)); } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { if (direction != Direction.UP) { - super.rotate(state, ms); + super.rotate(level, pos, state, ms); return; } TransformStack.of(ms) diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorRenderer.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorRenderer.java index a77c22a158..8935d016f1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorRenderer.java @@ -4,16 +4,17 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.base.ShaftRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.content.logistics.box.PackageItem; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.transform.Rotate; import dev.engine_room.flywheel.lib.transform.TransformStack; import dev.engine_room.flywheel.lib.transform.Translate; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -44,7 +45,7 @@ public class EjectorRenderer extends ShaftRenderer { float angle = lidProgress * 70; if (!VisualizationManager.supportsVisualization(be.getLevel())) { - SuperByteBuffer model = CachedBufferer.partial(AllPartialModels.EJECTOR_TOP, be.getBlockState()); + SuperByteBuffer model = CachedBuffers.partial(AllPartialModels.EJECTOR_TOP, be.getBlockState()); applyLidAngle(be, angle, model); model.light(light) .renderInto(ms, buffer.getBuffer(RenderType.solid())); @@ -62,14 +63,22 @@ public class EjectorRenderer extends ShaftRenderer { ms.pushPose(); Vec3 launchedItemLocation = be.getLaunchedItemLocation(time); msr.translate(launchedItemLocation.subtract(Vec3.atLowerCornerOf(be.getBlockPos()))); - Vec3 itemRotOffset = VecHelper.voxelSpace(0, 3, 0); + Vec3 itemRotOffset = VecHelper.voxelSpace(0, 2, -1); msr.translate(itemRotOffset); - msr.rotateYDegrees(AngleHelper.horizontalAngle(be.getFacing())); - msr.rotateXDegrees(time * 40); + + if (PackageItem.isPackage(intAttached.getValue())) { + ms.translate(0, 4 / 16f, 0); + ms.scale(1.5f, 1.5f, 1.5f); + msr.rotateYDegrees(time * 20); + } else { + ms.scale(.5f, .5f, .5f); + msr.rotateYDegrees(AngleHelper.horizontalAngle(be.getFacing())); + msr.rotateXDegrees(time * 40); + } msr.translateBack(itemRotOffset); Minecraft.getInstance() .getItemRenderer() - .renderStatic(intAttached.getValue(), ItemDisplayContext.GROUND, light, overlay, ms, buffer, be.getLevel(), 0); + .renderStatic(intAttached.getValue(), ItemDisplayContext.FIXED, light, overlay, ms, buffer, be.getLevel(), 0); ms.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTargetHandler.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTargetHandler.java index 661845f5d2..61596eca2c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTargetHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTargetHandler.java @@ -5,13 +5,13 @@ import org.joml.Vector3f; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.theme.Color; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -33,6 +33,7 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult.Type; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -60,7 +61,7 @@ public class EjectorTargetHandler { String key = "weighted_ejector.target_set"; ChatFormatting colour = ChatFormatting.GOLD; - player.displayClientMessage(Lang.translateDirect(key) + player.displayClientMessage(CreateLang.translateDirect(key) .withStyle(colour), true); currentSelection = pos; launcher = null; @@ -99,7 +100,7 @@ public class EjectorTargetHandler { Direction validTargetDirection = getValidTargetDirection(pos); if (validTargetDirection == null) { - player.displayClientMessage(Lang.translateDirect(key) + player.displayClientMessage(CreateLang.translateDirect(key) .withStyle(colour), true); currentItem = null; currentSelection = null; @@ -110,7 +111,7 @@ public class EjectorTargetHandler { colour = ChatFormatting.GREEN; player.displayClientMessage( - Lang.translateDirect(key, currentSelection.getX(), currentSelection.getY(), currentSelection.getZ()) + CreateLang.translateDirect(key, currentSelection.getX(), currentSelection.getY(), currentSelection.getZ()) .withStyle(colour), true); @@ -176,9 +177,8 @@ public class EjectorTargetHandler { return; HitResult objectMouseOver = mc.hitResult; - if (!(objectMouseOver instanceof BlockHitResult)) + if (!(objectMouseOver instanceof BlockHitResult blockRayTraceResult)) return; - BlockHitResult blockRayTraceResult = (BlockHitResult) objectMouseOver; if (blockRayTraceResult.getType() == Type.MISS) return; @@ -211,7 +211,7 @@ public class EjectorTargetHandler { ClientLevel world = mc.level; AABB bb = new AABB(0, 0, 0, 1, 0, 1).move(currentSelection.offset(-validX, -yDiff, -validZ)); - CreateClient.OUTLINER.chaseAABB("valid", bb) + Outliner.getInstance().chaseAABB("valid", bb) .colored(intColor) .lineWidth(1 / 16f); @@ -227,9 +227,8 @@ public class EjectorTargetHandler { if (!AllItems.WRENCH.isIn(heldItem)) return; HitResult objectMouseOver = Minecraft.getInstance().hitResult; - if (!(objectMouseOver instanceof BlockHitResult)) + if (!(objectMouseOver instanceof BlockHitResult result)) return; - BlockHitResult result = (BlockHitResult) objectMouseOver; BlockPos pos = result.getBlockPos(); BlockEntity be = Minecraft.getInstance().level.getBlockEntity(pos); @@ -261,7 +260,7 @@ public class EjectorTargetHandler { BlockState state = world.getBlockState(pos); VoxelShape shape = state.getShape(world, pos); AABB boundingBox = shape.isEmpty() ? new AABB(BlockPos.ZERO) : shape.bounds(); - CreateClient.OUTLINER.showAABB("target", boundingBox.move(pos)) + Outliner.getInstance().showAABB("target", boundingBox.move(pos)) .colored(0xffcb74) .lineWidth(1 / 16f); } diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EntityLauncher.java b/src/main/java/com/simibubi/create/content/logistics/depot/EntityLauncher.java index 3495a7d200..65df58497b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/EntityLauncher.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EntityLauncher.java @@ -1,8 +1,7 @@ package com.simibubi.create.content.logistics.depot; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -97,40 +96,40 @@ public class EntityLauncher { * Vertical Motion fv(x) = (x - 0.08) * 0.98 * (Gravity modification ignored) * > See LivingEntity.travel() - * + * ** n-th Iterative * (= given initial velocity x, motion after t ticks) * X'(x, t) = x * 0.91^t * Y'(x, t) = x * 0.98^t + ((0.98^t - 1) / (0.98 - 1)) * -0.0784 - * + * ** integral * (= given intial velocity x, location offset after t ticks) * X(x, t) = -10.6033x * (-1 + 0.91^t) * Y(x, t) = -49.4983x * 0.98^t + 49.4983x - 194.033 * 0.98^t - 3.92t + 194.033 - * + * ** argmax y * (= given initial y velocity, ticks at which y reaches top) * tPeak(x) = log(98 / (25x + 98)) / (2*log(7) - 2*log(5) - log(2)) - * + * ** max y * (= given initial y velocity, height offset at tPeak) * yPeak(x) = 889.636 + 49.4983x + 0.032928/(98 + 25x) + 194.033 * log(1/(98 + 25x)) - * + * ** yPeak inverse (Zelo's approximation) * (= given yPeak, initial y velocity required to reach it at max) * yMotion(h) = sqrt(2h/13) + 0.015h - * + * ** Y'(x, t) inverse (Simi's approximation) * (= given yTarget and initial y velocity, elapsed ticks when arc hits yTarget on its way down) * t*(x, v) = sqrt(yPeak(v) - x) * 4.87 + 0.115 * (yPeak(v) - x) + tPeak(v) - * + * ** xMotion * (= given t* and xTarget, initial x velocity such that X'(x, t*) = xTarget) * xMotion(t, x) = x / (-10.6033 * (-1 + 0.91^t)); - * + * ** xError * Interpolated correction function from observed inaccuracies in-game - * + * */ double xError = (-0.0007 * Math.pow(xTarget + .5, 2) + 0.484) diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/MountedDepotInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/depot/MountedDepotInteractionBehaviour.java new file mode 100644 index 0000000000..1c97e239a0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/MountedDepotInteractionBehaviour.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.logistics.depot; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.MountedStorageManager; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorage; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +public class MountedDepotInteractionBehaviour extends MovingInteractionBehaviour { + + @Override + public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + ItemStack itemInHand = player.getItemInHand(activeHand); + if (activeHand == InteractionHand.OFF_HAND) + return false; + if (player.level().isClientSide) + return true; + + MountedStorageManager manager = contraptionEntity.getContraption().getStorage(); + + MountedItemStorage storage = manager.getAllItemStorages().get(localPos); + if (!(storage instanceof DepotMountedStorage depot)) + return false; + + ItemStack itemOnDepot = depot.getItem(); + if (itemOnDepot.isEmpty() && itemInHand.isEmpty()) + return true; + + depot.setItem(itemInHand.copy()); + player.setItemInHand(activeHand, itemOnDepot.copy()); + AllSoundEvents.DEPOT_PLOP.playOnServer(player.level(), + BlockPos.containing(contraptionEntity.toGlobalVector(Vec3.atCenterOf(localPos), 0))); + + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/SharedDepotBlockMethods.java b/src/main/java/com/simibubi/create/content/logistics/depot/SharedDepotBlockMethods.java index 18f105944e..32e63049ae 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/SharedDepotBlockMethods.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/SharedDepotBlockMethods.java @@ -5,8 +5,11 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.box.PackageEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.sounds.SoundEvents; @@ -22,6 +25,7 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.items.ItemStackHandler; public class SharedDepotBlockMethods { @@ -75,22 +79,26 @@ public class SharedDepotBlockMethods { } public static void onLanded(BlockGetter worldIn, Entity entityIn) { - if (!(entityIn instanceof ItemEntity)) - return; - if (!entityIn.isAlive()) + ItemStack asItem = ItemHelper.fromItemEntity(entityIn); + if (asItem.isEmpty()) return; if (entityIn.level().isClientSide) return; - ItemEntity itemEntity = (ItemEntity) entityIn; - DirectBeltInputBehaviour inputBehaviour = - BlockEntityBehaviour.get(worldIn, entityIn.blockPosition(), DirectBeltInputBehaviour.TYPE); + BlockPos pos = entityIn.blockPosition(); + DirectBeltInputBehaviour inputBehaviour = BlockEntityBehaviour.get(worldIn, pos, DirectBeltInputBehaviour.TYPE); if (inputBehaviour == null) return; - ItemStack remainder = inputBehaviour.handleInsertion(itemEntity.getItem(), Direction.DOWN, false); - itemEntity.setItem(remainder); + Vec3 targetLocation = VecHelper.getCenterOf(pos) + .add(0, 5 / 16f, 0); + if (!PackageEntity.centerPackage(entityIn, targetLocation)) + return; + + ItemStack remainder = inputBehaviour.handleInsertion(asItem, Direction.DOWN, false); + if (entityIn instanceof ItemEntity) + ((ItemEntity) entityIn).setItem(remainder); if (remainder.isEmpty()) - itemEntity.discard(); + entityIn.discard(); } public static int getComparatorInputOverride(BlockState blockState, Level worldIn, BlockPos pos) { diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorage.java b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorage.java new file mode 100644 index 0000000000..d96eda7471 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorage.java @@ -0,0 +1,109 @@ +package com.simibubi.create.content.logistics.depot.storage; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.WrapperMountedItemStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.logistics.depot.DepotBlockEntity; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorage.Handler; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +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 net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +import net.minecraftforge.items.ItemStackHandler; + +public class DepotMountedStorage extends WrapperMountedItemStorage implements SyncedMountedStorage { + public static final Codec CODEC = ItemStack.CODEC.xmap( + DepotMountedStorage::new, DepotMountedStorage::getItem + ); + + private boolean dirty; + + protected DepotMountedStorage(ItemStack stack) { + this(AllMountedStorageTypes.DEPOT.get(), stack); + } + + protected DepotMountedStorage(MountedItemStorageType type, ItemStack stack) { + super(type, new Handler(stack)); + this.wrapped.onChange = () -> this.dirty = true; + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof DepotBlockEntity depot) { + depot.setHeldItem(this.getStackInSlot(0)); + } + } + + @Override + public boolean handleInteraction(ServerPlayer player, Contraption contraption, StructureBlockInfo info) { + // interaction is handled in the Interaction Behavior, swaps items with the player + return false; + } + + @Override + public boolean isDirty() { + return this.dirty; + } + + @Override + public void markClean() { + this.dirty = false; + } + + @Override + public void afterSync(Contraption contraption, BlockPos localPos) { + BlockEntity be = contraption.presentBlockEntities.get(localPos); + if (be instanceof DepotBlockEntity depot) { + depot.setHeldItem(this.getItem()); + } + } + + public void setItem(ItemStack stack) { + this.setStackInSlot(0, stack); + } + + public ItemStack getItem() { + return this.getStackInSlot(0); + } + + public static DepotMountedStorage fromDepot(DepotBlockEntity depot) { + ItemStack held = depot.getHeldItem(); + return new DepotMountedStorage(held.copy()); + } + + public static DepotMountedStorage fromLegacy(CompoundTag nbt) { + ItemStackHandler handler = new ItemStackHandler(); + handler.deserializeNBT(nbt); + if (handler.getSlots() == 1) { + ItemStack stack = handler.getStackInSlot(0); + return new DepotMountedStorage(stack); + } else { + return new DepotMountedStorage(ItemStack.EMPTY); + } + } + + public static final class Handler extends ItemStackHandler { + private Runnable onChange = () -> {}; + + private Handler(ItemStack stack) { + super(1); + this.setStackInSlot(0, stack); + } + + @Override + protected void onContentsChanged(int slot) { + this.onChange.run(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorageType.java b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorageType.java new file mode 100644 index 0000000000..6b47a17487 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.logistics.depot.storage; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.content.logistics.depot.DepotBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class DepotMountedStorageType extends MountedItemStorageType { + public DepotMountedStorageType() { + super(DepotMountedStorage.CODEC); + } + + @Override + @Nullable + public DepotMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof DepotBlockEntity depot) { + return DepotMountedStorage.fromDepot(depot); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java new file mode 100644 index 0000000000..ce280b1c74 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java @@ -0,0 +1,1071 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; + +import javax.annotation.Nullable; + +import org.joml.Math; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.logistics.filter.FilterItemStack; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportBlockEntity; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; +import com.simibubi.create.content.logistics.packager.PackagingRequest; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBlockItem; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedClientHandler; +import com.simibubi.create.content.logistics.packagerLink.LogisticsManager; +import com.simibubi.create.content.logistics.packagerLink.RequestPromise; +import com.simibubi.create.content.logistics.packagerLink.RequestPromiseQueue; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.gui.ScreenOpener; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.ChatFormatting; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkHooks; + +public class FactoryPanelBehaviour extends FilteringBehaviour implements MenuProvider { + + public static final BehaviourType TOP_LEFT = new BehaviourType<>(); + public static final BehaviourType TOP_RIGHT = new BehaviourType<>(); + public static final BehaviourType BOTTOM_LEFT = new BehaviourType<>(); + public static final BehaviourType BOTTOM_RIGHT = new BehaviourType<>(); + public static final int REQUEST_INTERVAL = 100; + + public Map targetedBy; + public Map targetedByLinks; + public Set targeting; + public List activeCraftingArrangement; + + public boolean satisfied; + public boolean promisedSatisfied; + public boolean waitingForNetwork; + public String recipeAddress; + public int recipeOutput; + public LerpedFloat bulb; + public PanelSlot slot; + public int promiseClearingInterval; + public boolean forceClearPromises; + public UUID network; + public boolean active; + + public boolean redstonePowered; + + public RequestPromiseQueue restockerPromises; + private boolean promisePrimedForMarkDirty; + + private int lastReportedUnloadedLinks; + private int lastReportedLevelInStorage; + private int lastReportedPromises; + private int timer; + + public FactoryPanelBehaviour(FactoryPanelBlockEntity be, PanelSlot slot) { + super(be, new FactoryPanelSlotPositioning(slot)); + this.slot = slot; + this.targetedBy = new HashMap<>(); + this.targetedByLinks = new HashMap<>(); + this.targeting = new HashSet<>(); + this.count = 0; + this.satisfied = false; + this.promisedSatisfied = false; + this.waitingForNetwork = false; + this.activeCraftingArrangement = List.of(); + this.recipeAddress = ""; + this.recipeOutput = 1; + this.active = false; + this.forceClearPromises = false; + this.redstonePowered = false; + this.promiseClearingInterval = -1; + this.bulb = LerpedFloat.linear() + .startWithValue(0) + .chase(0, 0.175, Chaser.EXP); + this.restockerPromises = new RequestPromiseQueue(be::setChanged); + this.promisePrimedForMarkDirty = true; + this.network = UUID.randomUUID(); + setLazyTickRate(40); + } + + public void setNetwork(UUID network) { + this.network = network; + } + + @Nullable + public static FactoryPanelBehaviour at(BlockAndTintGetter world, FactoryPanelConnection connection) { + Object cached = connection.cachedSource.get(); + if (cached instanceof FactoryPanelBehaviour fbe && !fbe.blockEntity.isRemoved()) + return fbe; + FactoryPanelBehaviour result = at(world, connection.from); + connection.cachedSource = new WeakReference<>(result); + return result; + } + + @Nullable + public static FactoryPanelBehaviour at(BlockAndTintGetter world, FactoryPanelPosition pos) { + if (world instanceof Level l && !l.isLoaded(pos.pos())) + return null; + if (!(world.getBlockEntity(pos.pos()) instanceof FactoryPanelBlockEntity fpbe)) + return null; + FactoryPanelBehaviour behaviour = fpbe.panels.get(pos.slot()); + if (!behaviour.active) + return null; + return behaviour; + } + + @Nullable + public static FactoryPanelSupportBehaviour linkAt(BlockAndTintGetter world, FactoryPanelConnection connection) { + Object cached = connection.cachedSource.get(); + if (cached instanceof FactoryPanelSupportBehaviour fpsb && !fpsb.blockEntity.isRemoved()) + return fpsb; + FactoryPanelSupportBehaviour result = linkAt(world, connection.from); + connection.cachedSource = new WeakReference<>(result); + return result; + } + + @Nullable + public static FactoryPanelSupportBehaviour linkAt(BlockAndTintGetter world, FactoryPanelPosition pos) { + if (world instanceof Level l && !l.isLoaded(pos.pos())) + return null; + return BlockEntityBehaviour.get(world, pos.pos(), FactoryPanelSupportBehaviour.TYPE); + } + + public void moveTo(FactoryPanelPosition newPos, ServerPlayer player) { + Level level = getWorld(); + BlockState existingState = level.getBlockState(newPos.pos()); + + // Check if target pos is valid + if (FactoryPanelBehaviour.at(level, newPos) != null) + return; + boolean isAddedToOtherGauge = AllBlocks.FACTORY_GAUGE.has(existingState); + if (!existingState.isAir() && !isAddedToOtherGauge) + return; + if (isAddedToOtherGauge && existingState != blockEntity.getBlockState()) + return; + if (!isAddedToOtherGauge) + level.setBlock(newPos.pos(), blockEntity.getBlockState(), 3); + + for (BlockPos blockPos : targetedByLinks.keySet()) + if (!blockPos.closerThan(newPos.pos(), 24)) + return; + for (FactoryPanelPosition blockPos : targetedBy.keySet()) + if (!blockPos.pos().closerThan(newPos.pos(), 24)) + return; + for (FactoryPanelPosition blockPos : targeting) + if (!blockPos.pos().closerThan(newPos.pos(), 24)) + return; + + // Disconnect links + for (BlockPos pos : targetedByLinks.keySet()) { + FactoryPanelSupportBehaviour at = linkAt(level, new FactoryPanelPosition(pos, slot)); + if (at != null) + at.disconnect(this); + } + + SmartBlockEntity oldBE = blockEntity; + FactoryPanelPosition oldPos = getPanelPosition(); + moveToSlot(newPos.slot()); + + // Add to new BE + if (level.getBlockEntity(newPos.pos()) instanceof FactoryPanelBlockEntity fpbe) { + fpbe.attachBehaviourLate(this); + fpbe.panels.put(slot, this); + fpbe.redraw = true; + fpbe.lastShape = null; + fpbe.notifyUpdate(); + } + + // Remove from old BE + if (oldBE instanceof FactoryPanelBlockEntity fpbe) { + FactoryPanelBehaviour newBehaviour = new FactoryPanelBehaviour(fpbe, oldPos.slot()); + fpbe.attachBehaviourLate(newBehaviour); + fpbe.panels.put(oldPos.slot(), newBehaviour); + fpbe.redraw = true; + fpbe.lastShape = null; + fpbe.notifyUpdate(); + } + + // Rewire connections + for (FactoryPanelPosition position : targeting) { + FactoryPanelBehaviour at = at(level, position); + if (at != null) { + FactoryPanelConnection connection = at.targetedBy.remove(oldPos); + connection.from = newPos; + at.targetedBy.put(newPos, connection); + at.blockEntity.sendData(); + } + } + + for (FactoryPanelPosition position : targetedBy.keySet()) { + FactoryPanelBehaviour at = at(level, position); + if (at != null) { + at.targeting.remove(oldPos); + at.targeting.add(newPos); + } + } + + // Reconnect links + for (BlockPos pos : targetedByLinks.keySet()) { + FactoryPanelSupportBehaviour at = linkAt(level, new FactoryPanelPosition(pos, slot)); + if (at != null) + at.connect(this); + } + + // Tell player + player.displayClientMessage(CreateLang.translate("factory_panel.relocated") + .style(ChatFormatting.GREEN) + .component(), true); + player.level() + .playSound(null, newPos.pos(), SoundEvents.COPPER_BREAK, SoundSource.BLOCKS, 1.0f, 1.0f); + } + + private void moveToSlot(PanelSlot slot) { + this.slot = slot; + if (this.getSlotPositioning() instanceof FactoryPanelSlotPositioning fpsp) + fpsp.slot = slot; + } + + @Override + public void initialize() { + super.initialize(); + notifyRedstoneOutputs(); + } + + @Override + public void tick() { + super.tick(); + if (getWorld().isClientSide()) { + if (blockEntity.isVirtual()) + tickStorageMonitor(); + bulb.updateChaseTarget(redstonePowered || satisfied ? 1 : 0); + bulb.tickChaser(); + if (active) + tickOutline(); + return; + } + + if (!promisePrimedForMarkDirty) { + restockerPromises.setOnChanged(blockEntity::setChanged); + promisePrimedForMarkDirty = true; + } + + tickStorageMonitor(); + tickRequests(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (getWorld().isClientSide()) + return; + checkForRedstoneInput(); + } + + public void checkForRedstoneInput() { + if (!active) + return; + + boolean shouldPower = false; + for (FactoryPanelConnection connection : targetedByLinks.values()) { + if (!getWorld().isLoaded(connection.from.pos())) + return; + FactoryPanelSupportBehaviour linkAt = linkAt(getWorld(), connection); + if (linkAt == null) + return; + shouldPower |= linkAt.shouldPanelBePowered(); + } + + if (shouldPower == redstonePowered) + return; + + redstonePowered = shouldPower; + blockEntity.notifyUpdate(); + timer = 1; + } + + private void notifyRedstoneOutputs() { + for (FactoryPanelConnection connection : targetedByLinks.values()) { + if (!getWorld().isLoaded(connection.from.pos())) + return; + FactoryPanelSupportBehaviour linkAt = linkAt(getWorld(), connection); + if (linkAt == null || linkAt.isOutput()) + return; + linkAt.notifyLink(); + } + } + + private void tickStorageMonitor() { + ItemStack filter = getFilter(); + int inStorage = getLevelInStorage(); + int promised = getPromised(); + int demand = getAmount() * (upTo ? 1 : filter.getMaxStackSize()); + int unloadedLinkCount = getUnloadedLinks(); + boolean shouldSatisfy = filter.isEmpty() || inStorage >= demand; + boolean shouldPromiseSatisfy = filter.isEmpty() || inStorage + promised >= demand; + boolean shouldWait = unloadedLinkCount > 0; + + if (lastReportedLevelInStorage == inStorage && lastReportedPromises == promised + && lastReportedUnloadedLinks == unloadedLinkCount && satisfied == shouldSatisfy + && promisedSatisfied == shouldPromiseSatisfy && waitingForNetwork == shouldWait) + return; + + if (!satisfied && shouldSatisfy && demand > 0) { + AllSoundEvents.CONFIRM.playOnServer(getWorld(), getPos(), 0.075f, 1f); + AllSoundEvents.CONFIRM_2.playOnServer(getWorld(), getPos(), 0.125f, 0.575f); + } + + boolean notifyOutputs = satisfied != shouldSatisfy; + lastReportedLevelInStorage = inStorage; + satisfied = shouldSatisfy; + lastReportedPromises = promised; + promisedSatisfied = shouldPromiseSatisfy; + lastReportedUnloadedLinks = unloadedLinkCount; + waitingForNetwork = shouldWait; + if (!getWorld().isClientSide) + blockEntity.sendData(); + if (notifyOutputs) + notifyRedstoneOutputs(); + } + + private void tickRequests() { + FactoryPanelBlockEntity panelBE = panelBE(); + if (targetedBy.isEmpty() && !panelBE.restocker) + return; + if (satisfied || promisedSatisfied || waitingForNetwork || redstonePowered) + return; + if (timer > 0) { + timer = Math.min(timer, REQUEST_INTERVAL); + timer--; + return; + } + + resetTimer(); + + if (recipeAddress.isBlank()) + return; + + if (panelBE.restocker) { + tryRestock(); + return; + } + + boolean failed = false; + + Multimap toRequest = HashMultimap.create(); + List toRequestAsList = new ArrayList<>(); + + for (FactoryPanelConnection connection : targetedBy.values()) { + FactoryPanelBehaviour source = at(getWorld(), connection); + if (source == null) + return; + + ItemStack item = source.getFilter(); + int amount = connection.amount; + InventorySummary summary = LogisticsManager.getSummaryOfNetwork(source.network, true); + if (amount == 0 || item.isEmpty() || summary.getCountOf(item) < amount) { + sendEffect(connection.from, false); + failed = true; + continue; + } + + BigItemStack stack = new BigItemStack(item, amount); + toRequest.put(source.network, stack); + toRequestAsList.add(stack); + sendEffect(connection.from, true); + } + + if (failed) + return; + + // Input items may come from differing networks + Map> asMap = toRequest.asMap(); + PackageOrder requestContext = new PackageOrder(toRequestAsList); + List> requests = new ArrayList<>(); + + // Panel may enforce item arrangement + if (!activeCraftingArrangement.isEmpty()) + requestContext = new PackageOrder(activeCraftingArrangement.stream() + .map(BigItemStack::new) + .toList()); + + // Collect request distributions + for (Entry> entry : asMap.entrySet()) { + PackageOrder order = new PackageOrder(new ArrayList<>(entry.getValue())); + Multimap request = + LogisticsManager.findPackagersForRequest(entry.getKey(), order, requestContext, null, recipeAddress); + requests.add(request); + } + + // Check if any packager is busy - cancel all + for (Multimap entry : requests) + for (PackagerBlockEntity packager : entry.keySet()) + if (packager.isTooBusyFor(RequestType.RESTOCK)) + return; + + // Send it + for (Multimap entry : requests) + LogisticsManager.performPackageRequests(entry); + + // Keep the output promise + RequestPromiseQueue promises = Create.LOGISTICS.getQueuedPromises(network); + if (promises != null) + promises.add(new RequestPromise(new BigItemStack(getFilter(), recipeOutput))); + + panelBE.advancements.awardPlayer(AllAdvancements.FACTORY_GAUGE); + } + + private void tryRestock() { + ItemStack item = getFilter(); + if (item.isEmpty()) + return; + + FactoryPanelBlockEntity panelBE = panelBE(); + PackagerBlockEntity packager = panelBE.getRestockedPackager(); + if (packager == null || !packager.targetInventory.hasInventory()) + return; + + int availableOnNetwork = LogisticsManager.getStockOf(network, item, packager.targetInventory.getInventory()); + if (availableOnNetwork == 0) { + sendEffect(getPanelPosition(), false); + return; + } + + int inStorage = getLevelInStorage(); + int promised = getPromised(); + int maxStackSize = item.getMaxStackSize(); + int demand = getAmount() * (upTo ? 1 : maxStackSize); + int amountToOrder = Math.clamp(demand - promised - inStorage, 0, maxStackSize * 9); + + BigItemStack orderedItem = new BigItemStack(item, Math.min(amountToOrder, availableOnNetwork)); + PackageOrder order = new PackageOrder(List.of(orderedItem)); + + sendEffect(getPanelPosition(), true); + + if (!LogisticsManager.broadcastPackageRequest(network, RequestType.RESTOCK, order, + packager.targetInventory.getInventory(), recipeAddress, null)) + return; + + restockerPromises.add(new RequestPromise(orderedItem)); + } + + private void sendEffect(FactoryPanelPosition fromPos, boolean success) { + AllPackets.sendToNear(getWorld(), getPos(), 64, + new FactoryPanelEffectPacket(fromPos, getPanelPosition(), success)); + } + + public void addConnection(FactoryPanelPosition fromPos) { + FactoryPanelSupportBehaviour link = linkAt(getWorld(), fromPos); + if (link != null) { + targetedByLinks.put(fromPos.pos(), new FactoryPanelConnection(fromPos, 1)); + link.connect(this); + blockEntity.notifyUpdate(); + return; + } + + if (panelBE().restocker) + return; + if (targetedBy.size() >= 9) + return; + + FactoryPanelBehaviour source = at(getWorld(), fromPos); + if (source == null) + return; + + source.targeting.add(getPanelPosition()); + targetedBy.put(fromPos, new FactoryPanelConnection(fromPos, 1)); + blockEntity.notifyUpdate(); + } + + public FactoryPanelPosition getPanelPosition() { + return new FactoryPanelPosition(getPos(), slot); + } + + public FactoryPanelBlockEntity panelBE() { + return (FactoryPanelBlockEntity) blockEntity; + } + + @Override + public void onShortInteract(Player player, InteractionHand hand, Direction side, BlockHitResult hitResult) { + // Network is protected + if (!Create.LOGISTICS.mayInteract(network, player)) { + player.displayClientMessage(CreateLang.translate("logistically_linked.protected") + .style(ChatFormatting.RED) + .component(), true); + return; + } + + boolean isClientSide = player.level().isClientSide; + + // Wrench cycles through arrow bending + if (targeting.size() + targetedByLinks.size() > 0 && AllItemTags.WRENCH.matches(player.getItemInHand(hand))) { + int sharedMode = -1; + boolean notifySelf = false; + + for (FactoryPanelPosition target : targeting) { + FactoryPanelBehaviour at = at(getWorld(), target); + if (at == null) + continue; + FactoryPanelConnection connection = at.targetedBy.get(getPanelPosition()); + if (connection == null) + continue; + if (sharedMode == -1) + sharedMode = (connection.arrowBendMode + 1) % 4; + connection.arrowBendMode = sharedMode; + if (!isClientSide) + at.blockEntity.notifyUpdate(); + } + + for (FactoryPanelConnection connection : targetedByLinks.values()) { + if (sharedMode == -1) + sharedMode = (connection.arrowBendMode + 1) % 4; + connection.arrowBendMode = sharedMode; + if (!isClientSide) + notifySelf = true; + } + + if (sharedMode == -1) + return; + + char[] boxes = "\u25a1\u25a1\u25a1\u25a1".toCharArray(); + boxes[sharedMode] = '\u25a0'; + player.displayClientMessage(CreateLang.translate("factory_panel.cycled_arrow_path", new String(boxes)) + .component(), true); + if (notifySelf) + blockEntity.notifyUpdate(); + + return; + } + + // Client might be in the process of connecting a panel + if (isClientSide) + if (FactoryPanelConnectionHandler.panelClicked(getWorld(), player, this)) + return; + + ItemStack heldItem = player.getItemInHand(hand); + if (getFilter().isEmpty()) { + // Open screen for setting an item through JEI + if (heldItem.isEmpty()) { + if (!isClientSide && player instanceof ServerPlayer sp) + NetworkHooks.openScreen(sp, this, buf -> getPanelPosition().send(buf)); + return; + } + + // Use regular filter interaction for setting the item + super.onShortInteract(player, hand, side, hitResult); + return; + } + + // Bind logistics items to this panels' frequency + if (heldItem.getItem() instanceof LogisticallyLinkedBlockItem) { + if (!isClientSide) + LogisticallyLinkedBlockItem.assignFrequency(heldItem, player, network); + return; + } + + // Open configuration screen + if (isClientSide) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> displayScreen(player)); + } + + public void enable() { + active = true; + blockEntity.notifyUpdate(); + } + + public void disable() { + destroy(); + active = false; + targetedBy = new HashMap<>(); + targeting = new HashSet<>(); + count = 0; + satisfied = false; + promisedSatisfied = false; + recipeAddress = ""; + recipeOutput = 1; + setFilter(ItemStack.EMPTY); + blockEntity.notifyUpdate(); + } + + @Override + public boolean isActive() { + return active; + } + + public boolean isMissingAddress() { + return (!targetedBy.isEmpty() || panelBE().restocker) && count != 0 && recipeAddress.isBlank(); + } + + @Override + public void destroy() { + disconnectAll(); + super.destroy(); + } + + public void disconnectAll() { + FactoryPanelPosition panelPosition = getPanelPosition(); + disconnectAllLinks(); + for (FactoryPanelConnection connection : targetedBy.values()) { + FactoryPanelBehaviour source = at(getWorld(), connection); + if (source != null) { + source.targeting.remove(panelPosition); + source.blockEntity.sendData(); + } + } + for (FactoryPanelPosition position : targeting) { + FactoryPanelBehaviour target = at(getWorld(), position); + if (target != null) { + target.targetedBy.remove(panelPosition); + target.blockEntity.sendData(); + } + } + targetedBy.clear(); + targeting.clear(); + } + + public void disconnectAllLinks() { + for (FactoryPanelConnection connection : targetedByLinks.values()) { + FactoryPanelSupportBehaviour source = linkAt(getWorld(), connection); + if (source != null) + source.disconnect(this); + } + targetedByLinks.clear(); + } + + public int getUnloadedLinks() { + if (getWorld().isClientSide()) + return lastReportedUnloadedLinks; + if (panelBE().restocker) + return panelBE().getRestockedPackager() == null ? 1 : 0; + return Create.LOGISTICS.getUnloadedLinkCount(network); + } + + public int getLevelInStorage() { + if (blockEntity.isVirtual()) + return 1; + if (getWorld().isClientSide()) + return lastReportedLevelInStorage; + if (getFilter().isEmpty()) + return 0; + + InventorySummary summary = getRelevantSummary(); + return summary.getCountOf(getFilter()); + } + + private InventorySummary getRelevantSummary() { + FactoryPanelBlockEntity panelBE = panelBE(); + if (!panelBE.restocker) + return LogisticsManager.getSummaryOfNetwork(network, false); + PackagerBlockEntity packager = panelBE.getRestockedPackager(); + if (packager == null) + return InventorySummary.EMPTY; + return packager.getAvailableItems(true); + } + + public int getPromised() { + if (getWorld().isClientSide()) + return lastReportedPromises; + ItemStack item = getFilter(); + if (item.isEmpty()) + return 0; + + if (panelBE().restocker) { + if (forceClearPromises) { + restockerPromises.forceClear(item); + resetTimerSlightly(); + } + forceClearPromises = false; + return restockerPromises.getTotalPromisedAndRemoveExpired(item, getPromiseExpiryTimeInTicks()); + } + + RequestPromiseQueue promises = Create.LOGISTICS.getQueuedPromises(network); + if (forceClearPromises) { + promises.forceClear(item); + resetTimerSlightly(); + } + forceClearPromises = false; + + return promises == null ? 0 : promises.getTotalPromisedAndRemoveExpired(item, getPromiseExpiryTimeInTicks()); + } + + public void resetTimer() { + timer = REQUEST_INTERVAL; + } + + public void resetTimerSlightly() { + timer = REQUEST_INTERVAL / 2; + } + + private int getPromiseExpiryTimeInTicks() { + if (promiseClearingInterval == -1) + return -1; + if (promiseClearingInterval == 0) + return 20 * 30; + + return promiseClearingInterval * 20 * 60; + } + + @Override + public void writeSafe(CompoundTag nbt) { + if (!active) + return; + + CompoundTag panelTag = new CompoundTag(); + panelTag.put("Filter", getFilter().serializeNBT()); + panelTag.putInt("FilterAmount", count); + panelTag.putUUID("Freq", network); + panelTag.putString("RecipeAddress", recipeAddress); + panelTag.putInt("PromiseClearingInterval", -1); + panelTag.putInt("RecipeOutput", 1); + nbt.put(CreateLang.asId(slot.name()), panelTag); + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + if (!active) + return; + + CompoundTag panelTag = new CompoundTag(); + super.write(panelTag, clientPacket); + + panelTag.putInt("Timer", timer); + panelTag.putInt("LastLevel", lastReportedLevelInStorage); + panelTag.putInt("LastPromised", lastReportedPromises); + panelTag.putInt("LastUnloadedLinks", lastReportedUnloadedLinks); + panelTag.putBoolean("Satisfied", satisfied); + panelTag.putBoolean("PromisedSatisfied", promisedSatisfied); + panelTag.putBoolean("Waiting", waitingForNetwork); + panelTag.putBoolean("RedstonePowered", redstonePowered); + panelTag.put("Targeting", NBTHelper.writeCompoundList(targeting, FactoryPanelPosition::write)); + panelTag.put("TargetedBy", NBTHelper.writeCompoundList(targetedBy.values(), FactoryPanelConnection::write)); + panelTag.put("TargetedByLinks", + NBTHelper.writeCompoundList(targetedByLinks.values(), FactoryPanelConnection::write)); + panelTag.putString("RecipeAddress", recipeAddress); + panelTag.putInt("RecipeOutput", recipeOutput); + panelTag.putInt("PromiseClearingInterval", promiseClearingInterval); + panelTag.putUUID("Freq", network); + panelTag.put("Craft", NBTHelper.writeItemList(activeCraftingArrangement)); + + if (panelBE().restocker && !clientPacket) + panelTag.put("Promises", restockerPromises.write()); + + nbt.put(CreateLang.asId(slot.name()), panelTag); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + CompoundTag panelTag = nbt.getCompound(CreateLang.asId(slot.name())); + if (panelTag.isEmpty()) { + active = false; + return; + } + + active = true; + filter = FilterItemStack.of(panelTag.getCompound("Filter")); + count = panelTag.getInt("FilterAmount"); + upTo = panelTag.getBoolean("UpTo"); + timer = panelTag.getInt("Timer"); + lastReportedLevelInStorage = panelTag.getInt("LastLevel"); + lastReportedPromises = panelTag.getInt("LastPromised"); + lastReportedUnloadedLinks = panelTag.getInt("LastUnloadedLinks"); + satisfied = panelTag.getBoolean("Satisfied"); + promisedSatisfied = panelTag.getBoolean("PromisedSatisfied"); + waitingForNetwork = panelTag.getBoolean("Waiting"); + redstonePowered = panelTag.getBoolean("RedstonePowered"); + promiseClearingInterval = panelTag.getInt("PromiseClearingInterval"); + if (panelTag.hasUUID("Freq")) + network = panelTag.getUUID("Freq"); + + targeting.clear(); + NBTHelper.iterateCompoundList(panelTag.getList("Targeting", Tag.TAG_COMPOUND), + c -> targeting.add(FactoryPanelPosition.read(c))); + + targetedBy.clear(); + NBTHelper.iterateCompoundList(panelTag.getList("TargetedBy", Tag.TAG_COMPOUND), + c -> targetedBy.put(FactoryPanelPosition.read(c), FactoryPanelConnection.read(c))); + + targetedByLinks.clear(); + NBTHelper.iterateCompoundList(panelTag.getList("TargetedByLinks", Tag.TAG_COMPOUND), + c -> targetedByLinks.put(FactoryPanelPosition.read(c) + .pos(), FactoryPanelConnection.read(c))); + + activeCraftingArrangement = NBTHelper.readItemList(panelTag.getList("Craft", Tag.TAG_COMPOUND)); + recipeAddress = panelTag.getString("RecipeAddress"); + recipeOutput = panelTag.getInt("RecipeOutput"); + + if (nbt.getBoolean("Restocker") && !clientPacket) { + restockerPromises = RequestPromiseQueue.read(panelTag.getCompound("Promises"), () -> { + }); + promisePrimedForMarkDirty = false; + } + } + + @Override + public float getRenderDistance() { + return 64; + } + + @Override + public MutableComponent formatValue(ValueSettings value) { + if (value.value() == 0) { + return CreateLang.translateDirect("gui.factory_panel.inactive"); + } else { + return Component.literal(Math.max(0, value.value()) + ((value.row() == 0) ? "" : "\u25A4")); + } + } + + @Override + public boolean setFilter(ItemStack stack) { + ItemStack filter = stack.copy(); + if (stack.getItem() instanceof FilterItem) + return false; + this.filter = FilterItemStack.of(filter); + blockEntity.setChanged(); + blockEntity.sendData(); + return true; + } + + @Override + public void setValueSettings(Player player, ValueSettings settings, boolean ctrlDown) { + if (getValueSettings().equals(settings)) + return; + count = Math.max(0, settings.value()); + upTo = settings.row() == 0; + panelBE().redraw = true; + blockEntity.setChanged(); + blockEntity.sendData(); + playFeedbackSound(this); + resetTimerSlightly(); + if (!getWorld().isClientSide) + notifyRedstoneOutputs(); + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + int maxAmount = 100; + return new ValueSettingsBoard(CreateLang.translate("factory_panel.target_amount") + .component(), maxAmount, 10, + List.of(CreateLang.translate("schedule.condition.threshold.items") + .component(), + CreateLang.translate("schedule.condition.threshold.stacks") + .component()), + new ValueSettingsFormatter(this::formatValue)); + } + + @Override + public MutableComponent getLabel() { + String key = ""; + + if (!targetedBy.isEmpty() && count == 0) + return CreateLang.translate("gui.factory_panel.no_target_amount_set") + .style(ChatFormatting.RED) + .component(); + + if (isMissingAddress()) + return CreateLang.translate("gui.factory_panel.address_missing") + .style(ChatFormatting.RED) + .component(); + + if (getFilter().isEmpty()) + key = "factory_panel.new_factory_task"; + else if (waitingForNetwork) + key = "factory_panel.some_links_unloaded"; + else if (getAmount() == 0 || targetedBy.isEmpty()) + return getFilter().getHoverName() + .plainCopy(); + else { + key = getFilter().getHoverName() + .getString(); + if (redstonePowered) + key += " " + CreateLang.translate("factory_panel.redstone_paused") + .string(); + else if (!satisfied) + key += " " + CreateLang.translate("factory_panel.in_progress") + .string(); + return CreateLang.text(key) + .component(); + } + + return CreateLang.translate(key) + .component(); + } + + @Override + public ValueSettings getValueSettings() { + return new ValueSettings(upTo ? 0 : 1, count); + } + + @Override + public MutableComponent getTip() { + return CreateLang + .translateDirect(filter.isEmpty() ? "logistics.filter.click_to_set" : "factory_panel.click_to_configure"); + } + + public MutableComponent getAmountTip() { + return CreateLang.translateDirect("factory_panel.hold_to_set_amount"); + } + + @Override + public MutableComponent getCountLabelForValueBox() { + if (filter.isEmpty()) + return Component.empty(); + if (waitingForNetwork) { + return Component.literal("?"); + } + + int levelInStorage = getLevelInStorage(); + boolean inf = levelInStorage >= BigItemStack.INF; + int inStorage = levelInStorage / (upTo ? 1 : getFilter().getMaxStackSize()); + int promised = getPromised(); + String stacks = upTo ? "" : "\u25A4"; + + if (count == 0) { + return CreateLang.text(inf ? " \u221e" : inStorage + stacks) + .color(0xF1EFE8) + .component(); + } + + return CreateLang.text(inf ? " \u221e" : " " + inStorage + stacks) + .color(satisfied ? 0xD7FFA8 : promisedSatisfied ? 0xffcd75 : 0xFFBFA8) + .add(CreateLang.text(promised == 0 ? "" : "\u23F6")) + .add(CreateLang.text("/") + .style(ChatFormatting.WHITE)) + .add(CreateLang.text(count + stacks + " ") + .color(0xF1EFE8)) + .component(); + } + + @Override + public int netId() { + return 2 + slot.ordinal(); + } + + @Override + public boolean isCountVisible() { + return !getFilter().isEmpty(); + } + + @Override + public BehaviourType getType() { + return getTypeForSlot(slot); + } + + public static BehaviourType getTypeForSlot(PanelSlot slot) { + return switch (slot) { + case BOTTOM_LEFT -> BOTTOM_LEFT; + case TOP_LEFT -> TOP_LEFT; + case TOP_RIGHT -> TOP_RIGHT; + case BOTTOM_RIGHT -> BOTTOM_RIGHT; + }; + } + + @OnlyIn(value = Dist.CLIENT) + public void displayScreen(Player player) { + if (player instanceof LocalPlayer) + ScreenOpener.open(new FactoryPanelScreen(this)); + } + + public int getIngredientStatusColor() { + return count == 0 || isMissingAddress() || redstonePowered ? 0x888898 + : waitingForNetwork ? 0x5B3B3B : satisfied ? 0x9EFF7F : promisedSatisfied ? 0x22AFAF : 0x3D6EBD; + } + + @Override + public ItemRequirement getRequiredItems() { + return isActive() ? new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, AllBlocks.FACTORY_GAUGE.asItem()) + : ItemRequirement.NONE; + } + + @Override + public boolean canShortInteract(ItemStack toApply) { + return true; + } + + @Override + public boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate) { + return false; + } + + @Override + public boolean writeToClipboard(CompoundTag tag, Direction side) { + return false; + } + + private void tickOutline() { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> LogisticallyLinkedClientHandler.tickPanel(this)); + } + + @Override + public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + return FactoryPanelSetItemMenu.create(containerId, playerInventory, this); + } + + @Override + public Component getDisplayName() { + return blockEntity.getBlockState() + .getBlock() + .getName(); + } + + public String getFrogAddress() { + PackagerBlockEntity packager = panelBE().getRestockedPackager(); + if (packager == null) + return null; + if (packager.getLevel().getBlockEntity(packager.getBlockPos().above()) instanceof FrogportBlockEntity fpbe) + if (fpbe.addressFilter != null && !fpbe.addressFilter.isBlank()) + return fpbe.addressFilter + ""; + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlock.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlock.java new file mode 100644 index 0000000000..dbcd2f78d7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlock.java @@ -0,0 +1,385 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.UUID; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBlockItem; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.EntityCollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.level.BlockEvent; + +public class FactoryPanelBlock extends FaceAttachedHorizontalDirectionalBlock + implements ProperWaterloggedBlock, IBE, IWrenchable, SpecialBlockItemRequirement { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public static enum PanelSlot { + TOP_LEFT(1, 1), TOP_RIGHT(0, 1), BOTTOM_LEFT(1, 0), BOTTOM_RIGHT(0, 0); + + public int xOffset; + public int yOffset; + + private PanelSlot(int xOffset, int yOffset) { + this.xOffset = xOffset; + this.yOffset = yOffset; + } + } + + public static enum PanelState { + PASSIVE, ACTIVE + } + + public static enum PanelType { + NETWORK, PACKAGER + } + + public FactoryPanelBlock(Properties p_53182_) { + super(p_53182_); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false) + .setValue(POWERED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(FACE, FACING, WATERLOGGED, POWERED)); + } + + @Override + public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { + return canAttachLenient(pLevel, pPos, getConnectedDirection(pState).getOpposite()); + } + + public static boolean canAttachLenient(LevelReader pReader, BlockPos pPos, Direction pDirection) { + BlockPos blockpos = pPos.relative(pDirection); + return !pReader.getBlockState(blockpos) + .getCollisionShape(pReader, blockpos) + .isEmpty(); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + BlockState stateForPlacement = super.getStateForPlacement(pContext); + if (stateForPlacement == null) + return null; + if (stateForPlacement.getValue(FACE) == AttachFace.FLOOR) + stateForPlacement = stateForPlacement.setValue(FACING, stateForPlacement.getValue(FACING) + .getOpposite()); + + Level level = pContext.getLevel(); + BlockPos pos = pContext.getClickedPos(); + BlockState blockState = level.getBlockState(pos); + FactoryPanelBlockEntity fpbe = getBlockEntity(level, pos); + + Vec3 location = pContext.getClickLocation(); + if (blockState.is(this) && location != null && fpbe != null) { + if (!level.isClientSide()) { + PanelSlot targetedSlot = getTargetedSlot(pos, blockState, location); + UUID networkFromStack = LogisticallyLinkedBlockItem.networkFromStack(pContext.getItemInHand()); + Player pPlayer = pContext.getPlayer(); + + if (fpbe.addPanel(targetedSlot, networkFromStack) && pPlayer != null) { + pPlayer.displayClientMessage(CreateLang.translateDirect("logistically_linked.connected"), true); + + if (!pPlayer.isCreative()) { + ItemStack item = pContext.getItemInHand(); + item.shrink(1); + if (item.isEmpty()) + pPlayer.setItemInHand(pContext.getHand(), ItemStack.EMPTY); + } + } + } + stateForPlacement = blockState; + } + + return withWater(stateForPlacement, pContext); + } + + @Override + public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { + Level world = context.getLevel(); + BlockPos pos = context.getClickedPos(); + Player player = context.getPlayer(); + PanelSlot slot = getTargetedSlot(pos, state, context.getClickLocation()); + + if (!(world instanceof ServerLevel)) + return InteractionResult.SUCCESS; + + return onBlockEntityUse(world, pos, be -> { + FactoryPanelBehaviour behaviour = be.panels.get(slot); + if (behaviour == null || !behaviour.isActive()) + return InteractionResult.SUCCESS; + + BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, world.getBlockState(pos), player); + MinecraftForge.EVENT_BUS.post(event); + if (event.isCanceled()) + return InteractionResult.SUCCESS; + + if (!be.removePanel(slot)) + return InteractionResult.SUCCESS; + + if (!player.isCreative()) + player.getInventory() + .placeItemBackInInventory(AllBlocks.FACTORY_GAUGE.asStack()); + + IWrenchable.playRemoveSound(world, pos); + if (be.activePanels() == 0) + world.destroyBlock(pos, false); + + return InteractionResult.SUCCESS; + }); + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + if (pPlacer == null) + return; + AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); + double range = pPlacer.getAttribute(ForgeMod.BLOCK_REACH.get()) + .getValue() + 1; + HitResult hitResult = pPlacer.pick(range, 1, false); + Vec3 location = hitResult.getLocation(); + if (location == null) + return; + PanelSlot initialSlot = getTargetedSlot(pPos, pState, location); + withBlockEntityDo(pLevel, pPos, + fpbe -> fpbe.addPanel(initialSlot, LogisticallyLinkedBlockItem.networkFromStack(pStack))); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + if (pPlayer == null) + return InteractionResult.PASS; + ItemStack item = pPlayer.getItemInHand(pHand); + if (pLevel.isClientSide) + return InteractionResult.SUCCESS; + if (!AllBlocks.FACTORY_GAUGE.isIn(item)) + return InteractionResult.SUCCESS; + Vec3 location = pHit.getLocation(); + if (location == null) + return InteractionResult.SUCCESS; + + if (!FactoryPanelBlockItem.isTuned(item)) { + AllSoundEvents.DENY.playOnServer(pLevel, pPos); + pPlayer.displayClientMessage(CreateLang.translate("factory_panel.tune_before_placing") + .component(), true); + return InteractionResult.FAIL; + } + + PanelSlot newSlot = getTargetedSlot(pPos, pState, location); + withBlockEntityDo(pLevel, pPos, fpbe -> { + if (!fpbe.addPanel(newSlot, LogisticallyLinkedBlockItem.networkFromStack(item))) + return; + pPlayer.displayClientMessage(CreateLang.translateDirect("logistically_linked.connected"), true); + pLevel.playSound(null, pPos, soundType.getPlaceSound(), SoundSource.BLOCKS); + if (pPlayer.isCreative()) + return; + item.shrink(1); + if (item.isEmpty()) + pPlayer.setItemInHand(pHand, ItemStack.EMPTY); + }); + return InteractionResult.SUCCESS; + } + + @Override + public boolean onDestroyedByPlayer(BlockState state, Level level, BlockPos pos, Player player, boolean willHarvest, + FluidState fluid) { + if (tryDestroySubPanelFirst(state, level, pos, player)) + return false; + boolean result = super.onDestroyedByPlayer(state, level, pos, player, willHarvest, fluid); + return result; + } + + private boolean tryDestroySubPanelFirst(BlockState state, Level level, BlockPos pos, Player player) { + double range = player.getAttribute(ForgeMod.BLOCK_REACH.get()) + .getValue() + 1; + HitResult hitResult = player.pick(range, 1, false); + Vec3 location = hitResult.getLocation(); + PanelSlot destroyedSlot = getTargetedSlot(pos, state, location); + return InteractionResult.SUCCESS == onBlockEntityUse(level, pos, fpbe -> { + if (fpbe.activePanels() < 2) + return InteractionResult.FAIL; + if (!fpbe.removePanel(destroyedSlot)) + return InteractionResult.FAIL; + if (!player.isCreative()) + popResource(level, pos, AllBlocks.FACTORY_GAUGE.asStack()); + return InteractionResult.SUCCESS; + }); + } + + @Override + public boolean isSignalSource(BlockState pState) { + return true; + } + + @Override + public int getSignal(BlockState pBlockState, BlockGetter pBlockAccess, BlockPos pPos, Direction pSide) { + return pBlockState.getValue(POWERED) ? 15 : 0; + } + + @Override + public int getDirectSignal(BlockState pBlockState, BlockGetter pBlockAccess, BlockPos pPos, Direction pSide) { + return pBlockState.getValue(POWERED) && getConnectedDirection(pBlockState) == pSide ? 15 : 0; + } + + @Override + public boolean canBeReplaced(BlockState pState, BlockPlaceContext pUseContext) { + if (pUseContext.isSecondaryUseActive()) + return false; + if (!AllBlocks.FACTORY_GAUGE.isIn(pUseContext.getItemInHand())) + return false; + Vec3 location = pUseContext.getClickLocation(); + if (location == null) + return false; + + BlockPos pos = pUseContext.getClickedPos(); + PanelSlot slot = getTargetedSlot(pos, pState, location); + FactoryPanelBlockEntity blockEntity = getBlockEntity(pUseContext.getLevel(), pos); + + if (blockEntity == null) + return false; + if (blockEntity.panels.get(slot) + .isActive()) + return false; + return true; + } + + @Override + public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, + CollisionContext pContext) { + if (pContext instanceof EntityCollisionContext ecc && ecc.getEntity() == null) + return getShape(pState, pLevel, pPos, pContext); + return Shapes.empty(); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + FactoryPanelBlockEntity blockEntity = getBlockEntity(pLevel, pPos); + if (blockEntity != null) + return blockEntity.getShape(); + return AllShapes.FACTORY_PANEL_FALLBACK.get(getConnectedDirection(pState)); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, + BlockPos pCurrentPos, BlockPos pFacingPos) { + updateWater(pLevel, pState, pCurrentPos); + return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + public static Direction connectedDirection(BlockState state) { + return getConnectedDirection(state); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + public static PanelSlot getTargetedSlot(BlockPos pos, BlockState blockState, Vec3 clickLocation) { + double bestDistance = Double.MAX_VALUE; + PanelSlot bestSlot = PanelSlot.BOTTOM_LEFT; + Vec3 localClick = clickLocation.subtract(Vec3.atLowerCornerOf(pos)); + float xRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getXRot(blockState); + float yRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getYRot(blockState); + + for (PanelSlot slot : PanelSlot.values()) { + Vec3 vec = new Vec3(.25 + slot.xOffset * .5, 0, .25 + slot.yOffset * .5); + vec = VecHelper.rotateCentered(vec, 180, Axis.Y); + vec = VecHelper.rotateCentered(vec, xRot + 90, Axis.X); + vec = VecHelper.rotateCentered(vec, yRot, Axis.Y); + + double diff = vec.distanceToSqr(localClick); + if (diff > bestDistance) + continue; + bestDistance = diff; + bestSlot = slot; + } + + return bestSlot; + } + + @Override + public Class getBlockEntityClass() { + return FactoryPanelBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.FACTORY_PANEL.get(); + } + + public static float getXRot(BlockState state) { + AttachFace face = state.getOptionalValue(FactoryPanelBlock.FACE) + .orElse(AttachFace.FLOOR); + return face == AttachFace.CEILING ? Mth.PI / 2 : face == AttachFace.FLOOR ? -Mth.PI / 2 : 0; + } + + public static float getYRot(BlockState state) { + Direction facing = state.getOptionalValue(FactoryPanelBlock.FACING) + .orElse(Direction.SOUTH); + AttachFace face = state.getOptionalValue(FactoryPanelBlock.FACE) + .orElse(AttachFace.FLOOR); + return (face == AttachFace.CEILING ? Mth.PI : 0) + AngleHelper.rad(AngleHelper.horizontalAngle(facing)); + } + + @Override + public ItemRequirement getRequiredItems(BlockState state, BlockEntity blockEntity) { + return ItemRequirement.NONE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlockEntity.java new file mode 100644 index 0000000000..64a5249ac8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlockEntity.java @@ -0,0 +1,217 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.EnumMap; +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; +import com.simibubi.create.content.logistics.packager.repackager.RepackagerBlockEntity; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class FactoryPanelBlockEntity extends SmartBlockEntity { + + public EnumMap panels; + + public boolean redraw; + public boolean restocker; + public VoxelShape lastShape; + + public AdvancementBehaviour advancements; + + public FactoryPanelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + restocker = false; + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).inflate(8); + } + + @Override + public void addBehaviours(List behaviours) { + panels = new EnumMap<>(PanelSlot.class); + redraw = true; + for (PanelSlot slot : PanelSlot.values()) { + FactoryPanelBehaviour e = new FactoryPanelBehaviour(this, slot); + panels.put(slot, e); + behaviours.add(e); + } + + behaviours.add(advancements = new AdvancementBehaviour(this, AllAdvancements.FACTORY_GAUGE)); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide()) + return; + + if (activePanels() == 0) + level.setBlockAndUpdate(worldPosition, Blocks.AIR.defaultBlockState()); + + if (AllBlocks.FACTORY_GAUGE.has(getBlockState())) { + boolean shouldBeRestocker = AllBlocks.PACKAGER + .has(level.getBlockState(worldPosition.relative(FactoryPanelBlock.connectedDirection(getBlockState()) + .getOpposite()))); + if (restocker == shouldBeRestocker) + return; + restocker = shouldBeRestocker; + redraw = true; + sendData(); + } + } + + @Nullable + public PackagerBlockEntity getRestockedPackager() { + BlockState state = getBlockState(); + if (!restocker || !AllBlocks.FACTORY_GAUGE.has(state)) + return null; + BlockPos packagerPos = worldPosition.relative(FactoryPanelBlock.connectedDirection(state) + .getOpposite()); + if (!level.isLoaded(packagerPos)) + return null; + BlockEntity be = level.getBlockEntity(packagerPos); + if (be == null || !(be instanceof PackagerBlockEntity pbe)) + return null; + if (pbe instanceof RepackagerBlockEntity) + return null; + return pbe; + } + + public int activePanels() { + int result = 0; + for (FactoryPanelBehaviour panelBehaviour : panels.values()) + if (panelBehaviour.isActive()) + result++; + return result; + } + + @Override + public void remove() { + for (FactoryPanelBehaviour panelBehaviour : panels.values()) + if (panelBehaviour.isActive()) + panelBehaviour.disconnectAll(); + super.remove(); + } + + @Override + public void destroy() { + super.destroy(); + int panelCount = activePanels(); + if (panelCount > 1) + Block.popResource(level, worldPosition, AllBlocks.FACTORY_GAUGE.asStack(panelCount - 1)); + } + + public boolean addPanel(PanelSlot slot, UUID frequency) { + FactoryPanelBehaviour behaviour = panels.get(slot); + if (behaviour != null && !behaviour.isActive()) { + behaviour.enable(); + behaviour.setNetwork(frequency); + redraw = true; + lastShape = null; + + if (activePanels() > 1) { + SoundType soundType = getBlockState().getSoundType(); + level.playSound(null, worldPosition, soundType.getPlaceSound(), SoundSource.BLOCKS, + (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F); + } + + return true; + } + return false; + } + + public boolean removePanel(PanelSlot slot) { + FactoryPanelBehaviour behaviour = panels.get(slot); + if (behaviour != null && behaviour.isActive()) { + behaviour.disable(); + redraw = true; + lastShape = null; + + if (activePanels() > 0) { + SoundType soundType = getBlockState().getSoundType(); + level.playSound(null, worldPosition, soundType.getBreakSound(), SoundSource.BLOCKS, + (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F); + } + + return true; + } + return false; + } + + public VoxelShape getShape() { + if (lastShape != null) + return lastShape; + + float xRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getXRot(getBlockState()) + 90; + float yRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getYRot(getBlockState()); + Direction connectedDirection = FactoryPanelBlock.connectedDirection(getBlockState()); + Vec3 inflateAxes = VecHelper.axisAlingedPlaneOf(connectedDirection); + + lastShape = Shapes.empty(); + + for (FactoryPanelBehaviour behaviour : panels.values()) { + if (!behaviour.isActive()) + continue; + FactoryPanelPosition panelPosition = behaviour.getPanelPosition(); + Vec3 vec = + new Vec3(.25 + panelPosition.slot().xOffset * .5, 1 / 16f, .25 + panelPosition.slot().yOffset * .5); + vec = VecHelper.rotateCentered(vec, 180, Axis.Y); + vec = VecHelper.rotateCentered(vec, xRot, Axis.X); + vec = VecHelper.rotateCentered(vec, yRot, Axis.Y); + AABB bb = new AABB(vec, vec).inflate(1 / 16f) + .inflate(inflateAxes.x * 3 / 16f, inflateAxes.y * 3 / 16f, inflateAxes.z * 3 / 16f); + lastShape = Shapes.or(lastShape, Shapes.create(bb)); + } + + return lastShape; + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + restocker = tag.getBoolean("Restocker"); + if (clientPacket && tag.contains("Redraw")) { + lastShape = null; + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); + } + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.putBoolean("Restocker", restocker); + if (clientPacket && redraw) { + NBTHelper.putMarker(tag, "Redraw"); + redraw = false; + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlockItem.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlockItem.java new file mode 100644 index 0000000000..83277f542a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBlockItem.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBlockItem; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; + +public class FactoryPanelBlockItem extends LogisticallyLinkedBlockItem { + + public FactoryPanelBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public InteractionResult place(BlockPlaceContext pContext) { + ItemStack stack = pContext.getItemInHand(); + + if (!isTuned(stack)) { + AllSoundEvents.DENY.playOnServer(pContext.getLevel(), pContext.getClickedPos()); + pContext.getPlayer() + .displayClientMessage(CreateLang.translate("factory_panel.tune_before_placing") + .component(), true); + return InteractionResult.FAIL; + } + + return super.place(pContext); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConfigurationPacket.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConfigurationPacket.java new file mode 100644 index 0000000000..5ec94a67fd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConfigurationPacket.java @@ -0,0 +1,143 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; + +public class FactoryPanelConfigurationPacket extends BlockEntityConfigurationPacket { + + private PanelSlot slot; + private String address; + private Map inputAmounts; + private List craftingArrangement; + private int outputAmount; + private int promiseClearingInterval; + private FactoryPanelPosition removeConnection; + private boolean clearPromises; + private boolean reset; + private boolean redstoneReset; + + public FactoryPanelConfigurationPacket(FactoryPanelPosition position, String address, + Map inputAmounts, List craftingArrangement, int outputAmount, + int promiseClearingInterval, @Nullable FactoryPanelPosition removeConnection, boolean clearPromises, + boolean reset, boolean sendRedstoneReset) { + super(position.pos()); + this.address = address; + this.inputAmounts = inputAmounts; + this.craftingArrangement = craftingArrangement; + this.outputAmount = outputAmount; + this.promiseClearingInterval = promiseClearingInterval; + this.removeConnection = removeConnection; + this.clearPromises = clearPromises; + this.reset = reset; + this.redstoneReset = sendRedstoneReset; + this.slot = position.slot(); + } + + public FactoryPanelConfigurationPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeVarInt(slot.ordinal()); + buffer.writeUtf(address); + buffer.writeVarInt(inputAmounts.size()); + for (Entry entry : inputAmounts.entrySet()) { + entry.getKey() + .send(buffer); + buffer.writeVarInt(entry.getValue()); + } + buffer.writeVarInt(craftingArrangement.size()); + craftingArrangement.forEach(buffer::writeItem); + buffer.writeVarInt(outputAmount); + buffer.writeVarInt(promiseClearingInterval); + buffer.writeBoolean(removeConnection != null); + if (removeConnection != null) + removeConnection.send(buffer); + buffer.writeBoolean(clearPromises); + buffer.writeBoolean(reset); + buffer.writeBoolean(redstoneReset); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + slot = PanelSlot.values()[buffer.readVarInt()]; + address = buffer.readUtf(); + inputAmounts = new HashMap<>(); + int entries = buffer.readVarInt(); + for (int i = 0; i < entries; i++) + inputAmounts.put(FactoryPanelPosition.receive(buffer), buffer.readVarInt()); + int craftEntries = buffer.readVarInt(); + craftingArrangement = new ArrayList<>(); + for (int i = 0; i < craftEntries; i++) + craftingArrangement.add(buffer.readItem()); + outputAmount = buffer.readVarInt(); + promiseClearingInterval = buffer.readVarInt(); + if (buffer.readBoolean()) + removeConnection = FactoryPanelPosition.receive(buffer); + clearPromises = buffer.readBoolean(); + reset = buffer.readBoolean(); + redstoneReset = buffer.readBoolean(); + } + + @Override + protected void applySettings(FactoryPanelBlockEntity be) { + FactoryPanelBehaviour behaviour = be.panels.get(slot); + if (behaviour == null) + return; + + behaviour.recipeAddress = reset ? "" : address; + behaviour.recipeOutput = reset ? 1 : outputAmount; + behaviour.promiseClearingInterval = reset ? -1 : promiseClearingInterval; + behaviour.activeCraftingArrangement = reset ? List.of() : craftingArrangement; + + if (reset) { + behaviour.forceClearPromises = true; + behaviour.disconnectAll(); + behaviour.setFilter(ItemStack.EMPTY); + behaviour.count = 0; + be.redraw = true; + be.notifyUpdate(); + return; + } + + if (redstoneReset) { + behaviour.disconnectAllLinks(); + be.notifyUpdate(); + return; + } + + for (Entry entry : inputAmounts.entrySet()) { + FactoryPanelPosition key = entry.getKey(); + FactoryPanelConnection connection = behaviour.targetedBy.get(key); + if (connection != null) + connection.amount = entry.getValue(); + } + + if (removeConnection != null) { + behaviour.targetedBy.remove(removeConnection); + FactoryPanelBehaviour source = FactoryPanelBehaviour.at(be.getLevel(), removeConnection); + if (source != null) { + source.targeting.remove(behaviour.getPanelPosition()); + source.blockEntity.sendData(); + } + } + + if (clearPromises) + behaviour.forceClearPromises = true; + + be.notifyUpdate(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnection.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnection.java new file mode 100644 index 0000000000..d520936b38 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnection.java @@ -0,0 +1,159 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class FactoryPanelConnection { + + public FactoryPanelPosition from; + public int amount; + public List path; + public int arrowBendMode; + public boolean success; + + public WeakReference cachedSource; + + private int arrowBendModeCurrentPathUses; + + public FactoryPanelConnection(FactoryPanelPosition from, int amount) { + this.from = from; + this.amount = amount; + path = new ArrayList<>(); + success = true; + arrowBendMode = -1; + arrowBendModeCurrentPathUses = 0; + cachedSource = new WeakReference<>(null); + } + + public static FactoryPanelConnection read(CompoundTag nbt) { + FactoryPanelConnection connection = + new FactoryPanelConnection(FactoryPanelPosition.read(nbt), nbt.getInt("Amount")); + connection.arrowBendMode = nbt.getInt("ArrowBending"); + return connection; + } + + public CompoundTag write() { + CompoundTag nbt = from.write(); + nbt.putInt("Amount", amount); + nbt.putInt("ArrowBending", arrowBendMode); + return nbt; + } + + public List getPath(Level level, BlockState state, FactoryPanelPosition to) { + if (!path.isEmpty() && arrowBendModeCurrentPathUses == arrowBendMode) + return path; + + boolean findSuitable = arrowBendMode == -1; + arrowBendModeCurrentPathUses = arrowBendMode; + + FactoryPanelBehaviour fromBehaviour = FactoryPanelBehaviour.at(level, to); + final Vec3 diff = calculatePathDiff(state, to); + final Vec3 start = fromBehaviour != null ? fromBehaviour.getSlotPositioning() + .getLocalOffset(level, to.pos(), state) + .add(Vec3.atLowerCornerOf(to.pos())) : Vec3.ZERO; + final float xRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getXRot(state); + final float yRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getYRot(state); + + // When mode is not locked, find one that doesnt intersect with other gauges + ModeFinder: + for (int actualMode = 0; actualMode <= 4; actualMode++) { + path.clear(); + if (!findSuitable && actualMode != arrowBendMode) + continue; + boolean desperateOption = actualMode == 4; + + BlockPos toTravelFirst = BlockPos.ZERO; + BlockPos toTravelLast = BlockPos.containing(diff.scale(2) + .add(0.1, 0.1, 0.1)); + + if (actualMode > 1) { + boolean flipX = diff.x > 0 ^ (actualMode % 2 == 1); + boolean flipZ = diff.z > 0 ^ (actualMode % 2 == 0); + int ceilX = Mth.positiveCeilDiv(toTravelLast.getX(), 2); + int ceilZ = Mth.positiveCeilDiv(toTravelLast.getZ(), 2); + int floorZ = Mth.floorDiv(toTravelLast.getZ(), 2); + int floorX = Mth.floorDiv(toTravelLast.getX(), 2); + toTravelFirst = new BlockPos(flipX ? floorX : ceilX, 0, flipZ ? floorZ : ceilZ); + toTravelLast = new BlockPos(!flipX ? floorX : ceilX, 0, !flipZ ? floorZ : ceilZ); + } + + Direction lastDirection = null; + Direction currentDirection = null; + + for (BlockPos toTravel : List.of(toTravelFirst, toTravelLast)) { + boolean zIsFarther = Math.abs(toTravel.getZ()) > Math.abs(toTravel.getX()); + boolean zIsPreferred = desperateOption ? zIsFarther : actualMode % 2 == 1; + List directionOrder = + zIsPreferred ? List.of(Direction.SOUTH, Direction.NORTH, Direction.WEST, Direction.EAST) + : List.of(Direction.WEST, Direction.EAST, Direction.SOUTH, Direction.NORTH); + + for (int i = 0; i < 100; i++) { + if (toTravel.equals(BlockPos.ZERO)) + break; + + for (Direction d : directionOrder) { + if (lastDirection != null && d == lastDirection.getOpposite()) + continue; + if (currentDirection == null || toTravel.relative(d) + .distManhattan(BlockPos.ZERO) < toTravel.relative(currentDirection) + .distManhattan(BlockPos.ZERO)) + currentDirection = d; + } + + lastDirection = currentDirection; + toTravel = toTravel.relative(currentDirection); + path.add(currentDirection); + } + } + + if (findSuitable && !desperateOption) { + BlockPos travelled = BlockPos.ZERO; + for (int i = 0; i < path.size() - 1; i++) { + Direction d = path.get(i); + travelled = travelled.relative(d); + Vec3 testOffset = Vec3.atLowerCornerOf(travelled) + .scale(0.5); + testOffset = VecHelper.rotate(testOffset, 180, Axis.Y); + testOffset = VecHelper.rotate(testOffset, xRot + 90, Axis.X); + testOffset = VecHelper.rotate(testOffset, yRot, Axis.Y); + Vec3 v = start.add(testOffset); + if (!level.noCollision(new AABB(v, v).inflate(1 / 128f))) + continue ModeFinder; + } + } + + break; + } + + return path; + } + + public Vec3 calculatePathDiff(BlockState state, FactoryPanelPosition to) { + float xRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getXRot(state); + float yRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getYRot(state); + int slotDiffx = to.slot().xOffset - from.slot().xOffset; + int slotDiffY = to.slot().yOffset - from.slot().yOffset; + + Vec3 diff = Vec3.atLowerCornerOf(to.pos() + .subtract(from.pos())); + diff = VecHelper.rotate(diff, -yRot, Axis.Y); + diff = VecHelper.rotate(diff, -xRot - 90, Axis.X); + diff = VecHelper.rotate(diff, -180, Axis.Y); + diff = diff.add(slotDiffx * .5, 0, slotDiffY * .5); + diff = diff.multiply(1, 0, 1); + return diff; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionHandler.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionHandler.java new file mode 100644 index 0000000000..da1b23bb71 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionHandler.java @@ -0,0 +1,319 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult.Type; +import net.minecraft.world.phys.Vec3; + +public class FactoryPanelConnectionHandler { + + static FactoryPanelPosition connectingFrom; + static AABB connectingFromBox; + + static boolean relocating; + static FactoryPanelPosition validRelocationTarget; + + public static boolean panelClicked(LevelAccessor level, Player player, FactoryPanelBehaviour panel) { + if (connectingFrom == null) + return false; + + FactoryPanelBehaviour at = FactoryPanelBehaviour.at(level, connectingFrom); + if (panel.getPanelPosition() + .equals(connectingFrom) || at == null) { + player.displayClientMessage(Component.empty(), true); + connectingFrom = null; + connectingFromBox = null; + return true; + } + + String checkForIssues = checkForIssues(at, panel); + if (checkForIssues != null) { + player.displayClientMessage(CreateLang.translate(checkForIssues) + .style(ChatFormatting.RED) + .component(), true); + connectingFrom = null; + connectingFromBox = null; + AllSoundEvents.DENY.playAt(player.level(), player.blockPosition(), 1, 1, false); + return true; + } + + ItemStack filterFrom = panel.getFilter(); + ItemStack filterTo = at.getFilter(); + + AllPackets.getChannel() + .sendToServer(new FactoryPanelConnectionPacket(panel.getPanelPosition(), connectingFrom, false)); + + player.displayClientMessage(CreateLang.translate("factory_panel.panels_connected", filterFrom.getHoverName() + .getString(), + filterTo.getHoverName() + .getString()) + .style(ChatFormatting.GREEN) + .component(), true); + + connectingFrom = null; + connectingFromBox = null; + player.level() + .playLocalSound(player.blockPosition(), SoundEvents.AMETHYST_BLOCK_PLACE, SoundSource.BLOCKS, 0.5f, 0.5f, + false); + + return true; + } + + @Nullable + private static String checkForIssues(FactoryPanelBehaviour from, FactoryPanelBehaviour to) { + if (from == null) + return "factory_panel.connection_aborted"; + if (from.targetedBy.containsKey(to.getPanelPosition())) + return "factory_panel.already_connected"; + if (from.targetedBy.size() >= 9) + return "factory_panel.cannot_add_more_inputs"; + + BlockState state1 = to.blockEntity.getBlockState(); + BlockState state2 = from.blockEntity.getBlockState(); + BlockPos diff = to.getPos() + .subtract(from.getPos()); + + if (state1.setValue(FactoryPanelBlock.WATERLOGGED, false) + .setValue(FactoryPanelBlock.POWERED, false) != state2.setValue(FactoryPanelBlock.WATERLOGGED, false) + .setValue(FactoryPanelBlock.POWERED, false)) + return "factory_panel.same_orientation"; + + if (FactoryPanelBlock.connectedDirection(state1) + .getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + return "factory_panel.same_surface"; + + if (!diff.closerThan(BlockPos.ZERO, 16)) + return "factory_panel.too_far_apart"; + + if (to.panelBE().restocker) + return "factory_panel.input_in_restock_mode"; + + if (to.getFilter() + .isEmpty() + || from.getFilter() + .isEmpty()) + return "factory_panel.no_item"; + + return null; + } + + @Nullable + private static String checkForIssues(FactoryPanelBehaviour from, FactoryPanelSupportBehaviour to) { + if (from == null) + return "factory_panel.connection_aborted"; + + BlockState state1 = from.blockEntity.getBlockState(); + BlockState state2 = to.blockEntity.getBlockState(); + BlockPos diff = to.getPos() + .subtract(from.getPos()); + Direction connectedDirection = FactoryPanelBlock.connectedDirection(state1); + + if (connectedDirection != state2.getOptionalValue(WrenchableDirectionalBlock.FACING) + .orElse(connectedDirection)) + return "factory_panel.same_orientation"; + + if (connectedDirection.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + return "factory_panel.same_surface"; + + if (!diff.closerThan(BlockPos.ZERO, 16)) + return "factory_panel.too_far_apart"; + + return null; + } + + public static void clientTick() { + if (connectingFrom == null || connectingFromBox == null) + return; + + Minecraft mc = Minecraft.getInstance(); + FactoryPanelBehaviour at = FactoryPanelBehaviour.at(mc.level, connectingFrom); + + if (!connectingFrom.pos() + .closerThan(mc.player.blockPosition(), 16) || at == null) { + connectingFrom = null; + connectingFromBox = null; + mc.player.displayClientMessage(Component.empty(), true); + return; + } + + Outliner.getInstance() + .showAABB(connectingFrom, connectingFromBox) + .colored(AnimationTickHolder.getTicks() % 16 > 8 ? 0x38b764 : 0xa7f070) + .lineWidth(1 / 16f); + + mc.player.displayClientMessage( + CreateLang.translate(relocating ? "factory_panel.click_to_relocate" : "factory_panel.click_second_panel") + .component(), + true); + + if (!relocating) + return; + + validRelocationTarget = null; + + if (!(mc.hitResult instanceof BlockHitResult bhr) || bhr.getType() == Type.MISS) + return; + + Vec3 offsetPos = bhr.getLocation() + .add(Vec3.atLowerCornerOf(bhr.getDirection() + .getNormal()) + .scale(1 / 32f)); + BlockPos pos = BlockPos.containing(offsetPos); + BlockState blockState = at.blockEntity.getBlockState(); + PanelSlot slot = FactoryPanelBlock.getTargetedSlot(pos, blockState, offsetPos); + BlockPos diff = pos.subtract(connectingFrom.pos()); + Direction facing = FactoryPanelBlock.connectedDirection(blockState); + + if (facing.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + return; + if (!AllBlocks.FACTORY_GAUGE.get() + .canSurvive(blockState, mc.level, pos)) + return; + if (AllBlocks.PACKAGER.has(mc.level.getBlockState(pos.relative(facing.getOpposite())))) + return; + + validRelocationTarget = new FactoryPanelPosition(pos, slot); + + Outliner.getInstance() + .showAABB("target", getBB(blockState, validRelocationTarget)) + .colored(0xeeeeee) + .disableLineNormals() + .lineWidth(1 / 16f); + } + + public static boolean onRightClick() { + if (connectingFrom == null || connectingFromBox == null) + return false; + Minecraft mc = Minecraft.getInstance(); + boolean missed = false; + + if (relocating) { + if (mc.player.isShiftKeyDown()) + validRelocationTarget = null; + if (validRelocationTarget != null) + AllPackets.getChannel() + .sendToServer(new FactoryPanelConnectionPacket(validRelocationTarget, connectingFrom, true)); + + connectingFrom = null; + connectingFromBox = null; + + if (validRelocationTarget == null) + mc.player.displayClientMessage(CreateLang.translate("factory_panel.relocation_aborted") + .component(), true); + + relocating = false; + validRelocationTarget = null; + return true; + } + + if (mc.hitResult instanceof BlockHitResult bhr && bhr.getType() != Type.MISS) { + BlockEntity blockEntity = mc.level.getBlockEntity(bhr.getBlockPos()); + FactoryPanelSupportBehaviour behaviour = + BlockEntityBehaviour.get(mc.level, bhr.getBlockPos(), FactoryPanelSupportBehaviour.TYPE); + + // Connecting redstone or display links + if (behaviour != null) { + FactoryPanelBehaviour at = FactoryPanelBehaviour.at(mc.level, connectingFrom); + String checkForIssues = checkForIssues(at, behaviour); + if (checkForIssues != null) { + mc.player.displayClientMessage(CreateLang.translate(checkForIssues) + .style(ChatFormatting.RED) + .component(), true); + connectingFrom = null; + connectingFromBox = null; + AllSoundEvents.DENY.playAt(mc.level, mc.player.blockPosition(), 1, 1, false); + return true; + } + + FactoryPanelPosition bestPosition = null; + double bestDistance = Double.POSITIVE_INFINITY; + + for (PanelSlot slot : PanelSlot.values()) { + FactoryPanelPosition panelPosition = new FactoryPanelPosition(blockEntity.getBlockPos(), slot); + FactoryPanelConnection connection = new FactoryPanelConnection(panelPosition, 1); + Vec3 diff = + connection.calculatePathDiff(mc.level.getBlockState(connectingFrom.pos()), connectingFrom); + if (bestDistance < diff.lengthSqr()) + continue; + bestDistance = diff.lengthSqr(); + bestPosition = panelPosition; + } + + AllPackets.getChannel() + .sendToServer(new FactoryPanelConnectionPacket(bestPosition, connectingFrom, false)); + + mc.player.displayClientMessage(CreateLang + .translate("factory_panel.link_connected", blockEntity.getBlockState() + .getBlock() + .getName()) + .style(ChatFormatting.GREEN) + .component(), true); + + connectingFrom = null; + connectingFromBox = null; + mc.player.level() + .playLocalSound(mc.player.blockPosition(), SoundEvents.AMETHYST_BLOCK_PLACE, SoundSource.BLOCKS, + 0.5f, 0.5f, false); + return true; + } + + if (!(blockEntity instanceof FactoryPanelBlockEntity)) + missed = true; + } + + if (!mc.player.isShiftKeyDown() && !missed) + return false; + connectingFrom = null; + connectingFromBox = null; + mc.player.displayClientMessage(CreateLang.translate("factory_panel.connection_aborted") + .component(), true); + return true; + } + + public static void startRelocating(FactoryPanelBehaviour behaviour) { + startConnection(behaviour); + relocating = true; + } + + public static void startConnection(FactoryPanelBehaviour behaviour) { + relocating = false; + connectingFrom = behaviour.getPanelPosition(); + connectingFromBox = getBB(behaviour.blockEntity.getBlockState(), connectingFrom); + } + + public static AABB getBB(BlockState blockState, FactoryPanelPosition factoryPanelPosition) { + Vec3 location = FactoryPanelSlotPositioning.getCenterOfSlot(blockState, factoryPanelPosition.slot()) + .add(Vec3.atLowerCornerOf(factoryPanelPosition.pos())); + Vec3 plane = VecHelper.axisAlingedPlaneOf(FactoryPanelBlock.connectedDirection(blockState)); + return new AABB(location, location).inflate(plane.x * 3 / 16f, plane.y * 3 / 16f, plane.z * 3 / 16f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionPacket.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionPacket.java new file mode 100644 index 0000000000..ed5757e4ef --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionPacket.java @@ -0,0 +1,62 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public class FactoryPanelConnectionPacket extends BlockEntityConfigurationPacket { + + private FactoryPanelPosition fromPos; + private FactoryPanelPosition toPos; + private boolean relocate; + + public FactoryPanelConnectionPacket(FactoryPanelPosition fromPos, FactoryPanelPosition toPos, boolean relocate) { + super(toPos.pos()); + this.fromPos = fromPos; + this.toPos = toPos; + this.relocate = relocate; + } + + public FactoryPanelConnectionPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBlockPos(fromPos.pos()); + buffer.writeVarInt(fromPos.slot() + .ordinal()); + buffer.writeBlockPos(toPos.pos()); + buffer.writeVarInt(toPos.slot() + .ordinal()); + buffer.writeBoolean(relocate); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + fromPos = new FactoryPanelPosition(buffer.readBlockPos(), PanelSlot.values()[buffer.readVarInt()]); + toPos = new FactoryPanelPosition(buffer.readBlockPos(), PanelSlot.values()[buffer.readVarInt()]); + relocate = buffer.readBoolean(); + } + + @Override + protected void applySettings(ServerPlayer player, FactoryPanelBlockEntity be) { + FactoryPanelBehaviour behaviour = FactoryPanelBehaviour.at(be.getLevel(), toPos); + if (behaviour != null) + if (relocate) + behaviour.moveTo(fromPos, player); + else + behaviour.addConnection(fromPos); + } + + @Override + protected void applySettings(FactoryPanelBlockEntity be) {} + + @Override + protected int maxRange() { + return super.maxRange() * 2; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelEffectPacket.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelEffectPacket.java new file mode 100644 index 0000000000..fedd42d225 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelEffectPacket.java @@ -0,0 +1,62 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkEvent.Context; + +public class FactoryPanelEffectPacket extends SimplePacketBase { + + private FactoryPanelPosition fromPos; + private FactoryPanelPosition toPos; + private boolean success; + + public FactoryPanelEffectPacket(FactoryPanelPosition fromPos, FactoryPanelPosition toPos, boolean success) { + this.fromPos = fromPos; + this.toPos = toPos; + this.success = success; + } + + public FactoryPanelEffectPacket(FriendlyByteBuf buffer) { + fromPos = new FactoryPanelPosition(buffer.readBlockPos(), PanelSlot.values()[buffer.readVarInt()]); + toPos = new FactoryPanelPosition(buffer.readBlockPos(), PanelSlot.values()[buffer.readVarInt()]); + success = buffer.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(fromPos.pos()); + buffer.writeVarInt(fromPos.slot() + .ordinal()); + buffer.writeBlockPos(toPos.pos()); + buffer.writeVarInt(toPos.slot() + .ordinal()); + buffer.writeBoolean(success); + } + + @Override + @OnlyIn(Dist.CLIENT) + public boolean handle(Context context) { + context.enqueueWork(() -> { + ClientLevel level = Minecraft.getInstance().level; + BlockState blockState = level.getBlockState(fromPos.pos()); + if (!AllBlocks.FACTORY_GAUGE.has(blockState)) + return; + FactoryPanelBehaviour panelBehaviour = FactoryPanelBehaviour.at(level, toPos); + if (panelBehaviour != null) { + panelBehaviour.bulb.setValue(1); + FactoryPanelConnection connection = panelBehaviour.targetedBy.get(fromPos); + if (connection != null) + connection.success = success; + } + }); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelModel.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelModel.java new file mode 100644 index 0000000000..a362f472fc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelModel.java @@ -0,0 +1,125 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelState; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelType; +import com.simibubi.create.foundation.model.BakedModelWrapperWithData; +import com.simibubi.create.foundation.model.BakedQuadHelper; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.math.VecHelper; +import net.createmod.ponder.api.level.PonderLevel; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.client.model.data.ModelData.Builder; +import net.minecraftforge.client.model.data.ModelProperty; + +public class FactoryPanelModel extends BakedModelWrapperWithData { + + private static final ModelProperty PANEL_PROPERTY = new ModelProperty<>(); + + public FactoryPanelModel(BakedModel originalModel) { + super(originalModel); + } + + @Override + protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, + ModelData blockEntityData) { + FactoryPanelModelData data = new FactoryPanelModelData(); + for (PanelSlot slot : PanelSlot.values()) { + FactoryPanelBehaviour behaviour = FactoryPanelBehaviour.at(world, new FactoryPanelPosition(pos, slot)); + if (behaviour == null) + continue; + data.states.put(slot, behaviour.count == 0 ? PanelState.PASSIVE : PanelState.ACTIVE); + data.type = behaviour.panelBE().restocker ? PanelType.PACKAGER : PanelType.NETWORK; + } + data.ponder = world instanceof PonderLevel; + return builder.with(PANEL_PROPERTY, data); + } + + @Override + public List getQuads(BlockState state, Direction side, RandomSource rand, ModelData data, + RenderType renderType) { + if (side != null || !data.has(PANEL_PROPERTY)) + return Collections.emptyList(); + FactoryPanelModelData modelData = data.get(PANEL_PROPERTY); + List quads = new ArrayList<>(super.getQuads(state, null, rand, data, renderType)); + for (PanelSlot panelSlot : PanelSlot.values()) + if (modelData.states.containsKey(panelSlot)) + addPanel(quads, state, panelSlot, modelData.type, modelData.states.get(panelSlot), rand, data, + renderType, modelData.ponder); + return quads; + } + + public void addPanel(List quads, BlockState state, PanelSlot slot, PanelType type, PanelState panelState, + RandomSource rand, ModelData data, RenderType renderType, boolean ponder) { + PartialModel factoryPanel = panelState == PanelState.PASSIVE + ? type == PanelType.NETWORK ? AllPartialModels.FACTORY_PANEL : AllPartialModels.FACTORY_PANEL_RESTOCKER + : type == PanelType.NETWORK ? AllPartialModels.FACTORY_PANEL_WITH_BULB + : AllPartialModels.FACTORY_PANEL_RESTOCKER_WITH_BULB; + + List quadsToAdd = factoryPanel.get() + .getQuads(state, null, rand, data, RenderType.solid()); + + float xRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getXRot(state); + float yRot = Mth.RAD_TO_DEG * FactoryPanelBlock.getYRot(state); + + for (BakedQuad bakedQuad : quadsToAdd) { + int[] vertices = bakedQuad.getVertices(); + int[] transformedVertices = Arrays.copyOf(vertices, vertices.length); + + Vec3 quadNormal = Vec3.atLowerCornerOf(bakedQuad.getDirection() + .getNormal()); + quadNormal = VecHelper.rotate(quadNormal, 180, Axis.Y); + quadNormal = VecHelper.rotate(quadNormal, xRot + 90, Axis.X); + quadNormal = VecHelper.rotate(quadNormal, yRot, Axis.Y); + + for (int i = 0; i < vertices.length / BakedQuadHelper.VERTEX_STRIDE; i++) { + Vec3 vertex = BakedQuadHelper.getXYZ(vertices, i); + Vec3 normal = BakedQuadHelper.getNormalXYZ(vertices, i); + + vertex = vertex.add(slot.xOffset * .5, 0, slot.yOffset * .5); + vertex = VecHelper.rotateCentered(vertex, 180, Axis.Y); + vertex = VecHelper.rotateCentered(vertex, xRot + 90, Axis.X); + vertex = VecHelper.rotateCentered(vertex, yRot, Axis.Y); + + normal = VecHelper.rotate(normal, 180, Axis.Y); + normal = VecHelper.rotate(normal, xRot + 90, Axis.X); + normal = VecHelper.rotate(normal, yRot, Axis.Y); + + BakedQuadHelper.setXYZ(transformedVertices, i, vertex); + BakedQuadHelper.setNormalXYZ(transformedVertices, i, new Vec3(0, 1, 0)); + } + + Direction newNormal = Direction.fromDelta((int) Math.round(quadNormal.x), (int) Math.round(quadNormal.y), + (int) Math.round(quadNormal.z)); + quads.add(new BakedQuad(transformedVertices, bakedQuad.getTintIndex(), newNormal, bakedQuad.getSprite(), + !ponder && bakedQuad.isShade())); + } + + } + + private static class FactoryPanelModelData { + public PanelType type; + public EnumMap states = new EnumMap<>(PanelSlot.class); + private boolean ponder; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelPosition.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelPosition.java new file mode 100644 index 0000000000..e2cd7005f4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelPosition.java @@ -0,0 +1,34 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.Mth; + +public record FactoryPanelPosition(BlockPos pos, PanelSlot slot) { + + public static FactoryPanelPosition read(CompoundTag nbt) { + return new FactoryPanelPosition(NbtUtils.readBlockPos(nbt), + PanelSlot.values()[Mth.positiveModulo(nbt.getInt("Slot"), 4)]); + } + + public CompoundTag write() { + CompoundTag nbt = NbtUtils.writeBlockPos(pos); + nbt.putInt("Slot", slot.ordinal()); + return nbt; + } + + public void send(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + buffer.writeVarInt(slot.ordinal()); + } + + public static FactoryPanelPosition receive(FriendlyByteBuf buffer) { + return new FactoryPanelPosition(buffer.readBlockPos(), + PanelSlot.values()[Mth.positiveModulo(buffer.readVarInt(), 4)]); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelRenderer.java new file mode 100644 index 0000000000..951481cb88 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelRenderer.java @@ -0,0 +1,169 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; +import com.simibubi.create.content.redstone.link.RedstoneLinkBlockEntity; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; +import com.simibubi.create.foundation.render.RenderTypes; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.theme.Color; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class FactoryPanelRenderer extends SmartBlockEntityRenderer { + + public FactoryPanelRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(FactoryPanelBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + for (FactoryPanelBehaviour behaviour : be.panels.values()) { + if (!behaviour.isActive()) + continue; + if (behaviour.getAmount() > 0) + renderBulb(behaviour, partialTicks, ms, buffer, light, overlay); + for (FactoryPanelConnection connection : behaviour.targetedBy.values()) + renderPath(behaviour, connection, partialTicks, ms, buffer, light, overlay); + for (FactoryPanelConnection connection : behaviour.targetedByLinks.values()) + renderPath(behaviour, connection, partialTicks, ms, buffer, light, overlay); + } + } + + public static void renderBulb(FactoryPanelBehaviour behaviour, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + BlockState blockState = behaviour.blockEntity.getBlockState(); + + float xRot = FactoryPanelBlock.getXRot(blockState) + Mth.PI / 2; + float yRot = FactoryPanelBlock.getYRot(blockState); + float glow = behaviour.bulb.getValue(partialTicks); + + boolean missingAddress = behaviour.isMissingAddress(); + PartialModel partial = behaviour.redstonePowered || missingAddress ? AllPartialModels.FACTORY_PANEL_RED_LIGHT + : AllPartialModels.FACTORY_PANEL_LIGHT; + + CachedBuffers.partial(partial, blockState) + .rotateCentered(yRot, Direction.UP) + .rotateCentered(xRot, Direction.EAST) + .rotateCentered(Mth.PI, Direction.UP) + .translate(behaviour.slot.xOffset * .5, 0, behaviour.slot.yOffset * .5) + .light(glow > 0.125f ? LightTexture.FULL_BRIGHT : light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.translucent())); + + if (glow < .125f) + return; + + glow = (float) (1 - (2 * Math.pow(glow - .75f, 2))); + glow = Mth.clamp(glow, -1, 1); + int color = (int) (200 * glow); + + CachedBuffers.partial(partial, blockState) + .rotateCentered(yRot, Direction.UP) + .rotateCentered(xRot, Direction.EAST) + .rotateCentered(Mth.PI, Direction.UP) + .translate(behaviour.slot.xOffset * .5, 0, behaviour.slot.yOffset * .5) + .light(LightTexture.FULL_BRIGHT) + .color(color, color, color, 255) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderTypes.additive())); + } + + public static void renderPath(FactoryPanelBehaviour behaviour, FactoryPanelConnection connection, + float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + BlockState blockState = behaviour.blockEntity.getBlockState(); + List path = connection.getPath(behaviour.getWorld(), blockState, behaviour.getPanelPosition()); + + float xRot = FactoryPanelBlock.getXRot(blockState) + Mth.PI / 2; + float yRot = FactoryPanelBlock.getYRot(blockState); + float glow = behaviour.bulb.getValue(partialTicks); + + FactoryPanelSupportBehaviour sbe = FactoryPanelBehaviour.linkAt(behaviour.getWorld(), connection); + boolean displayLinkMode = sbe != null && sbe.blockEntity instanceof DisplayLinkBlockEntity; + boolean redstoneLinkMode = sbe != null && sbe.blockEntity instanceof RedstoneLinkBlockEntity; + boolean pathReversed = sbe != null && !sbe.isOutput(); + + int color = 0; + float yOffset = 0; + boolean success = connection.success; + boolean dots = false; + + if (displayLinkMode) { + // Display status + color = 0x3C9852; + dots = true; + + } else if (redstoneLinkMode) { + // Link status + color = pathReversed ? (behaviour.count == 0 ? 0x888898 : behaviour.satisfied ? 0xEF0000 : 0x580101) + : (behaviour.redstonePowered ? 0xEF0000 : 0x580101); + yOffset = 0.5f; + + } else { + // Regular ingredient status + color = behaviour.getIngredientStatusColor(); + + yOffset = 1; + yOffset += behaviour.promisedSatisfied ? 1 : behaviour.satisfied ? 0 : 2; + + if (!behaviour.redstonePowered && !behaviour.waitingForNetwork && glow > 0 && !behaviour.satisfied) { + float p = (1 - (1 - glow) * (1 - glow)); + color = Color.mixColors(color, success ? 0xEAF2EC : 0xE5654B, p); + if (!behaviour.satisfied && !behaviour.promisedSatisfied) + yOffset += (success ? 1 : 2) * p; + } + } + + float currentX = 0; + float currentZ = 0; + + for (int i = 0; i < path.size(); i++) { + Direction direction = path.get(i); + + if (!pathReversed) { + currentX += direction.getStepX() * .5; + currentZ += direction.getStepZ() * .5; + } + + boolean isArrowSegment = pathReversed ? i == path.size() - 1 : i == 0; + PartialModel partial = (dots ? AllPartialModels.FACTORY_PANEL_DOTTED + : isArrowSegment ? AllPartialModels.FACTORY_PANEL_ARROWS : AllPartialModels.FACTORY_PANEL_LINES) + .get(pathReversed ? direction : direction.getOpposite()); + SuperByteBuffer connectionSprite = CachedBuffers.partial(partial, blockState) + .rotateCentered(yRot, Direction.UP) + .rotateCentered(xRot, Direction.EAST) + .rotateCentered(Mth.PI, Direction.UP) + .translate(behaviour.slot.xOffset * .5 + .25, 0, behaviour.slot.yOffset * .5 + .25) + .translate(currentX, (yOffset + (direction.get2DDataValue() % 2) * 0.125f) / 512f, currentZ); + + if (!displayLinkMode && !redstoneLinkMode && !behaviour.isMissingAddress() && !behaviour.waitingForNetwork + && !behaviour.satisfied && !behaviour.redstonePowered) + connectionSprite.shiftUV(AllSpriteShifts.FACTORY_PANEL_CONNECTIONS); + + connectionSprite.color(color) + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + + if (pathReversed) { + currentX += direction.getStepX() * .5; + currentZ += direction.getStepZ() * .5; + } + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelScreen.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelScreen.java new file mode 100644 index 0000000000..eb39a2148c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelScreen.java @@ -0,0 +1,708 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.FACTORY_GAUGE_BOTTOM; +import static com.simibubi.create.foundation.gui.AllGuiTextures.FACTORY_GAUGE_RECIPE; +import static com.simibubi.create.foundation.gui.AllGuiTextures.FACTORY_GAUGE_RESTOCK; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.logistics.AddressEditBox; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.box.PackageStyles; +import com.simibubi.create.content.trains.station.NoShadowFontWrapper; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.Mth; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraftforge.common.crafting.IShapedRecipe; +import net.minecraftforge.items.ItemHandlerHelper; + +public class FactoryPanelScreen extends AbstractSimiScreen { + + private EditBox addressBox; + private IconButton confirmButton; + private IconButton deleteButton; + private IconButton newInputButton; + private IconButton relocateButton; + private IconButton activateCraftingButton; + private ScrollInput promiseExpiration; + private FactoryPanelBehaviour behaviour; + private boolean restocker; + private boolean sendReset; + private boolean sendRedstoneReset; + + private BigItemStack outputConfig; + private List inputConfig; + private List connections; + + private CraftingRecipe availableCraftingRecipe; + private boolean craftingActive; + private List craftingIngredients; + + public FactoryPanelScreen(FactoryPanelBehaviour behaviour) { + this.behaviour = behaviour; + minecraft = Minecraft.getInstance(); + restocker = behaviour.panelBE().restocker; + availableCraftingRecipe = null; + craftingActive = !behaviour.activeCraftingArrangement.isEmpty(); + updateConfigs(); + } + + private void updateConfigs() { + connections = new ArrayList<>(behaviour.targetedBy.values()); + outputConfig = new BigItemStack(behaviour.getFilter(), behaviour.recipeOutput); + inputConfig = connections.stream() + .map(c -> { + FactoryPanelBehaviour b = FactoryPanelBehaviour.at(minecraft.level, c.from); + return b == null ? new BigItemStack(ItemStack.EMPTY, 0) : new BigItemStack(b.getFilter(), c.amount); + }) + .toList(); + + searchForCraftingRecipe(); + + if (availableCraftingRecipe == null) { + craftingActive = false; + return; + } + + craftingIngredients = convertRecipeToPackageOrderContext(availableCraftingRecipe, inputConfig); + } + + public static List convertRecipeToPackageOrderContext(CraftingRecipe availableCraftingRecipe, List inputs) { + List craftingIngredients = new ArrayList<>(); + BigItemStack emptyIngredient = new BigItemStack(ItemStack.EMPTY, 1); + NonNullList ingredients = availableCraftingRecipe.getIngredients(); + + int width = Math.min(3, ingredients.size()); + int height = Math.min(3, ingredients.size() / 3 + 1); + + if (availableCraftingRecipe instanceof IShapedRecipe shaped) { + width = shaped.getRecipeWidth(); + height = shaped.getRecipeHeight(); + } + + if (height == 1) + for (int i = 0; i < 3; i++) + craftingIngredients.add(emptyIngredient); + if (width == 1) + craftingIngredients.add(emptyIngredient); + + for (int i = 0; i < ingredients.size(); i++) { + Ingredient ingredient = ingredients.get(i); + BigItemStack craftingIngredient = emptyIngredient; + + if (!ingredient.isEmpty()) + for (BigItemStack bigItemStack : inputs) + if (ingredient.test(bigItemStack.stack)) + craftingIngredient = new BigItemStack(bigItemStack.stack, 1); + craftingIngredients.add(craftingIngredient); + + if (width < 3 && (i + 1) % width == 0) + for (int j = 0; j < 3 - width; j++) + craftingIngredients.add(emptyIngredient); + } + + while (craftingIngredients.size() < 9) + craftingIngredients.add(emptyIngredient); + + return craftingIngredients; + } + + @Override + protected void init() { + int sizeX = FACTORY_GAUGE_BOTTOM.getWidth(); + int sizeY = + (restocker ? FACTORY_GAUGE_RESTOCK : FACTORY_GAUGE_RECIPE).getHeight() + FACTORY_GAUGE_BOTTOM.getHeight(); + + setWindowSize(sizeX, sizeY); + super.init(); + clearWidgets(); + + int x = guiLeft; + int y = guiTop; + + if (addressBox == null) { + String frogAddress = behaviour.getFrogAddress(); + addressBox = new AddressEditBox(this, new NoShadowFontWrapper(font), x + 36, y + windowHeight - 51, 108, 10, false, frogAddress); + addressBox.setValue(behaviour.recipeAddress); + addressBox.setTextColor(0x555555); + } + addressBox.setX(x + 36); + addressBox.setY(y + windowHeight - 51); + addRenderableWidget(addressBox); + + confirmButton = new IconButton(x + sizeX - 33, y + sizeY - 25, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> minecraft.setScreen(null)); + confirmButton.setToolTip(CreateLang.translate("gui.factory_panel.save_and_close") + .component()); + addRenderableWidget(confirmButton); + + deleteButton = new IconButton(x + sizeX - 55, y + sizeY - 25, AllIcons.I_TRASH); + deleteButton.withCallback(() -> { + sendReset = true; + minecraft.setScreen(null); + }); + deleteButton.setToolTip(CreateLang.translate("gui.factory_panel.reset") + .component()); + addRenderableWidget(deleteButton); + + promiseExpiration = new ScrollInput(x + 97, y + windowHeight - 24, 28, 16).withRange(-1, 31) + .titled(CreateLang.translate("gui.factory_panel.promises_expire_title") + .component()); + promiseExpiration.setState(behaviour.promiseClearingInterval); + addRenderableWidget(promiseExpiration); + + newInputButton = new IconButton(x + 31, y + 47, AllIcons.I_ADD); + newInputButton.withCallback(() -> { + FactoryPanelConnectionHandler.startConnection(behaviour); + minecraft.setScreen(null); + }); + newInputButton.setToolTip(CreateLang.translate("gui.factory_panel.connect_input") + .component()); + + relocateButton = new IconButton(x + 31, y + 67, AllIcons.I_MOVE_GAUGE); + relocateButton.withCallback(() -> { + FactoryPanelConnectionHandler.startRelocating(behaviour); + minecraft.setScreen(null); + }); + relocateButton.setToolTip(CreateLang.translate("gui.factory_panel.relocate") + .component()); + + if (!restocker) { + addRenderableWidget(newInputButton); + addRenderableWidget(relocateButton); + } + + activateCraftingButton = null; + if (availableCraftingRecipe != null) { + activateCraftingButton = new IconButton(x + 31, y + 27, AllIcons.I_3x3); + activateCraftingButton.withCallback(() -> { + craftingActive = !craftingActive; + init(); + if (craftingActive) { + outputConfig.count = availableCraftingRecipe.getResultItem(minecraft.level.registryAccess()) + .getCount(); + } + }); + activateCraftingButton.setToolTip(CreateLang.translate("gui.factory_panel.activate_crafting") + .component()); + addRenderableWidget(activateCraftingButton); + } + } + + @Override + public void tick() { + super.tick(); + if (inputConfig.size() != behaviour.targetedBy.size()) { + updateConfigs(); + init(); + } + if (activateCraftingButton != null) + activateCraftingButton.green = craftingActive; + addressBox.tick(); + promiseExpiration.titled(CreateLang + .translate(promiseExpiration.getState() == -1 ? "gui.factory_panel.promises_do_not_expire" + : "gui.factory_panel.promises_expire_title") + .component()); + } + + @Override + protected void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + // BG + AllGuiTextures bg = restocker ? FACTORY_GAUGE_RESTOCK : FACTORY_GAUGE_RECIPE; + if (restocker) + FACTORY_GAUGE_RECIPE.render(graphics, x, y - 16); + bg.render(graphics, x, y); + FACTORY_GAUGE_BOTTOM.render(graphics, x, y + bg.getHeight()); + y = guiTop; + + // RECIPE + int slot = 0; + if (craftingActive) { + for (BigItemStack itemStack : craftingIngredients) + renderInputItem(graphics, slot++, itemStack, mouseX, mouseY); + } else { + for (BigItemStack itemStack : inputConfig) + renderInputItem(graphics, slot++, itemStack, mouseX, mouseY); + if (inputConfig.isEmpty()) { + int inputX = guiLeft + (restocker ? 88 : 68 + (slot % 3 * 20)); + int inputY = guiTop + (restocker ? 12 : 28) + (slot / 3 * 20); + if (!restocker && mouseY > inputY && mouseY < inputY + 60 && mouseX > inputX && mouseX < inputX + 60) + graphics.renderComponentTooltip(font, + List.of(CreateLang.translate("gui.factory_panel.unconfigured_input") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.unconfigured_input_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.factory_panel.unconfigured_input_tip_1") + .style(ChatFormatting.GRAY) + .component()), + mouseX, mouseY); + } + } + + if (restocker) + renderInputItem(graphics, slot, new BigItemStack(behaviour.getFilter(), 1), mouseX, mouseY); + + if (!restocker) { + int outputX = x + 160; + int outputY = y + 48; + graphics.renderItem(outputConfig.stack, outputX, outputY); + graphics.renderItemDecorations(font, behaviour.getFilter(), outputX, outputY, outputConfig.count + ""); + + if (mouseX >= outputX - 1 && mouseX < outputX - 1 + 18 && mouseY >= outputY - 1 + && mouseY < outputY - 1 + 18) { + MutableComponent c1 = CreateLang + .translate("gui.factory_panel.expected_output", CreateLang.itemName(outputConfig.stack) + .add(CreateLang.text(" x" + outputConfig.count)) + .string()) + .color(ScrollInput.HEADER_RGB) + .component(); + MutableComponent c2 = CreateLang.translate("gui.factory_panel.expected_output_tip") + .style(ChatFormatting.GRAY) + .component(); + MutableComponent c3 = CreateLang.translate("gui.factory_panel.expected_output_tip_1") + .style(ChatFormatting.GRAY) + .component(); + MutableComponent c4 = CreateLang.translate("gui.factory_panel.expected_output_tip_2") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component(); + graphics.renderComponentTooltip(font, craftingActive ? List.of(c1, c2, c3) : List.of(c1, c2, c3, c4), + mouseX, mouseY); + } + } + + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(0, 0, 10); + + // ADDRESS + if (addressBox.isHovered() && !addressBox.isFocused()) + showAddressBoxTooltip(graphics, mouseX, mouseY); + + // TITLE + Component title = CreateLang + .translate(restocker ? "gui.factory_panel.title_as_restocker" : "gui.factory_panel.title_as_recipe") + .component(); + graphics.drawString(font, title, x + 97 - font.width(title) / 2, y + (restocker ? -12 : 4), 0x3D3C48, false); + + // ITEM PREVIEW + int previewY = restocker ? 0 : 60; + + ms.pushPose(); + ms.translate(0, previewY, 0); + GuiGameElement.of(AllBlocks.FACTORY_GAUGE.asStack()) + .scale(4) + .at(0, 0, -200) + .render(graphics, x + 195, y + 55); + if (!behaviour.getFilter() + .isEmpty()) { + GuiGameElement.of(behaviour.getFilter()) + .scale(1.625) + .at(0, 0, 100) + .render(graphics, x + 214, y + 68); + } + + ms.popPose(); + + // REDSTONE LINKS + if (!behaviour.targetedByLinks.isEmpty()) { + ItemStack asStack = AllBlocks.REDSTONE_LINK.asStack(); + int itemX = x + 9; + int itemY = y + windowHeight - 24; + AllGuiTextures.FROGPORT_SLOT.render(graphics, itemX - 1, itemY - 1); + graphics.renderItem(asStack, itemX, itemY); + + if (mouseX >= itemX && mouseX < itemX + 16 && mouseY >= itemY && mouseY < itemY + 16) { + List linkTip = List.of(CreateLang.translate("gui.factory_panel.has_link_connections") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.left_click_disconnect") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()); + graphics.renderComponentTooltip(font, linkTip, mouseX, mouseY); + } + } + + // PROMISES + int state = promiseExpiration.getState(); + graphics.drawString(font, CreateLang.text(state == -1 ? " /" : state == 0 ? "30s" : state + "m") + .component(), promiseExpiration.getX() + 3, promiseExpiration.getY() + 4, 0xffeeeeee, true); + + ItemStack asStack = PackageStyles.getDefaultBox(); + int itemX = x + 68; + int itemY = y + windowHeight - 24; + graphics.renderItem(asStack, itemX, itemY); + int promised = behaviour.getPromised(); + graphics.renderItemDecorations(font, asStack, itemX, itemY, promised + ""); + + if (mouseX >= itemX && mouseX < itemX + 16 && mouseY >= itemY && mouseY < itemY + 16) { + List promiseTip = List.of(); + + if (promised == 0) { + promiseTip = List.of(CreateLang.translate("gui.factory_panel.no_open_promises") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang + .translate(restocker ? "gui.factory_panel.restocker_promises_tip" + : "gui.factory_panel.recipe_promises_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang + .translate(restocker ? "gui.factory_panel.restocker_promises_tip_1" + : "gui.factory_panel.recipe_promises_tip_1") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.factory_panel.promise_prevents_oversending") + .style(ChatFormatting.GRAY) + .component()); + } else { + promiseTip = List.of(CreateLang.translate("gui.factory_panel.promised_items") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.text(behaviour.getFilter() + .getHoverName() + .getString() + " x" + promised) + .component(), + CreateLang.translate("gui.factory_panel.left_click_reset") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()); + } + + graphics.renderComponentTooltip(font, promiseTip, mouseX, mouseY); + } + + ms.popPose(); + } + + // + + private void renderInputItem(GuiGraphics graphics, int slot, BigItemStack itemStack, int mouseX, int mouseY) { + int inputX = guiLeft + (restocker ? 88 : 68 + (slot % 3 * 20)); + int inputY = guiTop + (restocker ? 12 : 28) + (slot / 3 * 20); + + graphics.renderItem(itemStack.stack, inputX, inputY); + if (!craftingActive && !restocker && !itemStack.stack.isEmpty()) + graphics.renderItemDecorations(font, itemStack.stack, inputX, inputY, itemStack.count + ""); + + if (mouseX < inputX - 2 || mouseX >= inputX - 2 + 20 || mouseY < inputY - 2 || mouseY >= inputY - 2 + 20) + return; + + if (craftingActive) { + graphics.renderComponentTooltip(font, List.of(CreateLang.translate("gui.factory_panel.crafting_input") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.crafting_input_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.factory_panel.crafting_input_tip_1") + .style(ChatFormatting.GRAY) + .component()), + mouseX, mouseY); + return; + } + + if (itemStack.stack.isEmpty()) { + graphics.renderComponentTooltip(font, List.of(CreateLang.translate("gui.factory_panel.empty_panel") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.left_click_disconnect") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mouseX, mouseY); + return; + } + + if (restocker) { + graphics.renderComponentTooltip(font, + List.of(CreateLang.translate("gui.factory_panel.sending_item", CreateLang.itemName(itemStack.stack) + .string()) + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.sending_item_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.factory_panel.sending_item_tip_1") + .style(ChatFormatting.GRAY) + .component()), + mouseX, mouseY); + return; + } + + graphics.renderComponentTooltip(font, + List.of(CreateLang.translate("gui.factory_panel.sending_item", CreateLang.itemName(itemStack.stack) + .add(CreateLang.text(" x" + itemStack.count)) + .string()) + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.scroll_to_change_amount") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component(), + CreateLang.translate("gui.factory_panel.left_click_disconnect") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mouseX, mouseY); + } + + private void showAddressBoxTooltip(GuiGraphics graphics, int mouseX, int mouseY) { + if (addressBox.getValue() + .isBlank()) { + if (restocker) { + graphics.renderComponentTooltip(font, + List.of(CreateLang.translate("gui.factory_panel.restocker_address") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.restocker_address_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.factory_panel.restocker_address_tip_1") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.schedule.lmb_edit") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mouseX, mouseY); + + } else { + graphics.renderComponentTooltip(font, List.of(CreateLang.translate("gui.factory_panel.recipe_address") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.recipe_address_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.factory_panel.recipe_address_tip_1") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.schedule.lmb_edit") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mouseX, mouseY); + } + } else + graphics.renderComponentTooltip(font, + List.of( + CreateLang + .translate(restocker ? "gui.factory_panel.restocker_address_given" + : "gui.factory_panel.recipe_address_given") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.text("'" + addressBox.getValue() + "'") + .style(ChatFormatting.GRAY) + .component()), + mouseX, mouseY); + } + + // + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int pButton) { + if (getFocused() != null && !getFocused().isMouseOver(mouseX, mouseY)) + setFocused(null); + + int x = guiLeft; + int y = guiTop; + + // Remove connections + if (!craftingActive) + for (int i = 0; i < connections.size(); i++) { + int inputX = x + 68 + (i % 3 * 20); + int inputY = y + 28 + (i / 3 * 20); + if (mouseX >= inputX && mouseX < inputX + 16 && mouseY >= inputY && mouseY < inputY + 16) { + sendIt(connections.get(i).from, false); + playButtonSound(); + return true; + } + } + + // Clear promises + int itemX = x + 68; + int itemY = y + windowHeight - 24; + if (mouseX >= itemX && mouseX < itemX + 16 && mouseY >= itemY && mouseY < itemY + 16) { + sendIt(null, true); + playButtonSound(); + return true; + } + + // remove redstone connections + itemX = x + 9; + itemY = y + windowHeight - 24; + if (mouseX >= itemX && mouseX < itemX + 16 && mouseY >= itemY && mouseY < itemY + 16) { + sendRedstoneReset = true; + sendIt(null, false); + playButtonSound(); + return true; + } + + return super.mouseClicked(mouseX, mouseY, pButton); + } + + public void playButtonSound() { + Minecraft.getInstance() + .getSoundManager() + .play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK.get(), 1.0f, 0.25f)); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double pDelta) { + int x = guiLeft; + int y = guiTop; + + if (addressBox.mouseScrolled(mouseX, mouseY, pDelta)) + return true; + + if (craftingActive) + return super.mouseScrolled(mouseX, mouseY, pDelta); + + for (int i = 0; i < inputConfig.size(); i++) { + int inputX = x + 68 + (i % 3 * 20); + int inputY = y + 26 + (i / 3 * 20); + if (mouseX >= inputX && mouseX < inputX + 16 && mouseY >= inputY && mouseY < inputY + 16) { + BigItemStack itemStack = inputConfig.get(i); + if (itemStack.stack.isEmpty()) + return true; + itemStack.count = + Mth.clamp((int) (itemStack.count + Math.signum(pDelta) * (hasShiftDown() ? 10 : 1)), 1, 64); + return true; + } + } + + if (!restocker) { + int outputX = x + 160; + int outputY = y + 48; + if (mouseX >= outputX && mouseX < outputX + 16 && mouseY >= outputY && mouseY < outputY + 16) { + BigItemStack itemStack = outputConfig; + itemStack.count = + Mth.clamp((int) (itemStack.count + Math.signum(pDelta) * (hasShiftDown() ? 10 : 1)), 1, 64); + return true; + } + } + + return super.mouseScrolled(mouseX, mouseY, pDelta); + } + + @Override + public void removed() { + sendIt(null, false); + super.removed(); + } + + private void sendIt(@Nullable FactoryPanelPosition toRemove, boolean clearPromises) { + Map inputs = new HashMap<>(); + + if (inputConfig.size() == connections.size()) + for (int i = 0; i < inputConfig.size(); i++) { + BigItemStack stackInConfig = inputConfig.get(i); + inputs.put(connections.get(i).from, craftingActive ? (int) craftingIngredients.stream() + .filter( + b -> !b.stack.isEmpty() && ItemHandlerHelper.canItemStacksStack(b.stack, stackInConfig.stack)) + .count() : stackInConfig.count); + } + + List craftingArrangement = craftingActive ? craftingIngredients.stream() + .map(b -> b.stack) + .toList() : List.of(); + + FactoryPanelPosition pos = behaviour.getPanelPosition(); + int promiseExp = promiseExpiration.getState(); + String address = addressBox.getValue(); + + FactoryPanelConfigurationPacket packet = new FactoryPanelConfigurationPacket(pos, address, inputs, + craftingArrangement, outputConfig.count, promiseExp, toRemove, clearPromises, sendReset, sendRedstoneReset); + AllPackets.getChannel() + .sendToServer(packet); + } + + private void searchForCraftingRecipe() { + ItemStack output = outputConfig.stack; + if (output.isEmpty()) + return; + if (behaviour.targetedBy.isEmpty()) + return; + + Set itemsToUse = inputConfig.stream() + .map(b -> b.stack) + .filter(i -> !i.isEmpty()) + .map(i -> i.getItem()) + .collect(Collectors.toSet()); + + ClientLevel level = Minecraft.getInstance().level; + + availableCraftingRecipe = level.getRecipeManager() + .getAllRecipesFor(RecipeType.CRAFTING) + .parallelStream() + .filter(r -> output.getItem() == r.getResultItem(level.registryAccess()) + .getItem()) + .filter(r -> { + if (AllRecipeTypes.shouldIgnoreInAutomation(r)) + return false; + + Set itemsUsed = new HashSet<>(); + for (Ingredient ingredient : r.getIngredients()) { + if (ingredient.isEmpty()) + continue; + boolean available = false; + for (BigItemStack bis : inputConfig) { + if (!bis.stack.isEmpty() && ingredient.test(bis.stack)) { + available = true; + itemsUsed.add(bis.stack.getItem()); + break; + } + } + if (!available) + return false; + } + + if (itemsUsed.size() < itemsToUse.size()) + return false; + + return true; + }) + .findAny() + .orElse(null); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemMenu.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemMenu.java new file mode 100644 index 0000000000..c68c094b0c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemMenu.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class FactoryPanelSetItemMenu extends GhostItemMenu { + + public FactoryPanelSetItemMenu(MenuType type, int id, Inventory inv, FactoryPanelBehaviour contentHolder) { + super(type, id, inv, contentHolder); + } + + public FactoryPanelSetItemMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public static FactoryPanelSetItemMenu create(int id, Inventory inv, FactoryPanelBehaviour be) { + return new FactoryPanelSetItemMenu(AllMenuTypes.FACTORY_PANEL_SET_ITEM.get(), id, inv, be); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return new ItemStackHandler(1); + } + + @Override + protected boolean allowRepeats() { + return true; + } + + @Override + @OnlyIn(Dist.CLIENT) + protected FactoryPanelBehaviour createOnClient(FriendlyByteBuf extraData) { + FactoryPanelPosition pos = FactoryPanelPosition.receive(extraData); + return FactoryPanelBehaviour.at(Minecraft.getInstance().level, pos); + } + + @Override + protected void addSlots() { + int playerX = 13; + int playerY = 112; + int slotX = 74; + int slotY = 28; + + addPlayerSlots(playerX, playerY); + addSlot(new SlotItemHandler(ghostInventory, 0, slotX, slotY)); + } + + @Override + protected void saveData(FactoryPanelBehaviour contentHolder) { + if (!contentHolder.setFilter(ghostInventory.getStackInSlot(0))) { + player.displayClientMessage(CreateLang.translateDirect("logistics.filter.invalid_item"), true); + AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); + return; + } + player.level() + .playSound(null, contentHolder.getPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .1f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemScreen.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemScreen.java new file mode 100644 index 0000000000..6becd82492 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemScreen.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.Collections; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.gui.element.GuiGameElement; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; + +public class FactoryPanelSetItemScreen extends AbstractSimiContainerScreen { + + private IconButton confirmButton; + private List extraAreas = Collections.emptyList(); + + public FactoryPanelSetItemScreen(FactoryPanelSetItemMenu container, Inventory inv, Component title) { + super(container, inv, title); + } + + @Override + protected void init() { + int bgHeight = AllGuiTextures.FACTORY_GAUGE_SET_ITEM.getHeight(); + int bgWidth = AllGuiTextures.FACTORY_GAUGE_SET_ITEM.getWidth(); + setWindowSize(bgWidth, bgHeight + AllGuiTextures.PLAYER_INVENTORY.getHeight()); + super.init(); + clearWidgets(); + int x = getGuiLeft(); + int y = getGuiTop(); + + + confirmButton = new IconButton(x + bgWidth - 40, y + bgHeight - 25, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> minecraft.player.closeContainer()); + addRenderableWidget(confirmButton); + + extraAreas = List.of(new Rect2i(x + bgWidth, y + bgHeight - 30, 40, 20)); + } + + @Override + protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY) { + int x = getGuiLeft(); + int y = getGuiTop(); + AllGuiTextures.FACTORY_GAUGE_SET_ITEM.render(pGuiGraphics, x - 5, y); + renderPlayerInventory(pGuiGraphics, x + 5, y + 94); + + ItemStack stack = AllBlocks.FACTORY_GAUGE.asStack(); + Component title = CreateLang.translate("gui.factory_panel.place_item_to_monitor") + .component(); + pGuiGraphics.drawString(font, title, x + imageWidth / 2 - font.width(title) / 2 - 5, y + 4, 0x3D3C48, false); + + GuiGameElement.of(stack) + .scale(3) + .render(pGuiGraphics, x + 180, y + 48); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSlotPositioning.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSlotPositioning.java new file mode 100644 index 0000000000..2ab8ba5481 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSlotPositioning.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock.PanelSlot; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; + +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.Mth; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +class FactoryPanelSlotPositioning extends ValueBoxTransform { + + public PanelSlot slot; + + public FactoryPanelSlotPositioning(PanelSlot slot) { + this.slot = slot; + } + + @Override + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { + return getCenterOfSlot(state, slot); + } + + public static Vec3 getCenterOfSlot(BlockState state, PanelSlot slot) { + Vec3 vec = new Vec3(.25 + slot.xOffset * .5, 1.5 / 16f, .25 + slot.yOffset * .5); + vec = VecHelper.rotateCentered(vec, 180, Axis.Y); + vec = VecHelper.rotateCentered(vec, Mth.RAD_TO_DEG * FactoryPanelBlock.getXRot(state) + 90, Axis.X); + vec = VecHelper.rotateCentered(vec, Mth.RAD_TO_DEG * FactoryPanelBlock.getYRot(state), Axis.Y); + return vec; + } + + @Override + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(level, pos, state); + if (offset == null) + return false; + return localHit.distanceTo(offset) < scale / 2; + } + + @Override + public float getScale() { + return super.getScale(); + } + + @Override + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { + TransformStack.of(ms) + .rotate(FactoryPanelBlock.getYRot(state) + Mth.PI, Direction.UP) + .rotate(-FactoryPanelBlock.getXRot(state), Direction.EAST); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSupportBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSupportBehaviour.java new file mode 100644 index 0000000000..40705fcd3d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSupportBehaviour.java @@ -0,0 +1,143 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; + +public class FactoryPanelSupportBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + private List linkedPanels; + private boolean changed; + + private Supplier outputPower; + private Supplier isOutput; + private Runnable onNotify; + + public FactoryPanelSupportBehaviour(SmartBlockEntity be, Supplier isOutput, Supplier outputPower, + Runnable onNotify) { + super(be); + this.isOutput = isOutput; + this.outputPower = outputPower; + this.onNotify = onNotify; + linkedPanels = new ArrayList<>(); + } + + public boolean shouldPanelBePowered() { + return isOutput() && outputPower.get(); + } + + public boolean isOutput() { + return isOutput.get(); + } + + public void notifyLink() { + onNotify.run(); + } + + @Override + public void destroy() { + for (FactoryPanelPosition panelPos : linkedPanels) { + if (!getWorld().isLoaded(panelPos.pos())) + continue; + FactoryPanelBehaviour behaviour = FactoryPanelBehaviour.at(getWorld(), panelPos); + behaviour.targetedByLinks.remove(getPos()); + behaviour.blockEntity.notifyUpdate(); + } + super.destroy(); + } + + public void notifyPanels() { + if (getWorld().isClientSide()) + return; + for (Iterator iterator = linkedPanels.iterator(); iterator.hasNext(); ) { + FactoryPanelPosition panelPos = iterator.next(); + if (!getWorld().isLoaded(panelPos.pos())) + continue; + FactoryPanelBehaviour behaviour = FactoryPanelBehaviour.at(getWorld(), panelPos); + if (behaviour == null) { + iterator.remove(); + changed = true; + continue; + } + behaviour.checkForRedstoneInput(); + } + } + + @Nullable + public Boolean shouldBePoweredTristate() { + for (Iterator iterator = linkedPanels.iterator(); iterator.hasNext(); ) { + FactoryPanelPosition panelPos = iterator.next(); + if (!getWorld().isLoaded(panelPos.pos())) + return null; + FactoryPanelBehaviour behaviour = FactoryPanelBehaviour.at(getWorld(), panelPos); + if (behaviour == null) { + iterator.remove(); + changed = true; + continue; + } + if (behaviour.isActive() && behaviour.satisfied && behaviour.count != 0) + return true; + } + return false; + } + + public List getLinkedPanels() { + return linkedPanels; + } + + public void connect(FactoryPanelBehaviour panel) { + FactoryPanelPosition panelPosition = panel.getPanelPosition(); + if (linkedPanels.contains(panelPosition)) + return; + linkedPanels.add(panelPosition); + changed = true; + } + + public void disconnect(FactoryPanelBehaviour panel) { + linkedPanels.remove(panel.getPanelPosition()); + changed = true; + } + + @Override + public void tick() { + super.tick(); + if (changed) { + changed = false; + if (!isOutput()) + notifyLink(); + blockEntity.setChanged(); + } + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + if (!linkedPanels.isEmpty()) + nbt.put("LinkedGauges", NBTHelper.writeCompoundList(linkedPanels, FactoryPanelPosition::write)); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + linkedPanels.clear(); + linkedPanels.addAll( + NBTHelper.readCompoundList(nbt.getList("LinkedGauges", Tag.TAG_COMPOUND), FactoryPanelPosition::read)); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterScreen.java index d25f5b180d..4919324c48 100644 --- a/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterScreen.java @@ -11,14 +11,12 @@ import com.simibubi.create.AllPackets; import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.Indicator; -import com.simibubi.create.foundation.gui.widget.Indicator.State; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.lang.FontHelper.Palette; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.Rect2i; import net.minecraft.network.chat.Component; @@ -40,20 +38,20 @@ public abstract class AbstractFilterScreen extends @Override protected void init() { - setWindowSize(Math.max(background.width, PLAYER_INVENTORY.width), - background.height + 4 + PLAYER_INVENTORY.height); + setWindowSize(Math.max(background.getWidth(), PLAYER_INVENTORY.getWidth()), + background.getHeight() + 4 + PLAYER_INVENTORY.getHeight()); super.init(); int x = leftPos; int y = topPos; - resetButton = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_TRASH); + resetButton = new IconButton(x + background.getWidth() - 62, y + background.getHeight() - 24, AllIcons.I_TRASH); resetButton.withCallback(() -> { menu.clearContents(); contentsCleared(); menu.sendClearPacket(); }); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { minecraft.player.closeContainer(); }); @@ -61,24 +59,26 @@ public abstract class AbstractFilterScreen extends addRenderableWidget(resetButton); addRenderableWidget(confirmButton); - extraAreas = ImmutableList.of(new Rect2i(x + background.width, y + background.height - 40, 80, 48)); + extraAreas = ImmutableList.of(new Rect2i(x + background.getWidth(), y + background.getHeight() - 40, 80, 48)); } @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - int invX = getLeftOfCentered(PLAYER_INVENTORY.width); - int invY = topPos + background.height + 4; + int invX = getLeftOfCentered(PLAYER_INVENTORY.getWidth()); + int invY = topPos + background.getHeight() + 4; renderPlayerInventory(graphics, invX, invY); int x = leftPos; int y = topPos; background.render(graphics, x, y); - graphics.drawString(font, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, - AllItems.FILTER.isIn(menu.contentHolder) ? 0x303030 : 0x592424, false); + graphics.drawString(font, title, x + (background.getWidth() - 8) / 2 - font.width(title) / 2, y + 4, + AllItems.PACKAGE_FILTER.isIn(menu.contentHolder) ? 0x3D3C48 + : AllItems.FILTER.isIn(menu.contentHolder) ? 0x303030 : 0x592424, + false); GuiGameElement.of(menu.contentHolder).at(x + background.width + 8, y + background.height - 52, -200) + .GuiRenderBuilder>at(x + background.getWidth() + 8, y + background.getHeight() - 52, -200) .scale(4) .render(graphics); } @@ -117,15 +117,11 @@ public abstract class AbstractFilterScreen extends public void handleIndicators() { for (IconButton button : getTooltipButtons()) - button.active = isButtonEnabled(button); - for (Indicator indicator : getIndicators()) - indicator.state = isIndicatorOn(indicator) ? State.ON : State.OFF; + button.green = !isButtonEnabled(button); } protected abstract boolean isButtonEnabled(IconButton button); - protected abstract boolean isIndicatorOn(Indicator indicator); - protected List getTooltipButtons() { return Collections.emptyList(); } @@ -134,10 +130,6 @@ public abstract class AbstractFilterScreen extends return Collections.emptyList(); } - protected List getIndicators() { - return Collections.emptyList(); - } - private void fillToolTip(IconButton button, Component tooltip) { if (!button.isHoveredOrFocused()) return; diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterMenu.java b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterMenu.java index b66c6f31a4..f6bbd5572f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterMenu.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterMenu.java @@ -4,14 +4,16 @@ import java.util.ArrayList; import java.util.List; import com.simibubi.create.AllMenuTypes; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; + +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.ClickType; @@ -52,7 +54,7 @@ public class AttributeFilterMenu extends AbstractFilterMenu { super.init(inv, contentHolder); ItemStack stack = new ItemStack(Items.NAME_TAG); stack.setHoverName( - Components.literal("Selected Tags").withStyle(ChatFormatting.RESET, ChatFormatting.BLUE)); + Component.literal("Selected Tags").withStyle(ChatFormatting.RESET, ChatFormatting.BLUE)); ghostInventory.setStackInSlot(1, stack); } @@ -68,8 +70,8 @@ public class AttributeFilterMenu extends AbstractFilterMenu { @Override protected void addFilterSlots() { - this.addSlot(new SlotItemHandler(ghostInventory, 0, 16, 24)); - this.addSlot(new SlotItemHandler(ghostInventory, 1, 22, 59) { + this.addSlot(new SlotItemHandler(ghostInventory, 0, 16, 27)); + this.addSlot(new SlotItemHandler(ghostInventory, 1, 16, 62) { @Override public boolean mayPickup(Player playerIn) { return false; @@ -135,7 +137,9 @@ public class AttributeFilterMenu extends AbstractFilterMenu { .getList("MatchedAttributes", Tag.TAG_COMPOUND); attributes.forEach(inbt -> { CompoundTag compound = (CompoundTag) inbt; - selectedAttributes.add(Pair.of(ItemAttribute.fromNBT(compound), compound.getBoolean("Inverted"))); + ItemAttribute attribute = ItemAttribute.loadStatic(compound); + if (attribute != null) + selectedAttributes.add(Pair.of(attribute, compound.getBoolean("Inverted"))); }); } @@ -147,15 +151,14 @@ public class AttributeFilterMenu extends AbstractFilterMenu { selectedAttributes.forEach(at -> { if (at == null) return; - CompoundTag compoundNBT = new CompoundTag(); - at.getFirst() - .serializeNBT(compoundNBT); + + CompoundTag compoundNBT = ItemAttribute.saveStatic(at.getFirst()); compoundNBT.putBoolean("Inverted", at.getSecond()); attributes.add(compoundNBT); }); filterItem.getOrCreateTag() .put("MatchedAttributes", attributes); - + if (attributes.isEmpty() && whitelistMode == WhitelistMode.WHITELIST_DISJ) filterItem.setTag(null); } diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterScreen.java index 5f176f5004..7c48bc3d2c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterScreen.java @@ -7,21 +7,23 @@ import java.util.stream.Collectors; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPackets; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.Indicator; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.player.Inventory; @@ -31,22 +33,21 @@ public class AttributeFilterScreen extends AbstractFilterScreen { menu.whitelistMode = WhitelistMode.WHITELIST_DISJ; sendOptionUpdate(Option.WHITELIST); }); whitelistDis.setToolTip(allowDisN); - whitelistCon = new IconButton(x + 65, y + 61, AllIcons.I_WHITELIST_AND); + whitelistCon = new IconButton(x + 56, y + 61, AllIcons.I_WHITELIST_AND); whitelistCon.withCallback(() -> { menu.whitelistMode = WhitelistMode.WHITELIST_CONJ; sendOptionUpdate(Option.WHITELIST2); }); whitelistCon.setToolTip(allowConN); - blacklist = new IconButton(x + 83, y + 61, AllIcons.I_WHITELIST_NOT); + blacklist = new IconButton(x + 74, y + 61, AllIcons.I_WHITELIST_NOT); blacklist.withCallback(() -> { menu.whitelistMode = WhitelistMode.BLACKLIST; sendOptionUpdate(Option.BLACKLIST); }); blacklist.setToolTip(denyN); - whitelistDisIndicator = new Indicator(x + 47, y + 55, Components.immutableEmpty()); - whitelistConIndicator = new Indicator(x + 65, y + 55, Components.immutableEmpty()); - blacklistIndicator = new Indicator(x + 83, y + 55, Components.immutableEmpty()); + addRenderableWidgets(blacklist, whitelistCon, whitelistDis); - addRenderableWidgets(blacklist, whitelistCon, whitelistDis, blacklistIndicator, whitelistConIndicator, - whitelistDisIndicator); - - addRenderableWidget(add = new IconButton(x + 182, y + 23, AllIcons.I_ADD)); - addRenderableWidget(addInverted = new IconButton(x + 200, y + 23, AllIcons.I_ADD_INVERTED_ATTRIBUTE)); + addRenderableWidget(add = new IconButton(x + 182, y + 26, AllIcons.I_ADD)); + addRenderableWidget(addInverted = new IconButton(x + 200, y + 26, AllIcons.I_ADD_INVERTED_ATTRIBUTE)); add.withCallback(() -> { handleAddedAttibute(false); }); @@ -107,10 +103,10 @@ public class AttributeFilterScreen extends AbstractFilterScreen selectedAttributes.add(Components.literal("- ") - .append(at.getFirst() - .format(at.getSecond())) - .withStyle(ChatFormatting.GRAY))); + menu.selectedAttributes.forEach(at -> { + selectedAttributes.add(Component.literal("- ") + .append(at.getFirst() + .format(at.getSecond())) + .withStyle(ChatFormatting.GRAY)); + }); } private void referenceItemChanged(ItemStack stack) { @@ -148,8 +146,8 @@ public class AttributeFilterScreen extends AbstractFilterScreen options = attributesOfItem.stream() .map(a -> a.format(false)) .collect(Collectors.toList()); @@ -161,11 +159,8 @@ public class AttributeFilterScreen extends AbstractFilterScreen existing : menu.selectedAttributes) { - CompoundTag testTag = new CompoundTag(); - CompoundTag testTag2 = new CompoundTag(); - existing.getFirst() - .serializeNBT(testTag); - selected.serializeNBT(testTag2); + CompoundTag testTag = ItemAttribute.saveStatic(existing.getFirst()); + CompoundTag testTag2 = ItemAttribute.saveStatic(selected); if (testTag.equals(testTag2)) { add.active = false; addInverted.active = false; @@ -184,7 +179,7 @@ public class AttributeFilterScreen extends AbstractFilterScreen getIndicators() { - return Arrays.asList(blacklistIndicator, whitelistConIndicator, whitelistDisIndicator); - } - protected boolean handleAddedAttibute(boolean inverted) { int index = attributeSelector.getState(); if (index >= attributesOfItem.size()) return false; add.active = false; addInverted.active = false; - CompoundTag tag = new CompoundTag(); ItemAttribute itemAttribute = attributesOfItem.get(index); - itemAttribute.serializeNBT(tag); + CompoundTag tag = ItemAttribute.saveStatic(itemAttribute); AllPackets.getChannel() .sendToServer(new FilterScreenPacket(inverted ? Option.ADD_INVERTED_TAG : Option.ADD_TAG, tag)); menu.appendSelectedAttribute(itemAttribute, inverted); if (menu.selectedAttributes.size() == 1) selectedAttributes.set(0, selectedT.plainCopy() .withStyle(ChatFormatting.YELLOW)); - selectedAttributes.add(Components.literal("- ").append(itemAttribute.format(inverted)) + selectedAttributes.add(Component.literal("- ").append(itemAttribute.format(inverted)) .withStyle(ChatFormatting.GRAY)); return true; } @@ -268,15 +257,4 @@ public class AttributeFilterScreen extends AbstractFilterScreen tooltip, TooltipFlag flagIn) { - if (!AllKeys.shiftDown()) { - List makeSummary = makeSummary(stack); - if (makeSummary.isEmpty()) - return; - tooltip.add(Components.literal(" ")); - tooltip.addAll(makeSummary); - } + if (AllKeys.shiftDown()) + return; + List makeSummary = makeSummary(stack); + if (makeSummary.isEmpty()) + return; + tooltip.add(CommonComponents.SPACE); + tooltip.addAll(makeSummary); } private List makeSummary(ItemStack filter) { @@ -88,12 +99,12 @@ public class FilterItem extends Item implements MenuProvider { boolean blacklist = filter.getOrCreateTag() .getBoolean("Blacklist"); - list.add((blacklist ? Lang.translateDirect("gui.filter.deny_list") - : Lang.translateDirect("gui.filter.allow_list")).withStyle(ChatFormatting.GOLD)); + list.add((blacklist ? CreateLang.translateDirect("gui.filter.deny_list") + : CreateLang.translateDirect("gui.filter.allow_list")).withStyle(ChatFormatting.GOLD)); int count = 0; for (int i = 0; i < filterItems.getSlots(); i++) { if (count > 3) { - list.add(Components.literal("- ...") + list.add(Component.literal("- ...") .withStyle(ChatFormatting.DARK_GRAY)); break; } @@ -101,7 +112,7 @@ public class FilterItem extends Item implements MenuProvider { ItemStack filterStack = filterItems.getStackInSlot(i); if (filterStack.isEmpty()) continue; - list.add(Components.literal("- ") + list.add(Component.literal("- ") .append(filterStack.getHoverName()) .withStyle(ChatFormatting.GRAY)); count++; @@ -115,26 +126,26 @@ public class FilterItem extends Item implements MenuProvider { WhitelistMode whitelistMode = WhitelistMode.values()[filter.getOrCreateTag() .getInt("WhitelistMode")]; list.add((whitelistMode == WhitelistMode.WHITELIST_CONJ - ? Lang.translateDirect("gui.attribute_filter.allow_list_conjunctive") + ? CreateLang.translateDirect("gui.attribute_filter.allow_list_conjunctive") : whitelistMode == WhitelistMode.WHITELIST_DISJ - ? Lang.translateDirect("gui.attribute_filter.allow_list_disjunctive") - : Lang.translateDirect("gui.attribute_filter.deny_list")).withStyle(ChatFormatting.GOLD)); + ? CreateLang.translateDirect("gui.attribute_filter.allow_list_disjunctive") + : CreateLang.translateDirect("gui.attribute_filter.deny_list")).withStyle(ChatFormatting.GOLD)); int count = 0; ListTag attributes = filter.getOrCreateTag() .getList("MatchedAttributes", Tag.TAG_COMPOUND); for (Tag inbt : attributes) { CompoundTag compound = (CompoundTag) inbt; - ItemAttribute attribute = ItemAttribute.fromNBT(compound); + ItemAttribute attribute = ItemAttribute.loadStatic(compound); if (attribute == null) continue; boolean inverted = compound.getBoolean("Inverted"); if (count > 3) { - list.add(Components.literal("- ...") + list.add(Component.literal("- ...") .withStyle(ChatFormatting.DARK_GRAY)); break; } - list.add(Components.literal("- ") + list.add(Component.literal("- ") .append(attribute.format(inverted))); count++; } @@ -143,6 +154,17 @@ public class FilterItem extends Item implements MenuProvider { return Collections.emptyList(); } + if (type == FilterType.PACKAGE) { + String address = filter.getOrCreateTag() + .getString("Address"); + if (!address.isBlank()) + list.add(CreateLang.text("-> ") + .style(ChatFormatting.GRAY) + .add(CreateLang.text(address) + .style(ChatFormatting.GOLD)) + .component()); + } + return list; } @@ -151,8 +173,8 @@ public class FilterItem extends Item implements MenuProvider { ItemStack heldItem = player.getItemInHand(hand); if (!player.isShiftKeyDown() && hand == InteractionHand.MAIN_HAND) { - if (!world.isClientSide && player instanceof ServerPlayer) - NetworkHooks.openScreen((ServerPlayer) player, this, buf -> { + if (!world.isClientSide && player instanceof ServerPlayer serverPlayer) + NetworkHooks.openScreen(serverPlayer, this, buf -> { buf.writeItem(heldItem); }); return InteractionResultHolder.success(heldItem); @@ -167,6 +189,8 @@ public class FilterItem extends Item implements MenuProvider { return FilterMenu.create(id, inv, heldItem); if (type == FilterType.ATTRIBUTE) return AttributeFilterMenu.create(id, inv, heldItem); + if (type == FilterType.PACKAGE) + return PackageFilterMenu.create(id, inv, heldItem); return null; } @@ -189,10 +213,36 @@ public class FilterItem extends Item implements MenuProvider { public static boolean testDirect(ItemStack filter, ItemStack stack, boolean matchNBT) { if (matchNBT) { + if (PackageItem.isPackage(filter) && PackageItem.isPackage(stack)) + return doPackagesHaveSameData(filter, stack); + return ItemHandlerHelper.canItemStacksStack(filter, stack); - } else { - return ItemHelper.sameItem(filter, stack); } + + if (PackageItem.isPackage(filter) && PackageItem.isPackage(stack)) + return true; + + return ItemHelper.sameItem(filter, stack); + } + + public static boolean doPackagesHaveSameData(@NotNull ItemStack a, @NotNull ItemStack b) { + if (a.isEmpty() || a.hasTag() != b.hasTag()) + return false; + if (!a.hasTag()) + return true; + if (!a.areCapsCompatible(b)) + return false; + for (String key : a.getTag() + .getAllKeys()) { + if (key.equals("Fragment")) + continue; + if (!Objects.equals(a.getTag() + .get(key), + b.getTag() + .get(key))) + return false; + } + return true; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/FilterItemStack.java b/src/main/java/com/simibubi/create/content/logistics/filter/FilterItemStack.java index 196825a7c9..c63cb1d4c7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/filter/FilterItemStack.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/FilterItemStack.java @@ -5,13 +5,16 @@ import java.util.List; import com.simibubi.create.AllItems; import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; + import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.ItemStackHandler; @@ -23,15 +26,18 @@ public class FilterItemStack { public static FilterItemStack of(ItemStack filter) { if (filter.hasTag()) { - - if (AllItems.FILTER.isIn(filter)){ + if (AllItems.FILTER.isIn(filter)) { trimFilterTag(filter); return new ListFilterItemStack(filter); } - if (AllItems.ATTRIBUTE_FILTER.isIn(filter)){ + if (AllItems.ATTRIBUTE_FILTER.isIn(filter)) { trimFilterTag(filter); return new AttributeFilterItemStack(filter); } + if (AllItems.PACKAGE_FILTER.isIn(filter)) { + trimFilterTag(filter); + return new PackageFilterItemStack(filter); + } } return new FilterItemStack(filter); @@ -45,7 +51,7 @@ public class FilterItemStack { return of(ItemStack.EMPTY); } - private static void trimFilterTag(ItemStack filter){ + private static void trimFilterTag(ItemStack filter) { CompoundTag stackTag = filter.getTag(); stackTag.remove("Enchantments"); stackTag.remove("AttributeModifiers"); @@ -111,7 +117,7 @@ public class FilterItemStack { fluidExtracted = true; if (GenericItemEmptying.canItemBeEmptied(world, filterItemStack)) filterFluidStack = GenericItemEmptying.emptyItem(world, filterItemStack, true) - .getFirst(); + .getFirst(); } } @@ -141,10 +147,10 @@ public class FilterItemStack { shouldRespectNBT = defaults ? false : filter.getTag() - .getBoolean("RespectNBT"); + .getBoolean("RespectNBT"); isBlacklist = defaults ? false : filter.getTag() - .getBoolean("Blacklist"); + .getBoolean("Blacklist"); } @Override @@ -183,14 +189,14 @@ public class FilterItemStack { attributeTests = new ArrayList<>(); whitelistMode = WhitelistMode.values()[defaults ? 0 : filter.getTag() - .getInt("WhitelistMode")]; + .getInt("WhitelistMode")]; ListTag attributes = defaults ? new ListTag() : filter.getTag() - .getList("MatchedAttributes", Tag.TAG_COMPOUND); + .getList("MatchedAttributes", Tag.TAG_COMPOUND); for (Tag inbt : attributes) { CompoundTag compound = (CompoundTag) inbt; - ItemAttribute attribute = ItemAttribute.fromNBT(compound); + ItemAttribute attribute = ItemAttribute.loadStatic(compound); if (attribute != null) attributeTests.add(Pair.of(attribute, compound.getBoolean("Inverted"))); } @@ -212,34 +218,55 @@ public class FilterItemStack { if (matches) { switch (whitelistMode) { - case BLACKLIST: - return false; - case WHITELIST_CONJ: - continue; - case WHITELIST_DISJ: - return true; + case BLACKLIST -> { + return false; + } + case WHITELIST_CONJ -> { + continue; + } + case WHITELIST_DISJ -> { + return true; + } } } else { switch (whitelistMode) { - case BLACKLIST: - continue; - case WHITELIST_CONJ: - return false; - case WHITELIST_DISJ: - continue; + case BLACKLIST, WHITELIST_DISJ -> { + continue; + } + case WHITELIST_CONJ -> { + return false; + } } } } - switch (whitelistMode) { - case BLACKLIST: - return true; - case WHITELIST_CONJ: - return true; - case WHITELIST_DISJ: - return false; - } + return switch (whitelistMode) { + case BLACKLIST, WHITELIST_CONJ -> true; + case WHITELIST_DISJ -> false; + }; + } + + } + + public static class PackageFilterItemStack extends FilterItemStack { + + public String filterString; + + protected PackageFilterItemStack(ItemStack filter) { + super(filter); + filterString = filter.getOrCreateTag() + .getString("Address"); + } + + @Override + public boolean test(Level world, ItemStack stack, boolean matchNBT) { + return (filterString.isBlank() && super.test(world, stack, matchNBT)) + || PackageItem.isPackage(stack) && PackageItem.matchAddress(stack, filterString); + } + + @Override + public boolean test(Level world, FluidStack stack, boolean matchNBT) { return false; } diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/FilterMenu.java b/src/main/java/com/simibubi/create/content/logistics/filter/FilterMenu.java index 29864709fd..af1ddd622a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/filter/FilterMenu.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/FilterMenu.java @@ -40,7 +40,7 @@ public class FilterMenu extends AbstractFilterMenu { @Override protected void addFilterSlots() { int x = 23; - int y = 22; + int y = 25; for (int row = 0; row < 2; ++row) for (int col = 0; col < 9; ++col) this.addSlot(new SlotItemHandler(ghostInventory, col + row * 9, x + col * 18, y + row * 18)); diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreen.java index d2b5adb568..8909187c2b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreen.java @@ -7,9 +7,7 @@ import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.Indicator; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -19,20 +17,18 @@ public class FilterScreen extends AbstractFilterScreen { private static final String PREFIX = "gui.filter."; - private Component allowN = Lang.translateDirect(PREFIX + "allow_list"); - private Component allowDESC = Lang.translateDirect(PREFIX + "allow_list.description"); - private Component denyN = Lang.translateDirect(PREFIX + "deny_list"); - private Component denyDESC = Lang.translateDirect(PREFIX + "deny_list.description"); + private Component allowN = CreateLang.translateDirect(PREFIX + "allow_list"); + private Component allowDESC = CreateLang.translateDirect(PREFIX + "allow_list.description"); + private Component denyN = CreateLang.translateDirect(PREFIX + "deny_list"); + private Component denyDESC = CreateLang.translateDirect(PREFIX + "deny_list.description"); - private Component respectDataN = Lang.translateDirect(PREFIX + "respect_data"); - private Component respectDataDESC = Lang.translateDirect(PREFIX + "respect_data.description"); - private Component ignoreDataN = Lang.translateDirect(PREFIX + "ignore_data"); - private Component ignoreDataDESC = Lang.translateDirect(PREFIX + "ignore_data.description"); + private Component respectDataN = CreateLang.translateDirect(PREFIX + "respect_data"); + private Component respectDataDESC = CreateLang.translateDirect(PREFIX + "respect_data.description"); + private Component ignoreDataN = CreateLang.translateDirect(PREFIX + "ignore_data"); + private Component ignoreDataDESC = CreateLang.translateDirect(PREFIX + "ignore_data.description"); private IconButton whitelist, blacklist; private IconButton respectNBT, ignoreNBT; - private Indicator whitelistIndicator, blacklistIndicator; - private Indicator respectNBTIndicator, ignoreNBTIndicator; public FilterScreen(FilterMenu menu, Inventory inv, Component title) { super(menu, inv, title, AllGuiTextures.FILTER); @@ -58,9 +54,7 @@ public class FilterScreen extends AbstractFilterScreen { sendOptionUpdate(Option.WHITELIST); }); whitelist.setToolTip(allowN); - blacklistIndicator = new Indicator(x + 18, y + 69, Components.immutableEmpty()); - whitelistIndicator = new Indicator(x + 36, y + 69, Components.immutableEmpty()); - addRenderableWidgets(blacklist, whitelist, blacklistIndicator, whitelistIndicator); + addRenderableWidgets(blacklist, whitelist); respectNBT = new IconButton(x + 60, y + 75, AllIcons.I_RESPECT_NBT); respectNBT.withCallback(() -> { @@ -74,9 +68,7 @@ public class FilterScreen extends AbstractFilterScreen { sendOptionUpdate(Option.IGNORE_DATA); }); ignoreNBT.setToolTip(ignoreDataN); - respectNBTIndicator = new Indicator(x + 60, y + 69, Components.immutableEmpty()); - ignoreNBTIndicator = new Indicator(x + 78, y + 69, Components.immutableEmpty()); - addRenderableWidgets(respectNBT, ignoreNBT, respectNBTIndicator, ignoreNBTIndicator); + addRenderableWidgets(respectNBT, ignoreNBT); handleIndicators(); } @@ -91,11 +83,6 @@ public class FilterScreen extends AbstractFilterScreen { return Arrays.asList(denyDESC.plainCopy(), allowDESC.plainCopy(), respectDataDESC.plainCopy(), ignoreDataDESC.plainCopy()); } - @Override - protected List getIndicators() { - return Arrays.asList(blacklistIndicator, whitelistIndicator, respectNBTIndicator, ignoreNBTIndicator); - } - @Override protected boolean isButtonEnabled(IconButton button) { if (button == blacklist) @@ -109,17 +96,4 @@ public class FilterScreen extends AbstractFilterScreen { return true; } - @Override - protected boolean isIndicatorOn(Indicator indicator) { - if (indicator == blacklistIndicator) - return menu.blacklist; - if (indicator == whitelistIndicator) - return !menu.blacklist; - if (indicator == respectNBTIndicator) - return menu.respectNBT; - if (indicator == ignoreNBTIndicator) - return !menu.respectNBT; - return false; - } - } diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreenPacket.java b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreenPacket.java index 2896d8abc9..b97703851d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreenPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreenPacket.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.logistics.filter; import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.nbt.CompoundTag; @@ -11,7 +12,7 @@ import net.minecraftforge.network.NetworkEvent.Context; public class FilterScreenPacket extends SimplePacketBase { public enum Option { - WHITELIST, WHITELIST2, BLACKLIST, RESPECT_DATA, IGNORE_DATA, UPDATE_FILTER_ITEM, ADD_TAG, ADD_INVERTED_TAG; + WHITELIST, WHITELIST2, BLACKLIST, RESPECT_DATA, IGNORE_DATA, UPDATE_FILTER_ITEM, ADD_TAG, ADD_INVERTED_TAG, UPDATE_ADDRESS; } private final Option option; @@ -44,8 +45,7 @@ public class FilterScreenPacket extends SimplePacketBase { if (player == null) return; - if (player.containerMenu instanceof FilterMenu) { - FilterMenu c = (FilterMenu) player.containerMenu; + if (player.containerMenu instanceof FilterMenu c) { if (option == Option.WHITELIST) c.blacklist = false; if (option == Option.BLACKLIST) @@ -60,8 +60,7 @@ public class FilterScreenPacket extends SimplePacketBase { net.minecraft.world.item.ItemStack.of(data.getCompound("Item"))); } - if (player.containerMenu instanceof AttributeFilterMenu) { - AttributeFilterMenu c = (AttributeFilterMenu) player.containerMenu; + if (player.containerMenu instanceof AttributeFilterMenu c) { if (option == Option.WHITELIST) c.whitelistMode = WhitelistMode.WHITELIST_DISJ; if (option == Option.WHITELIST2) @@ -69,9 +68,14 @@ public class FilterScreenPacket extends SimplePacketBase { if (option == Option.BLACKLIST) c.whitelistMode = WhitelistMode.BLACKLIST; if (option == Option.ADD_TAG) - c.appendSelectedAttribute(ItemAttribute.fromNBT(data), false); + c.appendSelectedAttribute(ItemAttribute.loadStatic(data), false); if (option == Option.ADD_INVERTED_TAG) - c.appendSelectedAttribute(ItemAttribute.fromNBT(data), true); + c.appendSelectedAttribute(ItemAttribute.loadStatic(data), true); + } + + if (player.containerMenu instanceof PackageFilterMenu c) { + if (option == Option.UPDATE_ADDRESS) + c.address = data.getString("Address"); } }); diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/ItemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/ItemAttribute.java deleted file mode 100644 index d33b89bd54..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/ItemAttribute.java +++ /dev/null @@ -1,411 +0,0 @@ -package com.simibubi.create.content.logistics.filter; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.function.BiPredicate; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.Nullable; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.Create; -import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes; -import com.simibubi.create.content.logistics.filter.attribute.BookAuthorAttribute; -import com.simibubi.create.content.logistics.filter.attribute.BookCopyAttribute; -import com.simibubi.create.content.logistics.filter.attribute.ColorAttribute; -import com.simibubi.create.content.logistics.filter.attribute.EnchantAttribute; -import com.simibubi.create.content.logistics.filter.attribute.FluidContentsAttribute; -import com.simibubi.create.content.logistics.filter.attribute.ItemNameAttribute; -import com.simibubi.create.content.logistics.filter.attribute.ShulkerFillLevelAttribute; -import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryAmuletAttribute; -import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryAttunementAttribute; -import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryCrystalAttribute; -import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryPerkGemAttribute; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.ItemTags; -import net.minecraft.tags.TagKey; -import net.minecraft.world.Container; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.ComposterBlock; -import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.CreativeModeTabRegistry; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.forgespi.language.IModInfo; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public interface ItemAttribute { - - static List types = new ArrayList<>(); - - static ItemAttribute standard = register(StandardTraits.DUMMY); - static ItemAttribute inTag = register(new InTag(ItemTags.LOGS)); - static ItemAttribute inItemGroup = register(InItemGroup.EMPTY); - static ItemAttribute addedBy = register(new AddedBy("dummy")); - static ItemAttribute hasEnchant = register(EnchantAttribute.EMPTY); - static ItemAttribute shulkerFillLevel = register(ShulkerFillLevelAttribute.EMPTY); - static ItemAttribute hasColor = register(ColorAttribute.EMPTY); - static ItemAttribute hasFluid = register(FluidContentsAttribute.EMPTY); - static ItemAttribute hasName = register(new ItemNameAttribute("dummy")); - static ItemAttribute bookAuthor = register(new BookAuthorAttribute("dummy")); - static ItemAttribute bookCopy = register(new BookCopyAttribute(-1)); - static ItemAttribute astralAmulet = register(new AstralSorceryAmuletAttribute("dummy", -1)); - static ItemAttribute astralAttunement = register(new AstralSorceryAttunementAttribute("dummy")); - static ItemAttribute astralCrystal = register(new AstralSorceryCrystalAttribute("dummy")); - static ItemAttribute astralPerkGem = register(new AstralSorceryPerkGemAttribute("dummy")); - - static ItemAttribute register(ItemAttribute attributeType) { - types.add(attributeType); - return attributeType; - } - - @Nullable - static ItemAttribute fromNBT(CompoundTag nbt) { - for (ItemAttribute itemAttribute : types) - if (itemAttribute.canRead(nbt)) - return itemAttribute.readNBT(nbt.getCompound(itemAttribute.getNBTKey())); - return null; - } - - default boolean appliesTo(ItemStack stack, Level world) { - return appliesTo(stack); - } - - boolean appliesTo(ItemStack stack); - - default List listAttributesOf(ItemStack stack, Level world) { - return listAttributesOf(stack); - } - - List listAttributesOf(ItemStack stack); - - String getTranslationKey(); - - void writeNBT(CompoundTag nbt); - - ItemAttribute readNBT(CompoundTag nbt); - - default void serializeNBT(CompoundTag nbt) { - CompoundTag compound = new CompoundTag(); - writeNBT(compound); - nbt.put(getNBTKey(), compound); - } - - default Object[] getTranslationParameters() { - return new String[0]; - } - - default boolean canRead(CompoundTag nbt) { - return nbt.contains(getNBTKey()); - } - - default String getNBTKey() { - return getTranslationKey(); - } - - @OnlyIn(value = Dist.CLIENT) - default MutableComponent format(boolean inverted) { - return Lang.translateDirect("item_attributes." + getTranslationKey() + (inverted ? ".inverted" : ""), - getTranslationParameters()); - } - - public static enum StandardTraits implements ItemAttribute { - - DUMMY(s -> false), - PLACEABLE(s -> s.getItem() instanceof BlockItem), - CONSUMABLE(ItemStack::isEdible), - FLUID_CONTAINER(s -> s.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM) - .isPresent()), - ENCHANTED(ItemStack::isEnchanted), - MAX_ENCHANTED(StandardTraits::maxEnchanted), - RENAMED(ItemStack::hasCustomHoverName), - DAMAGED(ItemStack::isDamaged), - BADLY_DAMAGED(s -> s.isDamaged() && (float) s.getDamageValue() / s.getMaxDamage() > 3 / 4f), - NOT_STACKABLE(((Predicate) ItemStack::isStackable).negate()), - EQUIPABLE(s -> LivingEntity.getEquipmentSlotForItem(s) - .getType() != EquipmentSlot.Type.HAND), - FURNACE_FUEL(AbstractFurnaceBlockEntity::isFuel), - WASHABLE(AllFanProcessingTypes.SPLASHING::canProcess), - HAUNTABLE(AllFanProcessingTypes.HAUNTING::canProcess), - CRUSHABLE((s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType()) - || testRecipe(s, w, AllRecipeTypes.MILLING.getType())), - SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)), - SMOKABLE((s, w) -> testRecipe(s, w, RecipeType.SMOKING)), - BLASTABLE((s, w) -> testRecipe(s, w, RecipeType.BLASTING)), - COMPOSTABLE(s -> ComposterBlock.COMPOSTABLES.containsKey(s.getItem())); - - private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); - private Predicate test; - private BiPredicate testWithWorld; - - private StandardTraits(Predicate test) { - this.test = test; - } - - private static boolean testRecipe(ItemStack s, Level w, RecipeType> type) { - RECIPE_WRAPPER.setItem(0, s.copy()); - return w.getRecipeManager() - .getRecipeFor(type, RECIPE_WRAPPER, w) - .isPresent(); - } - - private static boolean maxEnchanted(ItemStack s) { - return EnchantmentHelper.getEnchantments(s) - .entrySet() - .stream() - .anyMatch(e -> e.getKey() - .getMaxLevel() <= e.getValue()); - } - - private StandardTraits(BiPredicate test) { - this.testWithWorld = test; - } - - @Override - public boolean appliesTo(ItemStack stack, Level world) { - if (testWithWorld != null) - return testWithWorld.test(stack, world); - return appliesTo(stack); - } - - @Override - public boolean appliesTo(ItemStack stack) { - return test.test(stack); - } - - @Override - public List listAttributesOf(ItemStack stack, Level world) { - List attributes = new ArrayList<>(); - for (StandardTraits trait : values()) - if (trait.appliesTo(stack, world)) - attributes.add(trait); - return attributes; - } - - @Override - public List listAttributesOf(ItemStack stack) { - return null; - } - - @Override - public String getTranslationKey() { - return Lang.asId(name()); - } - - @Override - public String getNBTKey() { - return "standard_trait"; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putBoolean(name(), true); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - for (StandardTraits trait : values()) - if (nbt.contains(trait.name())) - return trait; - return null; - } - - } - - public static class InTag implements ItemAttribute { - - public TagKey tag; - - public InTag(TagKey tag) { - this.tag = tag; - } - - @Override - public boolean appliesTo(ItemStack stack) { - return stack.is(tag); - } - - @Override - public List listAttributesOf(ItemStack stack) { - return stack.getTags() - .map(InTag::new) - .collect(Collectors.toList()); - } - - @Override - public String getTranslationKey() { - return "in_tag"; - } - - @Override - public Object[] getTranslationParameters() { - return new Object[] { "#" + tag.location() }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("space", tag.location().getNamespace()); - nbt.putString("path", tag.location().getPath()); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new InTag(ItemTags.create(new ResourceLocation(nbt.getString("space"), nbt.getString("path")))); - } - - } - - public static class InItemGroup implements ItemAttribute { - public static final InItemGroup EMPTY = new InItemGroup(null); - - private CreativeModeTab group; - - public InItemGroup(CreativeModeTab group) { - this.group = group; - } - - @Override - public boolean appliesTo(ItemStack stack, Level world) { - if (group == null) - return false; - - if (group.getDisplayItems() - .isEmpty() - && group.getSearchTabDisplayItems() - .isEmpty()) { - - try { - group.buildContents(new CreativeModeTab.ItemDisplayParameters(world.enabledFeatures(), false, - world.registryAccess())); - } catch (RuntimeException | LinkageError e) { - Create.LOGGER.error("Attribute Filter: Item Group crashed while building contents.", - group.getDisplayName() - .getString(), - e); - group = null; - return false; - } - - } - - return tabContainsItem(group, stack); - } - - @Override - public boolean appliesTo(ItemStack stack) { - return false; - } - - @Override - public List listAttributesOf(ItemStack stack) { - return CreativeModeTabs.tabs() - .stream() - .filter(tab -> tab.getType() == CreativeModeTab.Type.CATEGORY) - .filter(tab -> tabContainsItem(tab, stack)) - .map(tab -> (ItemAttribute) new InItemGroup(tab)) - .toList(); - } - - private static boolean tabContainsItem(CreativeModeTab tab, ItemStack stack) { - return tab.contains(stack) || tab.contains(new ItemStack(stack.getItem())); - } - - @Override - public String getTranslationKey() { - return "in_item_group"; - } - - @Override - public Object[] getTranslationParameters() { - return new Object[] { group == null ? "" : group.getDisplayName().getString() }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - if (group != null) { - ResourceLocation groupId = CreativeModeTabRegistry.getName(group); - - if (groupId != null) { - nbt.putString("group", groupId.toString()); - } - } - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return nbt.contains("group") ? new InItemGroup(CreativeModeTabRegistry.getTab(new ResourceLocation(nbt.getString("group")))) : EMPTY; - } - } - - public static class AddedBy implements ItemAttribute { - - private String modId; - - public AddedBy(String modId) { - this.modId = modId; - } - - @Override - public boolean appliesTo(ItemStack stack) { - return modId.equals(stack.getItem() - .getCreatorModId(stack)); - } - - @Override - public List listAttributesOf(ItemStack stack) { - String id = stack.getItem() - .getCreatorModId(stack); - return id == null ? Collections.emptyList() : Arrays.asList(new AddedBy(id)); - } - - @Override - public String getTranslationKey() { - return "added_by"; - } - - @Override - public Object[] getTranslationParameters() { - Optional modContainerById = ModList.get() - .getModContainerById(modId); - String name = modContainerById.map(ModContainer::getModInfo) - .map(IModInfo::getDisplayName) - .orElse(StringUtils.capitalize(modId)); - return new Object[] { name }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("id", modId); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new AddedBy(nbt.getString("id")); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/PackageFilterMenu.java b/src/main/java/com/simibubi/create/content/logistics/filter/PackageFilterMenu.java new file mode 100644 index 0000000000..cd1a0364d4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/filter/PackageFilterMenu.java @@ -0,0 +1,66 @@ +package com.simibubi.create.content.logistics.filter; + +import com.simibubi.create.AllMenuTypes; + +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.ItemStackHandler; + +public class PackageFilterMenu extends AbstractFilterMenu { + + String address; + EditBox addressInput; + + public PackageFilterMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public PackageFilterMenu(MenuType type, int id, Inventory inv, ItemStack stack) { + super(type, id, inv, stack); + } + + public static PackageFilterMenu create(int id, Inventory inv, ItemStack stack) { + return new PackageFilterMenu(AllMenuTypes.PACKAGE_FILTER.get(), id, inv, stack); + } + + @Override + protected int getPlayerInventoryXOffset() { + return 40; + } + + @Override + protected int getPlayerInventoryYOffset() { + return 101; + } + + @Override + protected void addFilterSlots() {} + + @Override + protected ItemStackHandler createGhostInventory() { + return new ItemStackHandler(); + } + + @Override + public void clearContents() { + address = ""; + } + + @Override + protected void initAndReadInventory(ItemStack filterItem) { + super.initAndReadInventory(filterItem); + address = filterItem.getOrCreateTag() + .getString("Address"); + } + + @Override + protected void saveData(ItemStack filterItem) { + super.saveData(filterItem); + filterItem.getOrCreateTag() + .putString("Address", address); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/PackageFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/filter/PackageFilterScreen.java new file mode 100644 index 0000000000..f03e8503b6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/filter/PackageFilterScreen.java @@ -0,0 +1,111 @@ +package com.simibubi.create.content.logistics.filter; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.AddressEditBox; +import com.simibubi.create.content.logistics.box.PackageStyles; +import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.widget.IconButton; + +import net.createmod.catnip.gui.element.GuiGameElement; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; + +public class PackageFilterScreen extends AbstractFilterScreen { + + private EditBox addressBox; + private boolean deferFocus; + + public PackageFilterScreen(PackageFilterMenu menu, Inventory inv, Component title) { + super(menu, inv, title, AllGuiTextures.PACKAGE_FILTER); + } + + @Override + protected void containerTick() { + super.containerTick(); + if (deferFocus) { + deferFocus = false; + setFocused(addressBox); + } + addressBox.tick(); + } + + @Override + protected void init() { + setWindowOffset(-11, 7); + super.init(); + + int x = leftPos; + int y = topPos; + + addressBox = new AddressEditBox(this, this.font, x + 44, y + 28, 129, 9, false); + addressBox.setTextColor(0xffffff); + addressBox.setValue(menu.address); + addressBox.setResponder(this::onAddressEdited); + addRenderableWidget(addressBox); + + setFocused(addressBox); + } + + @Override + public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + super.render(graphics, mouseX, mouseY, partialTicks); + + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(leftPos + 16, topPos + 23, 0); + GuiGameElement.of(PackageStyles.getDefaultBox()) + .render(graphics); + ms.popPose(); + } + + public void onAddressEdited(String s) { + menu.address = s; + CompoundTag tag = new CompoundTag(); + tag.putString("Address", s); + AllPackets.getChannel() + .sendToServer(new FilterScreenPacket(Option.UPDATE_ADDRESS, tag)); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + return super.mouseClicked(pMouseX, pMouseY, pButton); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + if (addressBox.mouseScrolled(mouseX, mouseY, delta)) + return true; + return super.mouseScrolled(mouseX, mouseY, delta); + } + + @Override + public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { + if (pKeyCode == GLFW.GLFW_KEY_ENTER) + setFocused(null); + return super.keyPressed(pKeyCode, pScanCode, pModifiers); + } + + @Override + public boolean charTyped(char pCodePoint, int pModifiers) { + return super.charTyped(pCodePoint, pModifiers); + } + + @Override + protected void contentsCleared() { + addressBox.setValue(""); + deferFocus = true; + } + + @Override + protected boolean isButtonEnabled(IconButton button) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookAuthorAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookAuthorAttribute.java deleted file mode 100644 index c0eaf419f5..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookAuthorAttribute.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; - -public class BookAuthorAttribute implements ItemAttribute { - String author; - - public BookAuthorAttribute(String author) { - this.author = author; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - return extractAuthor(itemStack).equals(author); - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - String name = extractAuthor(itemStack); - - List atts = new ArrayList<>(); - if(name.length() > 0) { - atts.add(new BookAuthorAttribute(name)); - } - return atts; - } - - @Override - public String getTranslationKey() { - return "book_author"; - } - - @Override - public Object[] getTranslationParameters() { - return new Object[] {author}; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("author", this.author); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new BookAuthorAttribute(nbt.getString("author")); - } - - private String extractAuthor(ItemStack stack) { - CompoundTag nbt = stack.getTag(); - if (nbt != null && nbt.contains("author")) { - return nbt.getString("author"); - } - return ""; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookCopyAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookCopyAttribute.java deleted file mode 100644 index 04a60b8b31..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookCopyAttribute.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.WrittenBookItem; - -public class BookCopyAttribute implements ItemAttribute { - int generation; - - public BookCopyAttribute(int generation) { - this.generation = generation; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - return extractGeneration(itemStack) == generation; - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - int generation = extractGeneration(itemStack); - - List atts = new ArrayList<>(); - if(generation >= 0) { - atts.add(new BookCopyAttribute(generation)); - } - return atts; - } - - @Override - public String getTranslationKey() { - switch(generation){ - case 0: - return "book_copy_original"; - case 1: - return "book_copy_first"; - case 2: - return "book_copy_second"; - default: - return "book_copy_tattered"; - } - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putInt("generation", this.generation); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new BookCopyAttribute(nbt.getInt("generation")); - } - - @Override - public String getNBTKey() { - return "book_copy"; - } - - private int extractGeneration(ItemStack stack) { - CompoundTag nbt = stack.getTag(); - if (nbt != null && stack.getItem() instanceof WrittenBookItem) { - return nbt.getInt("generation"); - } - return -1; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ColorAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ColorAttribute.java deleted file mode 100644 index 59fc5ec702..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ColorAttribute.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; -import com.simibubi.create.foundation.utility.RegisteredObjects; - -import net.minecraft.client.resources.language.I18n; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.item.FireworkRocketItem; -import net.minecraft.world.item.FireworkStarItem; -import net.minecraft.world.item.ItemStack; - -public class ColorAttribute implements ItemAttribute { - public static final ColorAttribute EMPTY = new ColorAttribute(DyeColor.PURPLE); - - public final DyeColor color; - - public ColorAttribute(DyeColor color) { - this.color = color; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - return findMatchingDyeColors(itemStack).stream().anyMatch(color::equals); - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - return findMatchingDyeColors(itemStack).stream().map(ColorAttribute::new).collect(Collectors.toList()); - } - - private Collection findMatchingDyeColors(ItemStack stack) { - CompoundTag nbt = stack.getTag(); - - DyeColor color = DyeColor.getColor(stack); - if (color != null) - return Collections.singletonList(color); - - Set colors = new HashSet<>(); - if (stack.getItem() instanceof FireworkRocketItem && nbt != null) { - ListTag listnbt = nbt.getCompound("Fireworks").getList("Explosions", 10); - for (int i = 0; i < listnbt.size(); i++) { - colors.addAll(getFireworkStarColors(listnbt.getCompound(i))); - } - } - - if (stack.getItem() instanceof FireworkStarItem && nbt != null) { - colors.addAll(getFireworkStarColors(nbt.getCompound("Explosion"))); - } - - Arrays.stream(DyeColor.values()).filter(c -> RegisteredObjects.getKeyOrThrow(stack.getItem()).getPath().startsWith(c.getName() + "_")).forEach(colors::add); - - return colors; - } - - private Collection getFireworkStarColors(CompoundTag compound) { - Set colors = new HashSet<>(); - Arrays.stream(compound.getIntArray("Colors")).mapToObj(DyeColor::byFireworkColor).forEach(colors::add); - Arrays.stream(compound.getIntArray("FadeColors")).mapToObj(DyeColor::byFireworkColor).forEach(colors::add); - return colors; - } - - @Override - public String getTranslationKey() { - return "color"; - } - - @Override - public Object[] getTranslationParameters() { - return new Object[] { I18n.get("color.minecraft." + color.getName()) }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putInt("id", color.getId()); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return nbt.contains("id") ? - new ColorAttribute(DyeColor.byId(nbt.getInt("id"))) - : EMPTY; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/EnchantAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/EnchantAttribute.java deleted file mode 100644 index fb61fe07f5..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/EnchantAttribute.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute; - -import java.util.List; -import java.util.stream.Collectors; - -import javax.annotation.Nullable; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraftforge.registries.ForgeRegistries; - -public class EnchantAttribute implements ItemAttribute { - public static final EnchantAttribute EMPTY = new EnchantAttribute(null); - - private final Enchantment enchantment; - - public EnchantAttribute(@Nullable Enchantment enchantment) { - this.enchantment = enchantment; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - return EnchantmentHelper.getEnchantments(itemStack).containsKey(enchantment); - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - return EnchantmentHelper.getEnchantments(itemStack).keySet().stream().map(EnchantAttribute::new).collect(Collectors.toList()); - } - - @Override - public String getTranslationKey() { - return "has_enchant"; - } - - @Override - public Object[] getTranslationParameters() { - String parameter = ""; - if(enchantment != null) - parameter = Components.translatable(enchantment.getDescriptionId()).getString(); - return new Object[] { parameter }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - if (enchantment == null) - return; - ResourceLocation id = ForgeRegistries.ENCHANTMENTS.getKey(enchantment); - if (id == null) - return; - nbt.putString("id", id.toString()); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return nbt.contains("id") ? new EnchantAttribute(ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(nbt.getString("id")))) : EMPTY; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/FluidContentsAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/FluidContentsAttribute.java deleted file mode 100644 index 4859953b3a..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/FluidContentsAttribute.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import javax.annotation.Nullable; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.registries.ForgeRegistries; - -public class FluidContentsAttribute implements ItemAttribute { - public static final FluidContentsAttribute EMPTY = new FluidContentsAttribute(null); - - private final Fluid fluid; - - public FluidContentsAttribute(@Nullable Fluid fluid) { - this.fluid = fluid; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - return extractFluids(itemStack).contains(fluid); - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - return extractFluids(itemStack).stream().map(FluidContentsAttribute::new).collect(Collectors.toList()); - } - - @Override - public String getTranslationKey() { - return "has_fluid"; - } - - @Override - public Object[] getTranslationParameters() { - String parameter = ""; - if (fluid != null) - parameter = fluid.getFluidType().getDescription().getString(); - return new Object[] { parameter }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - if (fluid == null) - return; - ResourceLocation id = ForgeRegistries.FLUIDS.getKey(fluid); - if (id == null) - return; - nbt.putString("id", id.toString()); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return nbt.contains("id") ? new FluidContentsAttribute(ForgeRegistries.FLUIDS.getValue(ResourceLocation.tryParse(nbt.getString("id")))) : EMPTY; - } - - private List extractFluids(ItemStack stack) { - List fluids = new ArrayList<>(); - - LazyOptional capability = - stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM); - - capability.ifPresent((cap) -> { - for(int i = 0; i < cap.getTanks(); i++) { - fluids.add(cap.getFluidInTank(i).getFluid()); - } - }); - - return fluids; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ItemNameAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ItemNameAttribute.java deleted file mode 100644 index 83bab8d968..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ItemNameAttribute.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute; - -import java.util.ArrayList; -import java.util.List; - -import com.google.gson.JsonParseException; -import com.simibubi.create.content.logistics.filter.ItemAttribute; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; - -public class ItemNameAttribute implements ItemAttribute { - String itemName; - - public ItemNameAttribute(String itemName) { - this.itemName = itemName; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - return extractCustomName(itemStack).equals(itemName); - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - String name = extractCustomName(itemStack); - - List atts = new ArrayList<>(); - if(name.length() > 0) { - atts.add(new ItemNameAttribute(name)); - } - return atts; - } - - @Override - public String getTranslationKey() { - return "has_name"; - } - - @Override - public Object[] getTranslationParameters() { - return new Object[] { itemName }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("name", this.itemName); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new ItemNameAttribute(nbt.getString("name")); - } - - private String extractCustomName(ItemStack stack) { - CompoundTag compoundnbt = stack.getTagElement("display"); - if (compoundnbt != null && compoundnbt.contains("Name", 8)) { - try { - Component itextcomponent = Component.Serializer.fromJson(compoundnbt.getString("Name")); - if (itextcomponent != null) { - return itextcomponent.getString(); - } - } catch (JsonParseException ignored) { - } - } - return ""; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ShulkerFillLevelAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ShulkerFillLevelAttribute.java deleted file mode 100644 index 9f0f20b064..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ShulkerFillLevelAttribute.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute; - -import java.util.Arrays; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import javax.annotation.Nullable; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.ShulkerBoxBlock; - -public class ShulkerFillLevelAttribute implements ItemAttribute { - public static final ShulkerFillLevelAttribute EMPTY = new ShulkerFillLevelAttribute(null); - - private final ShulkerLevels levels; - - public ShulkerFillLevelAttribute(ShulkerLevels levels) { - this.levels = levels; - } - - @Override - public boolean appliesTo(ItemStack stack) { - return levels != null && levels.canApply(stack); - } - - @Override - public List listAttributesOf(ItemStack stack) { - return Arrays.stream(ShulkerLevels.values()) - .filter(shulkerLevels -> shulkerLevels.canApply(stack)) - .map(ShulkerFillLevelAttribute::new) - .collect(Collectors.toList()); - } - - @Override - public String getTranslationKey() { - return "shulker_level"; - } - - @Override - public Object[] getTranslationParameters() { - String parameter = ""; - if (levels != null) - parameter = Lang.translateDirect("item_attributes." + getTranslationKey() + "." + levels.key).getString(); - return new Object[]{parameter}; - } - - @Override - public void writeNBT(CompoundTag nbt) { - if (levels != null) - nbt.putString("id", levels.key); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return nbt.contains("id") ? new ShulkerFillLevelAttribute(ShulkerLevels.fromKey(nbt.getString("id"))) : EMPTY; - } - - enum ShulkerLevels { - EMPTY("empty", amount -> amount == 0), - PARTIAL("partial", amount -> amount > 0 && amount < Integer.MAX_VALUE), - FULL("full", amount -> amount == Integer.MAX_VALUE); - - private final Predicate requiredSize; - private final String key; - - ShulkerLevels(String key, Predicate requiredSize) { - this.key = key; - this.requiredSize = requiredSize; - } - - @Nullable - public static ShulkerLevels fromKey(String key) { - return Arrays.stream(values()).filter(shulkerLevels -> shulkerLevels.key.equals(key)).findFirst().orElse(null); - } - - private static boolean isShulker(ItemStack stack) { - return Block.byItem(stack.getItem()) instanceof ShulkerBoxBlock; - } - - public boolean canApply(ItemStack testStack) { - if (!isShulker(testStack)) - return false; - CompoundTag compoundnbt = testStack.getTagElement("BlockEntityTag"); - if (compoundnbt == null) - return requiredSize.test(0); - if (compoundnbt.contains("LootTable", 8)) - return false; - if (compoundnbt.contains("Items", 9)) { - int rawSize = compoundnbt.getList("Items", 10).size(); - if (rawSize < 27) - return requiredSize.test(rawSize); - - NonNullList inventory = NonNullList.withSize(27, ItemStack.EMPTY); - ContainerHelper.loadAllItems(compoundnbt, inventory); - boolean isFull = inventory.stream().allMatch(itemStack -> !itemStack.isEmpty() && itemStack.getCount() == itemStack.getMaxStackSize()); - return requiredSize.test(isFull ? Integer.MAX_VALUE : rawSize); - } - return requiredSize.test(0); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java deleted file mode 100644 index 0bca33be94..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraftforge.registries.ForgeRegistries; - -public class AstralSorceryAmuletAttribute implements ItemAttribute { - String enchName; - int enchType; - - public AstralSorceryAmuletAttribute(String enchName, int enchType) { - this.enchName = enchName; - this.enchType = enchType; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - for (Tag trait : extractTraitList(itemStack)) { - if(((CompoundTag) trait).getString("ench").equals(this.enchName) - && ((CompoundTag)trait).getInt("type") == this.enchType) - return true; - } - return false; - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - ListTag traits = extractTraitList(itemStack); - List atts = new ArrayList<>(); - for (int i = 0; i < traits.size(); i++) { - atts.add(new AstralSorceryAmuletAttribute( - traits.getCompound(i).getString("ench"), - traits.getCompound(i).getInt("type"))); - } - return atts; - } - - @Override - public String getTranslationKey() { - return "astralsorcery_amulet"; - } - - @Override - public Object[] getTranslationParameters() { - String something = ""; - - Enchantment enchant = ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(enchName)); - if(enchant != null) { - something = Components.translatable(enchant.getDescriptionId()).getString(); - } - - if(enchType == 1) something = "existing " + something; - - return new Object[] { something }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("enchName", this.enchName); - nbt.putInt("enchType", this.enchType); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new AstralSorceryAmuletAttribute(nbt.getString("enchName"), nbt.getInt("enchType")); - } - - private ListTag extractTraitList(ItemStack stack) { - return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery").getList("amuletEnchantments", 10) : new ListTag(); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java deleted file mode 100644 index 139eefe699..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.registries.ForgeRegistries; - -public class AstralSorceryAttunementAttribute implements ItemAttribute { - String constellationName; - - public AstralSorceryAttunementAttribute(String constellationName) { - this.constellationName = constellationName; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - CompoundTag nbt = extractAstralNBT(itemStack); - String constellation = nbt.contains("constellation") ? nbt.getString("constellation") : nbt.getString("constellationName"); - - // Special handling for shifting stars - ResourceLocation itemResource = ForgeRegistries.ITEMS.getKey(itemStack.getItem()); - if (itemResource != null && itemResource.toString().contains("shifting_star_")) { - constellation = itemResource.toString().replace("shifting_star_", ""); - } - - return constellation.equals(constellationName); - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - CompoundTag nbt = extractAstralNBT(itemStack); - String constellation = nbt.contains("constellation") ? nbt.getString("constellation") : nbt.getString("constellationName"); - - // Special handling for shifting stars - ResourceLocation itemResource = ForgeRegistries.ITEMS.getKey(itemStack.getItem()); - if (itemResource != null && itemResource.toString().contains("shifting_star_")) { - constellation = itemResource.toString().replace("shifting_star_", ""); - } - - List atts = new ArrayList<>(); - if(constellation.length() > 0) { - atts.add(new AstralSorceryAttunementAttribute(constellation)); - } - return atts; - } - - @Override - public String getTranslationKey() { - return "astralsorcery_constellation"; - } - - @Override - public Object[] getTranslationParameters() { - ResourceLocation constResource = new ResourceLocation(constellationName); - String something = Components.translatable(String.format("%s.constellation.%s", constResource.getNamespace(), constResource.getPath())).getString(); - return new Object[] { something }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("constellation", this.constellationName); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new AstralSorceryAttunementAttribute(nbt.getString("constellation")); - } - - private CompoundTag extractAstralNBT(ItemStack stack) { - return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery") : new CompoundTag(); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java deleted file mode 100644 index d55d337714..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; - -public class AstralSorceryCrystalAttribute implements ItemAttribute { - String traitName; - - public AstralSorceryCrystalAttribute(String traitName) { - this.traitName = traitName; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - for (Tag trait : extractTraitList(itemStack)) { - if(((CompoundTag) trait).getString("property").equals(this.traitName)) - return true; - } - return false; - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - ListTag traits = extractTraitList(itemStack); - List atts = new ArrayList<>(); - for (int i = 0; i < traits.size(); i++) { - atts.add(new AstralSorceryCrystalAttribute(traits.getCompound(i).getString("property"))); - } - return atts; - } - - @Override - public String getTranslationKey() { - return "astralsorcery_crystal"; - } - - @Override - public Object[] getTranslationParameters() { - ResourceLocation traitResource = new ResourceLocation(traitName); - String something = Components.translatable(String.format("crystal.property.%s.%s.name", traitResource.getNamespace(), traitResource.getPath())).getString(); - return new Object[] { something }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("property", this.traitName); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new AstralSorceryCrystalAttribute(nbt.getString("property")); - } - - private ListTag extractTraitList(ItemStack stack) { - return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery").getCompound("crystalProperties").getList("attributes", 10) : new ListTag(); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java deleted file mode 100644 index 3e567c396a..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.logistics.filter.ItemAttribute; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; - -public class AstralSorceryPerkGemAttribute implements ItemAttribute { - String traitName; - - public AstralSorceryPerkGemAttribute(String traitName) { - this.traitName = traitName; - } - - @Override - public boolean appliesTo(ItemStack itemStack) { - for (Tag trait : extractTraitList(itemStack)) { - if(((CompoundTag) trait).getString("type").equals(this.traitName)) - return true; - } - return false; - } - - @Override - public List listAttributesOf(ItemStack itemStack) { - ListTag traits = extractTraitList(itemStack); - List atts = new ArrayList<>(); - for (int i = 0; i < traits.size(); i++) { - atts.add(new AstralSorceryPerkGemAttribute(traits.getCompound(i).getString("type"))); - } - return atts; - } - - @Override - public String getTranslationKey() { - return "astralsorcery_perk_gem"; - } - - @Override - public Object[] getTranslationParameters() { - ResourceLocation traitResource = new ResourceLocation(traitName); - String something = Components.translatable(String.format("perk.attribute.%s.%s.name", traitResource.getNamespace(), traitResource.getPath())).getString(); - return new Object[] { something }; - } - - @Override - public void writeNBT(CompoundTag nbt) { - nbt.putString("type", this.traitName); - } - - @Override - public ItemAttribute readNBT(CompoundTag nbt) { - return new AstralSorceryPerkGemAttribute(nbt.getString("type")); - } - - private ListTag extractTraitList(ItemStack stack) { - return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery").getList("attribute_modifiers", 10) : new ListTag(); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/flwdata/FlapInstance.java b/src/main/java/com/simibubi/create/content/logistics/flwdata/FlapInstance.java deleted file mode 100644 index 30e5251262..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/flwdata/FlapInstance.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.simibubi.create.content.logistics.flwdata; - -import org.joml.Vector3f; - -import dev.engine_room.flywheel.api.instance.InstanceHandle; -import dev.engine_room.flywheel.api.instance.InstanceType; -import dev.engine_room.flywheel.lib.instance.AbstractInstance; -import dev.engine_room.flywheel.lib.instance.FlatLit; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.core.BlockPos; - -public class FlapInstance extends AbstractInstance implements FlatLit { - - public float x; - public float y; - public float z; - public byte blockLight; - public byte skyLight; - public int packedLight; - public float segmentOffsetX; - public float segmentOffsetY; - public float segmentOffsetZ; - public float pivotX; - public float pivotY; - public float pivotZ; - public float horizontalAngle; - public float intensity; - public float flapScale; - public float flapness; - - public FlapInstance(InstanceType type, InstanceHandle handle) { - super(type, handle); - } - - - public FlapInstance setPosition(BlockPos pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); - } - - public FlapInstance setPosition(Vector3f pos) { - return setPosition(pos.x(), pos.y(), pos.z()); - } - - public FlapInstance setPosition(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - @Override - public FlapInstance light(int blockLight, int skyLight) { - return this.light(LightTexture.pack(blockLight, skyLight)); - } - - @Override - public FlapInstance light(int packedLight) { - this.packedLight = packedLight; - return this; - } - - public FlapInstance setSegmentOffset(float x, float y, float z) { - this.segmentOffsetX = x; - this.segmentOffsetY = y; - this.segmentOffsetZ = z; - return this; - } - - public FlapInstance setIntensity(float intensity) { - this.intensity = intensity; - return this; - } - - public FlapInstance setHorizontalAngle(float horizontalAngle) { - this.horizontalAngle = horizontalAngle; - return this; - } - - public FlapInstance setFlapScale(float flapScale) { - this.flapScale = flapScale; - return this; - } - - public FlapInstance setFlapness(float flapness) { - this.flapness = flapness; - return this; - } - - public FlapInstance setPivotVoxelSpace(float x, float y, float z) { - pivotX = x / 16f; - pivotY = y / 16f; - pivotZ = z / 16f; - return this; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/flwdata/package-info.java b/src/main/java/com/simibubi/create/content/logistics/flwdata/package-info.java deleted file mode 100644 index 5f4c5ce95a..0000000000 --- a/src/main/java/com/simibubi/create/content/logistics/flwdata/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.simibubi.create.content.logistics.flwdata; - -import javax.annotation.ParametersAreNonnullByDefault; - -import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractFunnelBlock.java index f24c093700..6d91e6b035 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractFunnelBlock.java @@ -32,6 +32,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientBlockExtensions; @@ -57,7 +58,7 @@ public abstract class AbstractFunnelBlock extends Block return withWater(defaultBlockState().setValue(POWERED, context.getLevel() .hasNeighborSignal(context.getClickedPos())), context); } - + @Override public FluidState getFluidState(BlockState pState) { return fluidState(pState); @@ -65,11 +66,11 @@ public abstract class AbstractFunnelBlock extends Block @Override public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, - LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { updateWater(pLevel, pState, pCurrentPos); return pState; } - + @Override public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { return false; @@ -81,16 +82,16 @@ public abstract class AbstractFunnelBlock extends Block } @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - if (worldIn.isClientSide) + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, + boolean isMoving) { + if (level.isClientSide) return; - InvManipulationBehaviour behaviour = BlockEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); + InvManipulationBehaviour behaviour = BlockEntityBehaviour.get(level, pos, InvManipulationBehaviour.TYPE); if (behaviour != null) behaviour.onNeighborChanged(fromPos); - if (!worldIn.getBlockTicks() + if (!level.getBlockTicks() .willTickThisTick(pos, this)) - worldIn.scheduleTick(pos, this, 0); + level.scheduleTick(pos, this, 1); } @Override @@ -113,8 +114,7 @@ public abstract class AbstractFunnelBlock extends Block if (!simulate && insert.getCount() != toInsert.getCount()) { BlockEntity blockEntity = worldIn.getBlockEntity(pos); - if (blockEntity instanceof FunnelBlockEntity) { - FunnelBlockEntity funnelBlockEntity = (FunnelBlockEntity) blockEntity; + if (blockEntity instanceof FunnelBlockEntity funnelBlockEntity) { funnelBlockEntity.onTransfer(toInsert); if (funnelBlockEntity.hasFlap()) funnelBlockEntity.flap(true); @@ -157,6 +157,8 @@ public abstract class AbstractFunnelBlock extends Block public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.FUNNEL.get(); - }; + } + + ; } diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelBlock.java index bdf48f6619..201152e2fd 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelBlock.java @@ -2,18 +2,18 @@ package com.simibubi.create.content.logistics.funnel; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.kinetics.belt.BeltBlock; import com.simibubi.create.content.kinetics.belt.BeltSlope; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VoxelShaper; import com.tterrag.registrate.util.entry.BlockEntry; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.StringRepresentable; @@ -37,7 +37,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements ISpecialBlockItemRequirement { +public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements SpecialBlockItemRequirement { private BlockEntry parent; @@ -75,14 +75,14 @@ public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements IS public boolean isOfSameType(FunnelBlock otherFunnel) { return parent.get() == otherFunnel; } - + @Override public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { if (newState.getBlock() instanceof FunnelBlock fb && isOfSameType(fb)) return; super.onRemove(state, world, pos, newState, isMoving); } - + @Override public VoxelShape getShape(BlockState state, BlockGetter p_220053_2_, BlockPos p_220053_3_, CollisionContext p_220053_4_) { diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlock.java index 460819ad93..ae5ff78b2c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlock.java @@ -3,10 +3,12 @@ package com.simibubi.create.content.logistics.funnel; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; +import com.simibubi.create.content.logistics.box.PackageEntity; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.item.ItemHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.AxisDirection; @@ -64,14 +66,14 @@ public abstract class FunnelBlock extends AbstractDirectionalFunnelBlock { protected void createBlockStateDefinition(Builder builder) { super.createBlockStateDefinition(builder.add(EXTRACTING)); } - + @Override public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { if (newState.getBlock() instanceof BeltFunnelBlock bfb && bfb.isOfSameType(this)) return; super.onRemove(state, world, pos, newState, isMoving); } - + @Override public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); @@ -114,31 +116,31 @@ public abstract class FunnelBlock extends AbstractDirectionalFunnelBlock { public void entityInside(BlockState state, Level worldIn, BlockPos pos, Entity entityIn) { if (worldIn.isClientSide) return; - if (!(entityIn instanceof ItemEntity)) + ItemStack stack = ItemHelper.fromItemEntity(entityIn); + if (stack.isEmpty()) return; if (!canInsertIntoFunnel(state)) return; - if (!entityIn.isAlive()) - return; - ItemEntity itemEntity = (ItemEntity) entityIn; Direction direction = getFunnelFacing(state); + Vec3 openPos = VecHelper.getCenterOf(pos) + .add(Vec3.atLowerCornerOf(direction.getNormal()) + .scale(entityIn instanceof ItemEntity ? -.25f : -.125f)); Vec3 diff = entityIn.position() - .subtract(VecHelper.getCenterOf(pos) - .add(Vec3.atLowerCornerOf(direction.getNormal()) - .scale(-.325f))); + .subtract(openPos); double projectedDiff = direction.getAxis() .choose(diff.x, diff.y, diff.z); if (projectedDiff < 0 == (direction.getAxisDirection() == AxisDirection.POSITIVE)) return; + float yOffset = direction == Direction.UP ? 0.25f : direction == Direction.DOWN ? -0.5f : -0.5f; + if (!PackageEntity.centerPackage(entityIn, openPos.add(0, yOffset, 0))) + return; - ItemStack toInsert = itemEntity.getItem(); - ItemStack remainder = tryInsert(worldIn, pos, toInsert, false); - + ItemStack remainder = tryInsert(worldIn, pos, stack, false); if (remainder.isEmpty()) - itemEntity.discard(); - if (remainder.getCount() < toInsert.getCount()) - itemEntity.setItem(remainder); + entityIn.discard(); + if (remainder.getCount() < stack.getCount() && entityIn instanceof ItemEntity) + ((ItemEntity) entityIn).setItem(remainder); } protected boolean canInsertIntoFunnel(BlockState state) { diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlockEntity.java index 733c8301d8..ce5283f707 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlockEntity.java @@ -8,11 +8,12 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.equipment.goggles.IHaveHoveringInformation; +import com.simibubi.create.api.equipment.goggles.IHaveHoveringInformation; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltHelper; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.box.PackageEntity; import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; @@ -21,16 +22,17 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import com.simibubi.create.infrastructure.config.AllConfigs; import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.math.BlockFace; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -38,6 +40,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; @@ -48,7 +51,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering private VersionedInventoryTrackerBehaviour invVersionTracker; private int extractionCooldown; - private WeakReference lastObserved; // In-world Extractors only + private WeakReference lastObserved; // In-world Extractors only LerpedFloat flap; @@ -131,7 +134,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering if (lastObserved == null) { trackingEntityPresent = false; } else { - ItemEntity lastEntity = lastObserved.get(); + Entity lastEntity = lastObserved.get(); if (lastEntity == null || !lastEntity.isAlive() || !lastEntity.getBoundingBox() .intersects(area)) { trackingEntityPresent = false; @@ -151,9 +154,11 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering invVersionTracker.awaitNewVersion(invManipulation); return; } - for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, area)) { - lastObserved = new WeakReference<>(itemEntity); - return; + for (Entity entity : level.getEntities(null, area)) { + if (entity instanceof ItemEntity || entity instanceof PackageEntity) { + lastObserved = new WeakReference<>(entity); + return; + } } // Extract @@ -187,7 +192,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering startCooldown(); } - static final AABB coreBB = new AABB(VecHelper.CENTER_OF_ORIGIN, VecHelper.CENTER_OF_ORIGIN).inflate(.75f); + static final AABB coreBB = new AABB(BlockPos.ZERO); private AABB getEntityOverflowScanningArea() { Direction facing = AbstractFunnelBlock.getFunnelFacing(getBlockState()); @@ -321,7 +326,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering AllPackets.getChannel() .send(packetTarget(), new FunnelFlapPacket(this, inward)); } else { - flap.setValue(inward ? 1 : -1); + flap.setValue(inward ? -1 : 1); AllSoundEvents.FUNNEL_FLAP.playAt(level, worldPosition, 1, 1, true); } } @@ -340,14 +345,14 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering if (!(blockState.getBlock() instanceof BeltFunnelBlock)) return -1 / 16f; switch (blockState.getValue(BeltFunnelBlock.SHAPE)) { - default: - case RETRACTED: - return 0; - case EXTENDED: - return 8 / 16f; - case PULLING: - case PUSHING: - return -2 / 16f; + default: + case RETRACTED: + return 0; + case EXTENDED: + return 8 / 16f; + case PULLING: + case PUSHING: + return -2 / 16f; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFilterSlotPositioning.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFilterSlotPositioning.java index 671d459261..53782f5a8b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFilterSlotPositioning.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFilterSlotPositioning.java @@ -3,19 +3,21 @@ package com.simibubi.create.content.logistics.funnel; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided { @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Direction side = getSide(); float horizontalAngle = AngleHelper.horizontalAngle(side); Direction funnelFacing = FunnelBlock.getFunnelFacing(state); @@ -45,19 +47,19 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided { } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { Direction facing = FunnelBlock.getFunnelFacing(state); if (facing.getAxis() .isVertical()) { - super.rotate(state, ms); + super.rotate(level, pos, state, ms); return; } boolean isBeltFunnel = state.getBlock() instanceof BeltFunnelBlock; if (isBeltFunnel && state.getValue(BeltFunnelBlock.SHAPE) != Shape.EXTENDED) { Shape shape = state.getValue(BeltFunnelBlock.SHAPE); - super.rotate(state, ms); + super.rotate(level, pos, state, ms); if (shape == Shape.PULLING || shape == Shape.PUSHING) TransformStack.of(ms) .rotateXDegrees(-22.5f); @@ -65,7 +67,7 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided { } if (state.getBlock() instanceof FunnelBlock) { - super.rotate(state, ms); + super.rotate(level, pos, state, ms); TransformStack.of(ms) .rotateXDegrees(-22.5f); return; diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java index 6f34f46b29..3f59735348 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java @@ -2,7 +2,7 @@ package com.simibubi.create.content.logistics.funnel; import java.util.List; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.logistics.filter.FilterItemStack; import com.simibubi.create.foundation.item.ItemHelper; @@ -16,6 +16,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.items.ItemHandlerHelper; public class FunnelMovementBehaviour implements MovementBehaviour { @@ -76,7 +77,7 @@ public class FunnelMovementBehaviour implements MovementBehaviour { boolean upTo = context.blockEntityData.getBoolean("UpTo"); filterAmount = hasFilter ? filterAmount : 1; - ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(), + ItemStack extract = ItemHelper.extract(context.contraption.getStorage().getAllItems(), s -> filter.test(world, s), upTo ? ItemHelper.ExtractionCountMode.UPTO : ItemHelper.ExtractionCountMode.EXACTLY, filterAmount, false); @@ -105,7 +106,7 @@ public class FunnelMovementBehaviour implements MovementBehaviour { if (!filter.test(context.world, toInsert)) continue; ItemStack remainder = - ItemHandlerHelper.insertItemStacked(context.contraption.getSharedInventory(), toInsert, false); + ItemHandlerHelper.insertItemStacked(context.contraption.getStorage().getAllItems(), toInsert, false); if (remainder.getCount() == toInsert.getCount()) continue; if (remainder.isEmpty()) { diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelRenderer.java index 4be0b1b428..298021e510 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelRenderer.java @@ -3,21 +3,17 @@ package com.simibubi.create.content.logistics.funnel; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.FlapStuffs; import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.lib.model.baked.PartialModel; -import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.util.Mth; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; public class FunnelRenderer extends SmartBlockEntityRenderer { @@ -37,40 +33,12 @@ public class FunnelRenderer extends SmartBlockEntityRenderer VertexConsumer vb = buffer.getBuffer(RenderType.solid()); PartialModel partialModel = (blockState.getBlock() instanceof FunnelBlock ? AllPartialModels.FUNNEL_FLAP : AllPartialModels.BELT_FUNNEL_FLAP); - SuperByteBuffer flapBuffer = CachedBufferer.partial(partialModel, blockState); - Vec3 pivot = VecHelper.voxelSpace(0, 10, 9.5f); - var msr = TransformStack.of(ms); + SuperByteBuffer flapBuffer = CachedBuffers.partial(partialModel, blockState); - float horizontalAngle = AngleHelper.horizontalAngle(FunnelBlock.getFunnelFacing(blockState) - .getOpposite()); + var funnelFacing = FunnelBlock.getFunnelFacing(blockState); float f = be.flap.getValue(partialTicks); - ms.pushPose(); - msr.center() - .rotateYDegrees(horizontalAngle) - .uncenter(); - ms.translate(0.075f / 16f, 0, -be.getFlapOffset()); - - for (int segment = 0; segment <= 3; segment++) { - ms.pushPose(); - - float intensity = segment == 3 ? 1.5f : segment + 1; - float abs = Math.abs(f); - float flapAngle = Mth.sin((float) ((1 - abs) * Math.PI * intensity)) * 30 * -f; - if (f > 0) - flapAngle *= .5f; - - msr.translate(pivot) - .rotateXDegrees(flapAngle) - .translateBack(pivot); - - flapBuffer.light(light) - .renderInto(ms, vb); - - ms.popPose(); - ms.translate(-3.05f / 16f, 0, 0); - } - ms.popPose(); + FlapStuffs.renderFlaps(ms, vb, flapBuffer, FlapStuffs.FUNNEL_PIVOT, funnelFacing, f, -be.getFlapOffset(), light); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelVisual.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelVisual.java index 3dd2bb7f8e..6265eb5529 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelVisual.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelVisual.java @@ -1,98 +1,65 @@ package com.simibubi.create.content.logistics.funnel; -import java.util.ArrayList; import java.util.function.Consumer; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.logistics.flwdata.FlapInstance; -import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.content.logistics.FlapStuffs; import dev.engine_room.flywheel.api.instance.Instance; -import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.instance.AbstractInstance; -import dev.engine_room.flywheel.lib.instance.FlatLit; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; -import net.minecraft.core.Direction; -import net.minecraft.world.level.LightLayer; public class FunnelVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { - private final ArrayList flaps; + private final FlapStuffs.Visual flaps; public FunnelVisual(VisualizationContext context, FunnelBlockEntity blockEntity, float partialTick) { super(context, blockEntity, partialTick); - flaps = new ArrayList<>(4); - - if (!blockEntity.hasFlap()) return; + if (!blockEntity.hasFlap()) { + flaps = null; + return; + } + var funnelFacing = FunnelBlock.getFunnelFacing(blockState); PartialModel flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllPartialModels.FUNNEL_FLAP - : AllPartialModels.BELT_FUNNEL_FLAP); - Instancer model = instancerProvider().instancer(AllInstanceTypes.FLAP, Models.partial(flapPartial)); + : AllPartialModels.BELT_FUNNEL_FLAP); - int blockLight = level.getBrightness(LightLayer.BLOCK, pos); - int skyLight = level.getBrightness(LightLayer.SKY, pos); + var commonTransform = FlapStuffs.commonTransform(getVisualPosition(), funnelFacing, -blockEntity.getFlapOffset()); + flaps = new FlapStuffs.Visual(instancerProvider(), commonTransform, FlapStuffs.FUNNEL_PIVOT, Models.partial(flapPartial)); - Direction direction = FunnelBlock.getFunnelFacing(blockState); - - float flapness = blockEntity.flap.getValue(AnimationTickHolder.getPartialTicks()); - float horizontalAngle = direction.getOpposite().toYRot(); - - for (int segment = 0; segment <= 3; segment++) { - float intensity = segment == 3 ? 1.5f : segment + 1; - float segmentOffset = -3.05f / 16f * segment + 0.075f / 16f; - - FlapInstance key = model.createInstance(); - - key.setPosition(getVisualPosition()) - .setSegmentOffset(segmentOffset, 0, -blockEntity.getFlapOffset()) - .light(blockLight, skyLight) - .setHorizontalAngle(horizontalAngle) - .setFlapness(flapness) - .setFlapScale(-1) - .setPivotVoxelSpace(0, 10, 9.5f) - .setIntensity(intensity) - .setChanged(); - - flaps.add(key); - } - } + flaps.update(blockEntity.flap.getValue(partialTick)); + } @Override public void beginFrame(DynamicVisual.Context ctx) { if (flaps == null) return; - float flapness = blockEntity.flap.getValue(ctx.partialTick()); - - for (FlapInstance flap : flaps) { - flap.setFlapness(flapness) - .setChanged(); - } + flaps.update(blockEntity.flap.getValue(ctx.partialTick())); } @Override public void updateLight(float partialTick) { if (flaps != null) - relight(flaps.toArray(FlatLit[]::new)); + flaps.updateLight(computePackedLight()); } @Override protected void _delete() { - if (flaps == null) return; + if (flaps == null) return; - flaps.forEach(AbstractInstance::delete); + flaps.delete(); } @Override public void collectCrumblingInstances(Consumer consumer) { if (flaps == null) return; - flaps.forEach(consumer); + flaps.collectCrumblingInstances(consumer); } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/AllItemAttributeTypes.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/AllItemAttributeTypes.java new file mode 100644 index 0000000000..100eb1f024 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/AllItemAttributeTypes.java @@ -0,0 +1,121 @@ +package com.simibubi.create.content.logistics.item.filter.attribute; + +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.Create; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.AddedByAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.BookAuthorAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.BookCopyAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.ColorAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.EnchantAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.FluidContentsAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.InItemGroupAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.InTagAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.ItemNameAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.ShulkerFillLevelAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery.AstralSorceryAmuletAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery.AstralSorceryAttunementAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery.AstralSorceryCrystalAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery.AstralSorceryPerkGemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.legacydeserializers.AllItemAttributeLegacyDeserializers; + +import net.minecraft.core.Registry; +import net.minecraft.world.Container; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.ComposterBlock; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; + +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +// TODO - Documentation +public class AllItemAttributeTypes { + private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); + + public static final ItemAttributeType + PLACEABLE = singleton("placeable", s -> s.getItem() instanceof BlockItem), + CONSUMABLE = singleton("consumable", ItemStack::isEdible), + FLUID_CONTAINER = singleton("fluid_container", s -> s.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM) + .isPresent()), + ENCHANTED = singleton("enchanted", ItemStack::isEnchanted), + MAX_ENCHANTED = singleton("max_enchanted", AllItemAttributeTypes::maxEnchanted), + RENAMED = singleton("renamed", ItemStack::hasCustomHoverName), + DAMAGED = singleton("damaged", ItemStack::isDamaged), + BADLY_DAMAGED = singleton("badly_damaged", s -> s.isDamaged() && (float) s.getDamageValue() / s.getMaxDamage() > 3 / 4f), + NOT_STACKABLE = singleton("not_stackable", ((Predicate) ItemStack::isStackable).negate()), + EQUIPABLE = singleton("equipable", s -> LivingEntity.getEquipmentSlotForItem(s) + .getType() != EquipmentSlot.Type.HAND), + FURNACE_FUEL = singleton("furnace_fuel", AbstractFurnaceBlockEntity::isFuel), + WASHABLE = singleton("washable", AllFanProcessingTypes.SPLASHING::canProcess), + HAUNTABLE = singleton("hauntable", AllFanProcessingTypes.HAUNTING::canProcess), + CRUSHABLE = singleton("crushable", (s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType()) + || testRecipe(s, w, AllRecipeTypes.MILLING.getType())), + SMELTABLE = singleton("smeltable", (s, w) -> testRecipe(s, w, RecipeType.SMELTING)), + SMOKABLE = singleton("smokable", (s, w) -> testRecipe(s, w, RecipeType.SMOKING)), + BLASTABLE = singleton("blastable", (s, w) -> testRecipe(s, w, RecipeType.BLASTING)), + COMPOSTABLE = singleton("compostable", s -> ComposterBlock.COMPOSTABLES.containsKey(s.getItem())), + + IN_TAG = register("in_tag", new InTagAttribute.Type()), + IN_ITEM_GROUP = register("in_item_group", new InItemGroupAttribute.Type()), + ADDED_BY = register("added_by", new AddedByAttribute.Type()), + HAS_ENCHANT = register("has_enchant", new EnchantAttribute.Type()), + SHULKER_FILL_LEVEL = register("shulker_fill_level", new ShulkerFillLevelAttribute.Type()), + HAS_COLOR = register("has_color", new ColorAttribute.Type()), + HAS_FLUID = register("has_fluid", new FluidContentsAttribute.Type()), + HAS_NAME = register("has_name", new ItemNameAttribute.Type()), + BOOK_AUTHOR = register("book_author", new BookAuthorAttribute.Type()), + BOOK_COPY = register("book_copy", new BookCopyAttribute.Type()), + + ASTRAL_AMULET = register("astral_amulet", new AstralSorceryAmuletAttribute.Type()), + ASTRAL_ATTUNMENT = register("astral_attunment", new AstralSorceryAttunementAttribute.Type()), + ASTRAL_CRYSTAL = register("astral_crystal", new AstralSorceryCrystalAttribute.Type()), + ASTRAL_PERK_GEM = register("astral_perk_gem", new AstralSorceryPerkGemAttribute.Type()); + + static { + // Register legacy deserializers to maintain backwards compatability + AllItemAttributeLegacyDeserializers.register(); + } + + private static > boolean testRecipe(ItemStack s, Level w, RecipeType type) { + RECIPE_WRAPPER.setItem(0, s.copy()); + return w.getRecipeManager() + .getRecipeFor(type, RECIPE_WRAPPER, w) + .isPresent(); + } + + private static boolean maxEnchanted(ItemStack s) { + return EnchantmentHelper.getEnchantments(s) + .entrySet() + .stream() + .anyMatch(e -> e.getKey() + .getMaxLevel() <= e.getValue()); + } + + private static ItemAttributeType singleton(String id, Predicate predicate) { + return register(id, new SingletonItemAttribute.Type(type -> new SingletonItemAttribute(type, (stack, level) -> predicate.test(stack), id))); + } + + private static ItemAttributeType singleton(String id, BiPredicate predicate) { + return register(id, new SingletonItemAttribute.Type(type -> new SingletonItemAttribute(type, predicate, id))); + } + + private static ItemAttributeType register(String id, ItemAttributeType type) { + return Registry.register(CreateBuiltInRegistries.ITEM_ATTRIBUTE_TYPE, Create.asResource(id), type); + } + + public static void init() { + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemAttribute.java new file mode 100644 index 0000000000..e611e94258 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemAttribute.java @@ -0,0 +1,94 @@ +package com.simibubi.create.content.logistics.item.filter.attribute; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.registry.CreateBuiltInRegistries; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface ItemAttribute { + static CompoundTag saveStatic(ItemAttribute attribute) { + CompoundTag nbt = new CompoundTag(); + ResourceLocation id = CreateBuiltInRegistries.ITEM_ATTRIBUTE_TYPE.getKey(attribute.getType()); + + if (id == null) + throw new IllegalArgumentException("Cannot get " + attribute.getType() + " as it does not exist in AllRegistries.ITEM_ATTRIBUTE_TYPES"); + + nbt.putString("attributeId", id.toString()); + attribute.save(nbt); + return nbt; + } + + @Nullable + static ItemAttribute loadStatic(CompoundTag nbt) { + for (LegacyDeserializer deserializer : LegacyDeserializer.ALL) { + if (deserializer.canRead(nbt)) { + return deserializer.readNBT(nbt.getCompound(deserializer.getNBTKey())); + } + } + + ResourceLocation id = ResourceLocation.tryParse(nbt.getString("attributeId")); + if (id == null) + return null; + + ItemAttributeType type = CreateBuiltInRegistries.ITEM_ATTRIBUTE_TYPE.get(id); + if (type == null) + return null; + + ItemAttribute attribute = type.createAttribute(); + attribute.load(nbt); + return attribute; + } + + static List getAllAttributes(ItemStack stack, Level level) { + List attributes = new ArrayList<>(); + for (ItemAttributeType type : CreateBuiltInRegistries.ITEM_ATTRIBUTE_TYPE) { + attributes.addAll(type.getAllAttributes(stack, level)); + } + return attributes; + } + + boolean appliesTo(ItemStack stack, Level world); + + ItemAttributeType getType(); + + void save(CompoundTag nbt); + + void load(CompoundTag nbt); + + @OnlyIn(value = Dist.CLIENT) + default MutableComponent format(boolean inverted) { + return CreateLang.translateDirect("item_attributes." + getTranslationKey() + (inverted ? ".inverted" : ""), + getTranslationParameters()); + } + + String getTranslationKey(); + + default Object[] getTranslationParameters() { + return new String[0]; + } + + @Deprecated + interface LegacyDeserializer { + List ALL = new ArrayList<>(); + + default boolean canRead(CompoundTag nbt) { + return nbt.contains(getNBTKey()); + } + + String getNBTKey(); + + ItemAttribute readNBT(CompoundTag nbt); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemAttributeType.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemAttributeType.java new file mode 100644 index 0000000000..7092ca4a93 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemAttributeType.java @@ -0,0 +1,14 @@ +package com.simibubi.create.content.logistics.item.filter.attribute; + +import java.util.List; + +import org.jetbrains.annotations.NotNull; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public interface ItemAttributeType { + @NotNull ItemAttribute createAttribute(); + + List getAllAttributes(ItemStack stack, Level level); +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/SingletonItemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/SingletonItemAttribute.java new file mode 100644 index 0000000000..3d797be983 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/SingletonItemAttribute.java @@ -0,0 +1,67 @@ +package com.simibubi.create.content.logistics.item.filter.attribute; + +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Function; + +import org.jetbrains.annotations.NotNull; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public final class SingletonItemAttribute implements ItemAttribute { + private final Type type; + private final BiPredicate predicate; + private final String translationKey; + + public SingletonItemAttribute(Type type, BiPredicate predicate, String translationKey) { + this.type = type; + this.predicate = predicate; + this.translationKey = translationKey; + } + + @Override + public boolean appliesTo(ItemStack stack, Level world) { + return predicate.test(stack, world); + } + + @Override + public ItemAttributeType getType() { + return type; + } + + @Override + public void save(CompoundTag nbt) { + } // NO-OP + + @Override + public void load(CompoundTag nbt) { + } // NO-OP + + @Override + public String getTranslationKey() { + return translationKey; + } + + public static final class Type implements ItemAttributeType { + private final SingletonItemAttribute attribute; + + public Type(Function singletonFunc) { + this.attribute = singletonFunc.apply(this); + } + + @Override + public @NotNull ItemAttribute createAttribute() { + return attribute; + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + if (attribute.appliesTo(stack, level)) { + return List.of(attribute); + } + return List.of(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/AddedByAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/AddedByAttribute.java new file mode 100644 index 0000000000..919b826963 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/AddedByAttribute.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.forgespi.language.IModInfo; + +public class AddedByAttribute implements ItemAttribute { + private String modId; + + public AddedByAttribute(String modId) { + this.modId = modId; + } + + @Override + public boolean appliesTo(ItemStack stack, Level world) { + return modId.equals(stack.getItem() + .getCreatorModId(stack)); + } + + @Override + public String getTranslationKey() { + return "added_by"; + } + + @Override + public Object[] getTranslationParameters() { + Optional modContainerById = ModList.get() + .getModContainerById(modId); + String name = modContainerById.map(ModContainer::getModInfo) + .map(IModInfo::getDisplayName) + .orElse(StringUtils.capitalize(modId)); + return new Object[]{name}; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putString("modId", modId); + } + + @Override + public void load(CompoundTag nbt) { + modId = nbt.getString("modId"); + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.ADDED_BY; + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new AddedByAttribute("dummy"); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + String id = stack.getItem() + .getCreatorModId(stack); + return id == null ? Collections.emptyList() : List.of(new AddedByAttribute(id)); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/BookAuthorAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/BookAuthorAttribute.java new file mode 100644 index 0000000000..be9b18771b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/BookAuthorAttribute.java @@ -0,0 +1,79 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class BookAuthorAttribute implements ItemAttribute { + private String author; + + public BookAuthorAttribute(String author) { + this.author = author; + } + + private static String extractAuthor(ItemStack stack) { + CompoundTag nbt = stack.getTag(); + if (nbt != null && nbt.contains("author")) { + return nbt.getString("author"); + } + return ""; + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + return extractAuthor(itemStack).equals(author); + } + + @Override + public String getTranslationKey() { + return "book_author"; + } + + @Override + public Object[] getTranslationParameters() { + return new Object[]{author}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.BOOK_AUTHOR; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putString("author", author); + } + + @Override + public void load(CompoundTag nbt) { + author = nbt.getString("author"); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new BookAuthorAttribute("dummy"); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + String name = BookAuthorAttribute.extractAuthor(stack); + if (!name.isEmpty()) { + list.add(new BookAuthorAttribute(name)); + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/BookCopyAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/BookCopyAttribute.java new file mode 100644 index 0000000000..5128e71379 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/BookCopyAttribute.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.WrittenBookItem; +import net.minecraft.world.level.Level; + +public class BookCopyAttribute implements ItemAttribute { + private int generation; + + public BookCopyAttribute(int generation) { + this.generation = generation; + } + + private static int extractGeneration(ItemStack stack) { + CompoundTag nbt = stack.getTag(); + if (nbt != null && stack.getItem() instanceof WrittenBookItem) { + return nbt.getInt("generation"); + } + return -1; + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + return extractGeneration(itemStack) == generation; + } + + @Override + public String getTranslationKey() { + return switch (generation) { + case 0 -> "book_copy_original"; + case 1 -> "book_copy_first"; + case 2 -> "book_copy_second"; + default -> "book_copy_tattered"; + }; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.BOOK_COPY; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putInt("generation", generation); + } + + @Override + public void load(CompoundTag nbt) { + generation = nbt.getInt("generation"); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new BookCopyAttribute(-1); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + int generation = BookCopyAttribute.extractGeneration(stack); + if (generation >= 0) { + list.add(new BookCopyAttribute(generation)); + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ColorAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ColorAttribute.java new file mode 100644 index 0000000000..74d4c2cc30 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ColorAttribute.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; + +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.createmod.catnip.platform.CatnipServices; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.FireworkRocketItem; +import net.minecraft.world.item.FireworkStarItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +import org.jetbrains.annotations.NotNull; + +public class ColorAttribute implements ItemAttribute { + private DyeColor color; + + public ColorAttribute(DyeColor color) { + this.color = color; + } + + private static Collection findMatchingDyeColors(ItemStack stack) { + CompoundTag nbt = stack.getTag(); + + DyeColor color = DyeColor.getColor(stack); + if (color != null) + return Collections.singletonList(color); + + Set colors = new HashSet<>(); + if (stack.getItem() instanceof FireworkRocketItem && nbt != null) { + ListTag listnbt = nbt.getCompound("Fireworks").getList("Explosions", 10); + for (int i = 0; i < listnbt.size(); i++) { + colors.addAll(getFireworkStarColors(listnbt.getCompound(i))); + } + } + + if (stack.getItem() instanceof FireworkStarItem && nbt != null) { + colors.addAll(getFireworkStarColors(nbt.getCompound("Explosion"))); + } + + Arrays.stream(DyeColor.values()).filter(c -> CatnipServices.REGISTRIES.getKeyOrThrow(stack.getItem()).getPath().startsWith(c.getName() + "_")).forEach(colors::add); + + return colors; + } + + private static Collection getFireworkStarColors(CompoundTag compound) { + Set colors = new HashSet<>(); + Arrays.stream(compound.getIntArray("Colors")).mapToObj(DyeColor::byFireworkColor).forEach(colors::add); + Arrays.stream(compound.getIntArray("FadeColors")).mapToObj(DyeColor::byFireworkColor).forEach(colors::add); + return colors; + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + return findMatchingDyeColors(itemStack).stream().anyMatch(color::equals); + } + + @Override + public String getTranslationKey() { + return "color"; + } + + @Override + public Object[] getTranslationParameters() { + return new Object[]{I18n.get("color.minecraft." + color.getName())}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.HAS_COLOR; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putInt("color", color.getId()); + } + + @Override + public void load(CompoundTag nbt) { + if (nbt.contains("color")) { + color = DyeColor.byId(nbt.getInt("color")); + } + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new ColorAttribute(DyeColor.PURPLE); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + for (DyeColor color : ColorAttribute.findMatchingDyeColors(stack)) { + list.add(new ColorAttribute(color)); + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/EnchantAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/EnchantAttribute.java new file mode 100644 index 0000000000..69ff34af90 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/EnchantAttribute.java @@ -0,0 +1,89 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.List; + +import net.createmod.catnip.nbt.NBTHelper; + +import net.minecraft.network.chat.Component; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.Level; +import net.minecraftforge.registries.ForgeRegistries; + +public class EnchantAttribute implements ItemAttribute { + private @Nullable Enchantment enchantment; + + public EnchantAttribute(@Nullable Enchantment enchantment) { + this.enchantment = enchantment; + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + return EnchantmentHelper.getEnchantments(itemStack).containsKey(enchantment); + } + + @Override + public String getTranslationKey() { + return "has_enchant"; + } + + @Override + public Object[] getTranslationParameters() { + String parameter = ""; + if (enchantment != null) + parameter = Component.translatable(enchantment.getDescriptionId()).getString(); + return new Object[]{parameter}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.HAS_ENCHANT; + } + + @Override + public void save(CompoundTag nbt) { + if (enchantment == null) + return; + ResourceLocation id = ForgeRegistries.ENCHANTMENTS.getKey(enchantment); + if (id == null) + return; + NBTHelper.writeResourceLocation(nbt, "enchantId", id); + } + + @Override + public void load(CompoundTag nbt) { + if (nbt.contains("enchantId")) { + enchantment = ForgeRegistries.ENCHANTMENTS.getValue(NBTHelper.readResourceLocation(nbt, "enchantId")); + } + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new EnchantAttribute(null); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + for (Enchantment enchantment : EnchantmentHelper.getEnchantments(stack).keySet()) { + list.add(new EnchantAttribute(enchantment)); + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/FluidContentsAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/FluidContentsAttribute.java new file mode 100644 index 0000000000..a7fe751788 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/FluidContentsAttribute.java @@ -0,0 +1,102 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.registries.ForgeRegistries; + +public class FluidContentsAttribute implements ItemAttribute { + private @Nullable Fluid fluid; + + public FluidContentsAttribute(@Nullable Fluid fluid) { + this.fluid = fluid; + } + + private static List extractFluids(ItemStack stack) { + List fluids = new ArrayList<>(); + + LazyOptional capability = + stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM); + + capability.ifPresent((cap) -> { + for (int i = 0; i < cap.getTanks(); i++) { + fluids.add(cap.getFluidInTank(i).getFluid()); + } + }); + + return fluids; + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + return extractFluids(itemStack).contains(fluid); + } + + @Override + public String getTranslationKey() { + return "has_fluid"; + } + + @Override + public Object[] getTranslationParameters() { + String parameter = ""; + if (fluid != null) + parameter = fluid.getFluidType().getDescription().getString(); + return new Object[]{parameter}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.HAS_FLUID; + } + + @Override + public void save(CompoundTag nbt) { + if (fluid == null) + return; + ResourceLocation id = ForgeRegistries.FLUIDS.getKey(fluid); + if (id == null) + return; + nbt.putString("fluidId", id.toString()); + } + + @Override + public void load(CompoundTag nbt) { + if (nbt.contains("fluidId")) { + fluid = ForgeRegistries.FLUIDS.getValue(ResourceLocation.tryParse(nbt.getString("fluidId"))); + } + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new FluidContentsAttribute(null); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + for (Fluid fluid : extractFluids(stack)) { + list.add(new FluidContentsAttribute(fluid)); + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/InItemGroupAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/InItemGroupAttribute.java new file mode 100644 index 0000000000..47778fc7fc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/InItemGroupAttribute.java @@ -0,0 +1,109 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.CreativeModeTabs; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.CreativeModeTabRegistry; + +public class InItemGroupAttribute implements ItemAttribute { + private CreativeModeTab group; + + public InItemGroupAttribute(CreativeModeTab group) { + this.group = group; + } + + private static boolean tabContainsItem(CreativeModeTab tab, ItemStack stack) { + return tab.contains(stack) || tab.contains(new ItemStack(stack.getItem())); + } + + @Override + public boolean appliesTo(ItemStack stack, Level world) { + if (group == null) + return false; + + if (group.getDisplayItems() + .isEmpty() + && group.getSearchTabDisplayItems() + .isEmpty()) { + + try { + group.buildContents(new CreativeModeTab.ItemDisplayParameters(world.enabledFeatures(), false, + world.registryAccess())); + } catch (RuntimeException | LinkageError e) { + Create.LOGGER.error("Attribute Filter: Item Group {} crashed while building contents.", + group.getDisplayName().getString(), e); + group = null; + return false; + } + + } + + return tabContainsItem(group, stack); + } + + @Override + public String getTranslationKey() { + return "in_item_group"; + } + + @Override + public Object[] getTranslationParameters() { + return new Object[]{group == null ? "" : group.getDisplayName().getString()}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.IN_ITEM_GROUP; + } + + @Override + public void save(CompoundTag nbt) { + if (group != null) { + ResourceLocation groupId = CreativeModeTabRegistry.getName(group); + + if (groupId != null) { + nbt.putString("group", groupId.toString()); + } + } + } + + @Override + public void load(CompoundTag nbt) { + if (nbt.contains("group")) { + group = CreativeModeTabRegistry.getTab(new ResourceLocation(nbt.getString("group"))); + } + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new InItemGroupAttribute(null); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + for (CreativeModeTab tab : CreativeModeTabs.tabs()) { + if (tab.getType() == CreativeModeTab.Type.CATEGORY && tabContainsItem(tab, stack)) { + list.add(new InItemGroupAttribute(tab)); + } + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/InTagAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/InTagAttribute.java new file mode 100644 index 0000000000..14fe5a71ff --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/InTagAttribute.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.List; +import java.util.stream.Collectors; + +import net.createmod.catnip.nbt.NBTHelper; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.tags.ItemTags; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class InTagAttribute implements ItemAttribute { + @ApiStatus.Internal + public TagKey tag; + + public InTagAttribute(TagKey tag) { + this.tag = tag; + } + + @Override + public boolean appliesTo(ItemStack stack, Level level) { + return stack.is(tag); + } + + @Override + public String getTranslationKey() { + return "in_tag"; + } + + @Override + public Object[] getTranslationParameters() { + return new Object[]{"#" + tag.location()}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.IN_TAG; + } + + @Override + public void save(CompoundTag nbt) { + NBTHelper.writeResourceLocation(nbt, "tag", tag.location()); + } + + @Override + public void load(CompoundTag nbt) { + tag = ItemTags.create(NBTHelper.readResourceLocation(nbt, "tag")); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new InTagAttribute(ItemTags.LOGS); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + return stack.getTags() + .map(InTagAttribute::new) + .collect(Collectors.toList()); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ItemNameAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ItemNameAttribute.java new file mode 100644 index 0000000000..d05f6d3978 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ItemNameAttribute.java @@ -0,0 +1,87 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.NotNull; + +import com.google.gson.JsonParseException; +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class ItemNameAttribute implements ItemAttribute { + private String itemName; + + public ItemNameAttribute(String itemName) { + this.itemName = itemName; + } + + private static String extractCustomName(ItemStack stack) { + CompoundTag compoundnbt = stack.getTagElement("display"); + if (compoundnbt != null && compoundnbt.contains("Name", 8)) { + try { + Component itextcomponent = Component.Serializer.fromJson(compoundnbt.getString("Name")); + if (itextcomponent != null) { + return itextcomponent.getString(); + } + } catch (JsonParseException ignored) { + } + } + return ""; + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + return extractCustomName(itemStack).equals(itemName); + } + + @Override + public String getTranslationKey() { + return "has_name"; + } + + @Override + public Object[] getTranslationParameters() { + return new Object[]{itemName}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.HAS_NAME; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putString("name", itemName); + } + + @Override + public void load(CompoundTag nbt) { + itemName = nbt.getString("name"); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new ItemNameAttribute("dummy"); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + String name = extractCustomName(stack); + if (!name.isEmpty()) { + list.add(new ItemNameAttribute(name)); + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ShulkerFillLevelAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ShulkerFillLevelAttribute.java new file mode 100644 index 0000000000..2f68bd8575 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/ShulkerFillLevelAttribute.java @@ -0,0 +1,131 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; + +import javax.annotation.Nullable; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.ShulkerBoxBlock; + +public class ShulkerFillLevelAttribute implements ItemAttribute { + private ShulkerLevels levels; + + public ShulkerFillLevelAttribute(ShulkerLevels levels) { + this.levels = levels; + } + + @Override + public boolean appliesTo(ItemStack stack, Level level) { + return levels != null && levels.canApply(stack); + } + + @Override + public String getTranslationKey() { + return "shulker_level"; + } + + @Override + public Object[] getTranslationParameters() { + String parameter = ""; + if (levels != null) + parameter = CreateLang.translateDirect("item_attributes." + getTranslationKey() + "." + levels.key).getString(); + return new Object[]{parameter}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.SHULKER_FILL_LEVEL; + } + + @Override + public void save(CompoundTag nbt) { + if (levels != null) + nbt.putString("level", levels.key); + } + + @Override + public void load(CompoundTag nbt) { + if (nbt.contains("level")) { + levels = ShulkerLevels.fromKey(nbt.getString("level")); + } + } + + public enum ShulkerLevels { + EMPTY("empty", amount -> amount == 0), + PARTIAL("partial", amount -> amount > 0 && amount < Integer.MAX_VALUE), + FULL("full", amount -> amount == Integer.MAX_VALUE); + + private final Predicate requiredSize; + private final String key; + + ShulkerLevels(String key, Predicate requiredSize) { + this.key = key; + this.requiredSize = requiredSize; + } + + @Nullable + public static ShulkerFillLevelAttribute.ShulkerLevels fromKey(String key) { + return Arrays.stream(values()).filter(shulkerLevels -> shulkerLevels.key.equals(key)).findFirst().orElse(null); + } + + private static boolean isShulker(ItemStack stack) { + return Block.byItem(stack.getItem()) instanceof ShulkerBoxBlock; + } + + public boolean canApply(ItemStack testStack) { + if (!isShulker(testStack)) + return false; + CompoundTag compoundnbt = testStack.getTagElement("BlockEntityTag"); + if (compoundnbt == null) + return requiredSize.test(0); + if (compoundnbt.contains("LootTable", 8)) + return false; + if (compoundnbt.contains("Items", 9)) { + int rawSize = compoundnbt.getList("Items", 10).size(); + if (rawSize < 27) + return requiredSize.test(rawSize); + + NonNullList inventory = NonNullList.withSize(27, ItemStack.EMPTY); + ContainerHelper.loadAllItems(compoundnbt, inventory); + boolean isFull = inventory.stream().allMatch(itemStack -> !itemStack.isEmpty() && itemStack.getCount() == itemStack.getMaxStackSize()); + return requiredSize.test(isFull ? Integer.MAX_VALUE : rawSize); + } + return requiredSize.test(0); + } + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new ShulkerFillLevelAttribute(null); + } + + @Override + public List getAllAttributes(ItemStack stack, Level level) { + List list = new ArrayList<>(); + + for (ShulkerLevels shulkerLevels : ShulkerLevels.values()) { + if (shulkerLevels.canApply(stack)) { + list.add(new ShulkerFillLevelAttribute(shulkerLevels)); + } + } + + return list; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryAmuletAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryAmuletAttribute.java new file mode 100644 index 0000000000..9fd2bc5bcf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryAmuletAttribute.java @@ -0,0 +1,101 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; + +import net.minecraft.network.chat.Component; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.level.Level; +import net.minecraftforge.registries.ForgeRegistries; + +public class AstralSorceryAmuletAttribute implements ItemAttribute { + String enchName; + int enchType; + + public AstralSorceryAmuletAttribute(String enchName, int enchType) { + this.enchName = enchName; + this.enchType = enchType; + } + + private static ListTag extractTraitList(ItemStack stack) { + return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery").getList("amuletEnchantments", 10) : new ListTag(); + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + for (Tag trait : extractTraitList(itemStack)) { + if (((CompoundTag) trait).getString("ench").equals(this.enchName) + && ((CompoundTag) trait).getInt("type") == this.enchType) + return true; + } + return false; + } + + @Override + public String getTranslationKey() { + return "astralsorcery_amulet"; + } + + @Override + public Object[] getTranslationParameters() { + String something = ""; + + Enchantment enchant = ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(enchName)); + if (enchant != null) { + something = Component.translatable(enchant.getDescriptionId()).getString(); + } + + if (enchType == 1) something = "existing " + something; + + return new Object[]{something}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.ASTRAL_AMULET; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putString("enchName", enchName); + nbt.putInt("enchType", enchType); + } + + @Override + public void load(CompoundTag nbt) { + enchName = nbt.getString("enchName"); + enchType = nbt.getInt("enchType"); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new AstralSorceryAmuletAttribute("dummy", -1); + } + + @Override + public List getAllAttributes(ItemStack itemStack, Level level) { + ListTag traits = extractTraitList(itemStack); + List atts = new ArrayList<>(); + for (int i = 0; i < traits.size(); i++) { + atts.add(new AstralSorceryAmuletAttribute( + traits.getCompound(i).getString("ench"), + traits.getCompound(i).getInt("type"))); + } + return atts; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryAttunementAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryAttunementAttribute.java new file mode 100644 index 0000000000..1dc38bba91 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryAttunementAttribute.java @@ -0,0 +1,96 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.network.chat.Component; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.registries.ForgeRegistries; + +public class AstralSorceryAttunementAttribute implements ItemAttribute { + String constellationName; + + public AstralSorceryAttunementAttribute(String constellationName) { + this.constellationName = constellationName; + } + + private static CompoundTag extractAstralNBT(ItemStack stack) { + return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery") : new CompoundTag(); + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + CompoundTag nbt = extractAstralNBT(itemStack); + String constellation = nbt.contains("constellation") ? nbt.getString("constellation") : nbt.getString("constellationName"); + + // Special handling for shifting stars + ResourceLocation itemResource = ForgeRegistries.ITEMS.getKey(itemStack.getItem()); + if (itemResource != null && itemResource.toString().contains("shifting_star_")) { + constellation = itemResource.toString().replace("shifting_star_", ""); + } + + return constellation.equals(constellationName); + } + + @Override + public String getTranslationKey() { + return "astralsorcery_constellation"; + } + + @Override + public Object[] getTranslationParameters() { + ResourceLocation constResource = new ResourceLocation(constellationName); + String something = Component.translatable(String.format("%s.constellation.%s", constResource.getNamespace(), constResource.getPath())).getString(); + return new Object[]{something}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.ASTRAL_ATTUNMENT; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putString("constellation", constellationName); + } + + @Override + public void load(CompoundTag nbt) { + constellationName = nbt.getString("constellation"); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new AstralSorceryAttunementAttribute("dummy"); + } + + @Override + public List getAllAttributes(ItemStack itemStack, Level level) { + CompoundTag nbt = extractAstralNBT(itemStack); + String constellation = nbt.contains("constellation") ? nbt.getString("constellation") : nbt.getString("constellationName"); + + // Special handling for shifting stars + ResourceLocation itemResource = ForgeRegistries.ITEMS.getKey(itemStack.getItem()); + if (itemResource != null && itemResource.toString().contains("shifting_star_")) { + constellation = itemResource.toString().replace("shifting_star_", ""); + } + + List atts = new ArrayList<>(); + if (constellation.length() > 0) { + atts.add(new AstralSorceryAttunementAttribute(constellation)); + } + return atts; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryCrystalAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryCrystalAttribute.java new file mode 100644 index 0000000000..77887970d7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryCrystalAttribute.java @@ -0,0 +1,84 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.network.chat.Component; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class AstralSorceryCrystalAttribute implements ItemAttribute { + String traitName; + + public AstralSorceryCrystalAttribute(String traitName) { + this.traitName = traitName; + } + + private static ListTag extractTraitList(ItemStack stack) { + return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery").getCompound("crystalProperties").getList("attributes", 10) : new ListTag(); + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + for (Tag trait : extractTraitList(itemStack)) { + if (((CompoundTag) trait).getString("property").equals(this.traitName)) + return true; + } + return false; + } + + @Override + public String getTranslationKey() { + return "astralsorcery_crystal"; + } + + @Override + public Object[] getTranslationParameters() { + ResourceLocation traitResource = new ResourceLocation(traitName); + String something = Component.translatable(String.format("crystal.property.%s.%s.name", traitResource.getNamespace(), traitResource.getPath())).getString(); + return new Object[]{something}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.ASTRAL_CRYSTAL; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putString("property", traitName); + } + + @Override + public void load(CompoundTag nbt) { + traitName = nbt.getString("property"); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new AstralSorceryCrystalAttribute("dummy"); + } + + @Override + public List getAllAttributes(ItemStack itemStack, Level level) { + ListTag traits = extractTraitList(itemStack); + List atts = new ArrayList<>(); + for (int i = 0; i < traits.size(); i++) { + atts.add(new AstralSorceryCrystalAttribute(traits.getCompound(i).getString("property"))); + } + return atts; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryPerkGemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryPerkGemAttribute.java new file mode 100644 index 0000000000..e82e368c75 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/attributes/astralsorcery/AstralSorceryPerkGemAttribute.java @@ -0,0 +1,84 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.attributes.astralsorcery; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.network.chat.Component; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class AstralSorceryPerkGemAttribute implements ItemAttribute { + String traitName; + + public AstralSorceryPerkGemAttribute(String traitName) { + this.traitName = traitName; + } + + private static ListTag extractTraitList(ItemStack stack) { + return stack.getTag() != null ? stack.getTag().getCompound("astralsorcery").getList("attribute_modifiers", 10) : new ListTag(); + } + + @Override + public boolean appliesTo(ItemStack itemStack, Level level) { + for (Tag trait : extractTraitList(itemStack)) { + if (((CompoundTag) trait).getString("type").equals(this.traitName)) + return true; + } + return false; + } + + @Override + public String getTranslationKey() { + return "astralsorcery_perk_gem"; + } + + @Override + public Object[] getTranslationParameters() { + ResourceLocation traitResource = new ResourceLocation(traitName); + String something = Component.translatable(String.format("perk.attribute.%s.%s.name", traitResource.getNamespace(), traitResource.getPath())).getString(); + return new Object[]{something}; + } + + @Override + public ItemAttributeType getType() { + return AllItemAttributeTypes.ASTRAL_PERK_GEM; + } + + @Override + public void save(CompoundTag nbt) { + nbt.putString("type", traitName); + } + + @Override + public void load(CompoundTag nbt) { + traitName = nbt.getString("type"); + } + + public static class Type implements ItemAttributeType { + @Override + public @NotNull ItemAttribute createAttribute() { + return new AstralSorceryPerkGemAttribute("dummy"); + } + + @Override + public List getAllAttributes(ItemStack itemStack, Level level) { + ListTag traits = extractTraitList(itemStack); + List atts = new ArrayList<>(); + for (int i = 0; i < traits.size(); i++) { + atts.add(new AstralSorceryPerkGemAttribute(traits.getCompound(i).getString("type"))); + } + return atts; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/AllItemAttributeLegacyDeserializers.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/AllItemAttributeLegacyDeserializers.java new file mode 100644 index 0000000000..53cc3a8572 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/AllItemAttributeLegacyDeserializers.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.legacydeserializers; + +import java.util.function.Function; + +import org.jetbrains.annotations.ApiStatus; + +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.AddedByAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.ColorAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.EnchantAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.FluidContentsAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.InTagAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.ShulkerFillLevelAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.attributes.ShulkerFillLevelAttribute.ShulkerLevels; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.item.DyeColor; + +@SuppressWarnings("deprecation") +public class AllItemAttributeLegacyDeserializers { + @ApiStatus.Internal + public static void register() { + addLegacyDeserializer(new StandardTraitsLegacyDeserializer()); + createLegacyDeserializer("in_tag", tag -> + new InTagAttribute(ItemTags.create(new ResourceLocation( + tag.getString("space"), + tag.getString("path") + ))) + ); + createLegacyDeserializer("in_item_group", AllItemAttributeTypes.IN_ITEM_GROUP); + createLegacyDeserializer("added_by", tag -> + new AddedByAttribute(tag.getString("id"))); + createLegacyDeserializer("has_enchant", tag -> + new EnchantAttribute(BuiltInRegistries.ENCHANTMENT.get(ResourceLocation.tryParse(tag.getString("id"))))); + createLegacyDeserializer("shulker_fill_level", tag -> + new ShulkerFillLevelAttribute(ShulkerLevels.fromKey(tag.getString("id")))); + createLegacyDeserializer("has_color", tag -> + new ColorAttribute(DyeColor.byId(tag.getInt("id")))); + createLegacyDeserializer("has_fluid", tag -> + new FluidContentsAttribute(BuiltInRegistries.FLUID.get(ResourceLocation.tryParse(tag.getString("id"))))); + createLegacyDeserializer("has_name", AllItemAttributeTypes.HAS_NAME); + createLegacyDeserializer("book_author", AllItemAttributeTypes.BOOK_AUTHOR); + createLegacyDeserializer("book_copy", AllItemAttributeTypes.BOOK_COPY); + createLegacyDeserializer("astralsorcery_amulet", AllItemAttributeTypes.ASTRAL_AMULET); + createLegacyDeserializer("astralsorcery_constellation", AllItemAttributeTypes.ASTRAL_ATTUNMENT); + createLegacyDeserializer("astralsorcery_crystal", AllItemAttributeTypes.ASTRAL_CRYSTAL); + createLegacyDeserializer("astralsorcery_perk_gem", AllItemAttributeTypes.ASTRAL_PERK_GEM); + } + + private static void createLegacyDeserializer(String nbtKey, ItemAttributeType type) { + createLegacyDeserializer(nbtKey, tag -> { + ItemAttribute attribute = type.createAttribute(); + attribute.load(tag); + return attribute; + }); + } + + private static void createLegacyDeserializer(String nbtKey, Function func) { + addLegacyDeserializer(new ItemAttribute.LegacyDeserializer() { + @Override + public String getNBTKey() { + return nbtKey; + } + + @Override + public ItemAttribute readNBT(CompoundTag nbt) { + return func.apply(nbt); + } + }); + } + + private static void addLegacyDeserializer(ItemAttribute.LegacyDeserializer legacyDeserializer) { + ItemAttribute.LegacyDeserializer.ALL.add(legacyDeserializer); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/StandardTraitsLegacyDeserializer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/StandardTraitsLegacyDeserializer.java new file mode 100644 index 0000000000..0511ebd9df --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/StandardTraitsLegacyDeserializer.java @@ -0,0 +1,50 @@ +package com.simibubi.create.content.logistics.item.filter.attribute.legacydeserializers; + +import java.util.Map; + +import com.google.common.collect.ImmutableBiMap; +import com.simibubi.create.content.logistics.item.filter.attribute.AllItemAttributeTypes; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttribute; +import com.simibubi.create.content.logistics.item.filter.attribute.ItemAttributeType; + +import net.minecraft.nbt.CompoundTag; + +@SuppressWarnings("deprecation") +public class StandardTraitsLegacyDeserializer implements ItemAttribute.LegacyDeserializer { + @Override + public String getNBTKey() { + return "standard_trait"; + } + + @Override + public ItemAttribute readNBT(CompoundTag nbt) { + ImmutableBiMap map = ImmutableBiMap.builder() + .put("PLACEABLE", AllItemAttributeTypes.PLACEABLE) + .put("CONSUMABLE", AllItemAttributeTypes.CONSUMABLE) + .put("FLUID_CONTAINER", AllItemAttributeTypes.FLUID_CONTAINER) + .put("ENCHANTED", AllItemAttributeTypes.ENCHANTED) + .put("MAX_ENCHANTED", AllItemAttributeTypes.MAX_ENCHANTED) + .put("RENAMED", AllItemAttributeTypes.RENAMED) + .put("DAMAGED", AllItemAttributeTypes.DAMAGED) + .put("BADLY_DAMAGED", AllItemAttributeTypes.BADLY_DAMAGED) + .put("NOT_STACKABLE", AllItemAttributeTypes.NOT_STACKABLE) + .put("EQUIPABLE", AllItemAttributeTypes.EQUIPABLE) + .put("FURNACE_FUEL", AllItemAttributeTypes.FURNACE_FUEL) + .put("WASHABLE", AllItemAttributeTypes.WASHABLE) + .put("HAUNTABLE", AllItemAttributeTypes.HAUNTABLE) + .put("CRUSHABLE", AllItemAttributeTypes.CRUSHABLE) + .put("SMELTABLE", AllItemAttributeTypes.SMELTABLE) + .put("SMOKABLE", AllItemAttributeTypes.SMOKABLE) + .put("BLASTABLE", AllItemAttributeTypes.BLASTABLE) + .put("COMPOSTABLE", AllItemAttributeTypes.COMPOSTABLE) + .build(); + + for (Map.Entry entry : map.entrySet()) { + if (nbt.contains(entry.getKey())) { + return entry.getValue().createAttribute(); + } + } + + throw new IllegalArgumentException("Tried to read standard trait and migrate to a type that doesn't exist!"); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/package-info.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/package-info.java new file mode 100644 index 0000000000..f95457f621 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/legacydeserializers/package-info.java @@ -0,0 +1,5 @@ +@Deprecated +@ApiStatus.Internal +package com.simibubi.create.content.logistics.item.filter.attribute.legacydeserializers; + +import org.jetbrains.annotations.ApiStatus; diff --git a/src/main/java/com/simibubi/create/content/logistics/itemHatch/HatchFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/itemHatch/HatchFilterSlot.java new file mode 100644 index 0000000000..e8ea30f5b6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/itemHatch/HatchFilterSlot.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.logistics.itemHatch; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; + +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HatchFilterSlot extends ValueBoxTransform { + + @Override + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { + return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 5.15, 9.5), angle(state), Direction.Axis.Y); + } + + @Override + public float getScale() { + return super.getScale() * 0.965f; + } + + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + return localHit.distanceTo(getLocalOffset(level, pos, state).subtract(0, 0.125, 0)) < scale / 2; + } + + @Override + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { + ms.mulPose(Axis.YP.rotationDegrees(angle(state))); + ms.mulPose(Axis.XP.rotationDegrees(-45)); + } + + private float angle(BlockState state) { + return AngleHelper.horizontalAngle(state.getOptionalValue(ItemHatchBlock.FACING) + .orElse(Direction.NORTH)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchBlock.java b/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchBlock.java new file mode 100644 index 0000000000..6a84ff7d9c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchBlock.java @@ -0,0 +1,195 @@ +package com.simibubi.create.content.logistics.itemHatch; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ItemHatchBlock extends HorizontalDirectionalBlock + implements IBE, IWrenchable, ProperWaterloggedBlock { + + public static final BooleanProperty OPEN = BooleanProperty.create("open"); + + public ItemHatchBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(OPEN, false) + .setValue(WATERLOGGED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(OPEN, FACING, WATERLOGGED)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + BlockState state = super.getStateForPlacement(pContext); + if (state == null) + return state; + if (pContext.getClickedFace() + .getAxis() + .isVertical()) + return null; + + return withWater(state.setValue(FACING, pContext.getClickedFace() + .getOpposite()) + .setValue(OPEN, false), pContext); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pPos); + return pState; + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + if (pLevel.isClientSide()) + return InteractionResult.SUCCESS; + if (pPlayer instanceof FakePlayer) + return InteractionResult.SUCCESS; + + BlockEntity blockEntity = pLevel.getBlockEntity(pPos.relative(pState.getValue(FACING))); + if (blockEntity == null) + return InteractionResult.FAIL; + LazyOptional optional = blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER); + IItemHandler targetInv = optional.orElse(null); + if (targetInv == null) + return InteractionResult.FAIL; + + FilteringBehaviour filter = BlockEntityBehaviour.get(pLevel, pPos, FilteringBehaviour.TYPE); + if (filter == null) + return InteractionResult.FAIL; + + Inventory inventory = pPlayer.getInventory(); + List failedInsertions = new ArrayList<>(); + boolean anyInserted = false; + boolean depositItemInHand = !pPlayer.isShiftKeyDown(); + + if (!depositItemInHand && AllItemTags.WRENCH.matches(pPlayer.getItemInHand(pHand))) + return InteractionResult.PASS; + + for (int i = 0; i < inventory.items.size(); i++) { + if (Inventory.isHotbarSlot(i) != depositItemInHand) + continue; + if (depositItemInHand && i != inventory.selected) + continue; + ItemStack item = inventory.getItem(i); + if (item.isEmpty()) + continue; + if (!item.getItem() + .canFitInsideContainerItems() && !PackageItem.isPackage(item)) + continue; + if (!filter.getFilter() + .isEmpty() && !filter.test(item)) + continue; + + ItemStack remainder = ItemHandlerHelper.insertItemStacked(targetInv, item, true); + if (remainder.getCount() == item.getCount()) + continue; + + ItemStack extracted = inventory.removeItem(i, item.getCount() - remainder.getCount()); + remainder = ItemHandlerHelper.insertItemStacked(targetInv, extracted, false); + anyInserted = true; + + // remainder might not be empty in itemhandler edge cases + if (!remainder.isEmpty()) + failedInsertions.add(remainder); + } + + failedInsertions.forEach(inventory::placeItemBackInInventory); + + if (!anyInserted) + return InteractionResult.SUCCESS; + + AllSoundEvents.ITEM_HATCH.playOnServer(pLevel, pPos); + pLevel.setBlockAndUpdate(pPos, pState.setValue(OPEN, true)); + pLevel.scheduleTick(pPos, this, 10); + + CreateLang.translate(depositItemInHand ? "item_hatch.deposit_item" : "item_hatch.deposit_inventory") + .sendStatus(pPlayer); + + return InteractionResult.SUCCESS; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.ITEM_HATCH.get(pState.getValue(FACING) + .getOpposite()); + } + + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + if (pState.getValue(OPEN)) + pLevel.setBlockAndUpdate(pPos, pState.setValue(OPEN, false)); + } + + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { + IBE.onRemove(state, level, pos, newState); + } + + @Override + public Class getBlockEntityClass() { + return ItemHatchBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ITEM_HATCH.get(); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchBlockEntity.java new file mode 100644 index 0000000000..fcfa2022fe --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchBlockEntity.java @@ -0,0 +1,26 @@ +package com.simibubi.create.content.logistics.itemHatch; + +import java.util.List; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class ItemHatchBlockEntity extends SmartBlockEntity { + + public FilteringBehaviour filtering; + + public ItemHatchBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = new FilteringBehaviour(this, new HatchFilterSlot())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchHandler.java b/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchHandler.java new file mode 100644 index 0000000000..6afb3c2747 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/itemHatch/ItemHatchHandler.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.logistics.itemHatch; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; + +import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock; +import net.minecraftforge.eventbus.api.Event.Result; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(modid = Create.ID) +public class ItemHatchHandler { + + @SubscribeEvent(priority = EventPriority.LOW) + public static void useOnItemHatchIgnoresSneak(RightClickBlock event) { + if (event.getUseItem() == Result.DEFAULT && AllBlocks.ITEM_HATCH.has(event.getLevel() + .getBlockState(event.getPos()))) + event.setUseBlock(Result.ALLOW); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortAutomationInventoryWrapper.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortAutomationInventoryWrapper.java new file mode 100644 index 0000000000..0dcbe2d688 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortAutomationInventoryWrapper.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.logistics.packagePort; + +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.foundation.item.ItemHandlerWrapper; +import com.simibubi.create.foundation.item.ItemHelper; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandlerModifiable; + +public class PackagePortAutomationInventoryWrapper extends ItemHandlerWrapper { + + private PackagePortBlockEntity ppbe; + + private boolean access; + + public PackagePortAutomationInventoryWrapper(IItemHandlerModifiable wrapped, PackagePortBlockEntity ppbe) { + super(wrapped); + this.ppbe = ppbe; + access = false; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (access) + return super.extractItem(slot, amount, simulate); + + access = true; + ItemStack extract = ItemHelper.extract(this, stack -> { + if (!PackageItem.isPackage(stack)) + return false; + String filterString = ppbe.getFilterString(); + return filterString != null && PackageItem.matchAddress(stack, filterString); + }, simulate); + access = false; + + return extract; + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (!PackageItem.isPackage(stack)) + return stack; + String filterString = ppbe.getFilterString(); + if (filterString != null && PackageItem.matchAddress(stack, filterString)) + return stack; + return super.insertItem(slot, stack, simulate); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortBlockEntity.java new file mode 100644 index 0000000000..6d48963d74 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortBlockEntity.java @@ -0,0 +1,218 @@ +package com.simibubi.create.content.logistics.packagePort; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.equipment.clipboard.ClipboardEntry; +import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.animatedContainer.AnimatedContainerBehaviour; +import com.simibubi.create.foundation.item.SmartInventory; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.network.NetworkHooks; + +public abstract class PackagePortBlockEntity extends SmartBlockEntity implements MenuProvider { + + public boolean acceptsPackages; + public String addressFilter; + public PackagePortTarget target; + public SmartInventory inventory; + + protected AnimatedContainerBehaviour openTracker; + + protected LazyOptional itemHandler; + + public PackagePortBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + addressFilter = ""; + acceptsPackages = true; + inventory = new SmartInventory(18, this); + itemHandler = LazyOptional.of(() -> new PackagePortAutomationInventoryWrapper(inventory, this)); + } + + public boolean isBackedUp() { + for (int i = 0; i < inventory.getSlots(); i++) + if (inventory.getStackInSlot(i) + .isEmpty()) + return false; + return true; + } + + public void filterChanged() { + if (target != null) { + target.deregister(this, level, worldPosition); + target.register(this, level, worldPosition); + } + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (target != null) + target.register(this, level, worldPosition); + } + + public String getFilterString() { + return acceptsPackages ? addressFilter : null; + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + if (target != null) + tag.put("Target", target.write()); + tag.putString("AddressFilter", addressFilter); + tag.putBoolean("AcceptsPackages", acceptsPackages); + tag.put("Inventory", inventory.serializeNBT()); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + inventory.deserializeNBT(tag.getCompound("Inventory")); + PackagePortTarget prevTarget = target; + target = PackagePortTarget.read(tag.getCompound("Target")); + addressFilter = tag.getString("AddressFilter"); + acceptsPackages = tag.getBoolean("AcceptsPackages"); + if (clientPacket && prevTarget != target) + invalidateRenderBoundingBox(); + } + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (isItemHandlerCap(cap)) + return itemHandler.cast(); + return super.getCapability(cap, side); + } + + @Override + public void invalidate() { + itemHandler.invalidate(); + super.invalidate(); + } + + @Override + public void destroy() { + if (target != null) + target.deregister(this, level, worldPosition); + super.destroy(); + for (int i = 0; i < inventory.getSlots(); i++) + drop(inventory.getStackInSlot(i)); + } + + public void drop(ItemStack box) { + if (box.isEmpty()) + return; + Block.popResource(level, worldPosition, box); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(openTracker = new AnimatedContainerBehaviour<>(this, PackagePortMenu.class)); + openTracker.onOpenChanged(this::onOpenChange); + } + + protected abstract void onOpenChange(boolean open); + + public InteractionResult use(Player player) { + if (player == null || player.isCrouching()) + return InteractionResult.PASS; + if (player instanceof FakePlayer) + return InteractionResult.PASS; + + ItemStack mainHandItem = player.getMainHandItem(); + boolean clipboard = AllBlocks.CLIPBOARD.isIn(mainHandItem); + + if (level.isClientSide) { + if (!clipboard) + onOpenedManually(); + return InteractionResult.SUCCESS; + } + + if (clipboard) { + addAddressToClipboard(player, mainHandItem); + return InteractionResult.SUCCESS; + } + + NetworkHooks.openScreen((ServerPlayer) player, this, worldPosition); + return InteractionResult.SUCCESS; + } + + protected void onOpenedManually() {}; + + private void addAddressToClipboard(Player player, ItemStack mainHandItem) { + if (addressFilter == null || addressFilter.isBlank()) + return; + + List> list = ClipboardEntry.readAll(mainHandItem); + for (List page : list) { + for (ClipboardEntry entry : page) { + String existing = entry.text.getString(); + if (existing.equals("#" + addressFilter) || existing.equals("# " + addressFilter)) + return; + } + } + + List page = null; + + for (List freePage : list) { + if (freePage.size() > 11) + continue; + page = freePage; + break; + } + + if (page == null) { + page = new ArrayList<>(); + list.add(page); + } + + page.add(new ClipboardEntry(false, Component.literal("#" + addressFilter))); + player.displayClientMessage(CreateLang.translate("clipboard.address_added", addressFilter) + .component(), true); + + ClipboardEntry.saveAll(list, mainHandItem); + mainHandItem.getTag() + .putInt("Type", ClipboardOverrides.ClipboardType.WRITTEN.ordinal()); + } + + @Override + public Component getDisplayName() { + return Component.empty(); + } + + @Override + public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { + return PackagePortMenu.create(pContainerId, pPlayerInventory, this); + } + + public int getComparatorOutput() { + return ItemHandlerHelper.calcRedstoneFromInventory(inventory); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortConfigurationPacket.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortConfigurationPacket.java new file mode 100644 index 0000000000..2ac5521c2e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortConfigurationPacket.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.logistics.packagePort; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; + +public class PackagePortConfigurationPacket extends BlockEntityConfigurationPacket { + + private String newFilter; + private boolean acceptPackages; + + public PackagePortConfigurationPacket(BlockPos pos, String newFilter, boolean acceptPackages) { + super(pos); + this.newFilter = newFilter; + this.acceptPackages = acceptPackages; + } + + public PackagePortConfigurationPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBoolean(acceptPackages); + buffer.writeUtf(newFilter); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + acceptPackages = buffer.readBoolean(); + newFilter = buffer.readUtf(); + } + + @Override + protected void applySettings(PackagePortBlockEntity be) { + if (be.addressFilter.equals(newFilter) && be.acceptsPackages == acceptPackages) + return; + be.addressFilter = newFilter; + be.acceptsPackages = acceptPackages; + be.filterChanged(); + be.notifyUpdate(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortItem.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortItem.java new file mode 100644 index 0000000000..07a107e49f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortItem.java @@ -0,0 +1,30 @@ +package com.simibubi.create.content.logistics.packagePort; + +import com.simibubi.create.AllPackets; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.network.PacketDistributor; + +public class PackagePortItem extends BlockItem { + + public PackagePortItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, Player player, ItemStack p_195943_4_, + BlockState p_195943_5_) { + if (!world.isClientSide && player instanceof ServerPlayer sp) + AllPackets.getChannel() + .send(PacketDistributor.PLAYER.with(() -> sp), new PackagePortPlacementPacket.ClientBoundRequest(pos)); + return super.updateCustomBlockEntityTag(pos, world, player, p_195943_4_, p_195943_5_); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortMenu.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortMenu.java new file mode 100644 index 0000000000..dd9d22e70d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortMenu.java @@ -0,0 +1,91 @@ +package com.simibubi.create.content.logistics.packagePort; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.animatedContainer.AnimatedContainerBehaviour; +import com.simibubi.create.foundation.gui.menu.MenuBase; +import com.simibubi.create.foundation.item.SmartInventory; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.SlotItemHandler; + +public class PackagePortMenu extends MenuBase { + + public PackagePortMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public PackagePortMenu(MenuType type, int id, Inventory inv, PackagePortBlockEntity be) { + super(type, id, inv, be); + BlockEntityBehaviour.get(be, AnimatedContainerBehaviour.TYPE) + .startOpen(player); + } + + public static PackagePortMenu create(int id, Inventory inv, PackagePortBlockEntity be) { + return new PackagePortMenu(AllMenuTypes.PACKAGE_PORT.get(), id, inv, be); + } + + @Override + protected PackagePortBlockEntity createOnClient(FriendlyByteBuf extraData) { + BlockPos readBlockPos = extraData.readBlockPos(); + ClientLevel world = Minecraft.getInstance().level; + BlockEntity blockEntity = world.getBlockEntity(readBlockPos); + if (blockEntity instanceof PackagePortBlockEntity ppbe) + return ppbe; + return null; + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + Slot clickedSlot = getSlot(index); + if (!clickedSlot.hasItem()) + return ItemStack.EMPTY; + + ItemStack stack = clickedSlot.getItem(); + int size = contentHolder.inventory.getSlots(); + boolean success = false; + if (index < size) { + success = !moveItemStackTo(stack, size, slots.size(), false); + } else + success = !moveItemStackTo(stack, 0, size, false); + + return success ? ItemStack.EMPTY : stack; + } + + @Override + protected void initAndReadInventory(PackagePortBlockEntity contentHolder) {} + + @Override + protected void addSlots() { + SmartInventory inventory = contentHolder.inventory; + int x = 27; + int y = 9; + + for (int row = 0; row < 2; row++) + for (int col = 0; col < 9; col++) + addSlot(new SlotItemHandler(inventory, row * 9 + col, x + col * 18, y + row * 18)); + + addPlayerSlots(38, 108); + } + + @Override + protected void saveData(PackagePortBlockEntity contentHolder) {} + + @Override + public void removed(Player playerIn) { + super.removed(playerIn); + if (!playerIn.level().isClientSide) + BlockEntityBehaviour.get(contentHolder, AnimatedContainerBehaviour.TYPE) + .stopOpen(playerIn); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortPlacementPacket.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortPlacementPacket.java new file mode 100644 index 0000000000..7dc29da673 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortPlacementPacket.java @@ -0,0 +1,91 @@ +package com.simibubi.create.content.logistics.packagePort; + +import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class PackagePortPlacementPacket extends SimplePacketBase { + + private PackagePortTarget target; + private BlockPos pos; + + public PackagePortPlacementPacket(PackagePortTarget target, BlockPos pos) { + this.target = target; + this.pos = pos; + } + + public PackagePortPlacementPacket(FriendlyByteBuf buffer) { + target = PackagePortTarget.read(buffer.readNbt()); + pos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeNbt(target.write()); + buffer.writeBlockPos(pos); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + Level world = player.level(); + if (world == null || !world.isLoaded(pos)) + return; + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof PackagePortBlockEntity ppbe)) + return; + if (!target.canSupport(ppbe)) + return; + + Vec3 targetLocation = target.getExactTargetLocation(ppbe, world, pos); + if (targetLocation == Vec3.ZERO || !targetLocation.closerThan(Vec3.atBottomCenterOf(pos), + AllConfigs.server().logistics.packagePortRange.get() + 2)) + return; + + target.setup(ppbe, world, pos); + ppbe.target = target; + ppbe.notifyUpdate(); + ppbe.use(player); + }); + return true; + } + + public static class ClientBoundRequest extends SimplePacketBase { + + BlockPos pos; + + public ClientBoundRequest(BlockPos pos) { + this.pos = pos; + } + + public ClientBoundRequest(FriendlyByteBuf buffer) { + this.pos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> PackagePortTargetSelectionHandler.flushSettings(pos))); + return true; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortScreen.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortScreen.java new file mode 100644 index 0000000000..33eb9bf737 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortScreen.java @@ -0,0 +1,191 @@ +package com.simibubi.create.content.logistics.packagePort; + +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.platform.InputConstants; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportBlockEntity; +import com.simibubi.create.content.trains.station.NoShadowFontWrapper; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; + +public class PackagePortScreen extends AbstractSimiContainerScreen { + + private boolean frogMode; + private AllGuiTextures background; + + private EditBox addressBox; + private IconButton confirmButton; + private IconButton dontAcceptPackages; + private IconButton acceptPackages; + + private ItemStack icon; + + private List extraAreas = Collections.emptyList(); + + public PackagePortScreen(PackagePortMenu container, Inventory inv, Component title) { + super(container, inv, title); + background = AllGuiTextures.FROGPORT_BG; + frogMode = container.contentHolder instanceof FrogportBlockEntity; + icon = new ItemStack(container.contentHolder.getBlockState() + .getBlock() + .asItem()); + } + + @Override + protected void init() { + setWindowSize(background.getWidth(), background.getHeight() + AllGuiTextures.PLAYER_INVENTORY.getHeight()); + super.init(); + clearWidgets(); + + int x = getGuiLeft(); + int y = getGuiTop(); + + Consumer onTextChanged; + onTextChanged = s -> addressBox.setX(nameBoxX(s, addressBox)); + addressBox = new EditBox(new NoShadowFontWrapper(font), x + 23, y - 11, background.getWidth() - 20, 10, + Component.empty()); + addressBox.setBordered(false); + addressBox.setMaxLength(25); + addressBox.setTextColor(0x3D3C48); + addressBox.setValue(menu.contentHolder.addressFilter); + addressBox.setFocused(false); + addressBox.mouseClicked(0, 0, 0); + addressBox.setResponder(onTextChanged); + addressBox.setX(nameBoxX(addressBox.getValue(), addressBox)); + addRenderableWidget(addressBox); + + confirmButton = + new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> minecraft.player.closeContainer()); + addRenderableWidget(confirmButton); + + acceptPackages = new IconButton(x + 37, y + background.getHeight() - 24, AllIcons.I_SEND_AND_RECEIVE); + acceptPackages.withCallback(() -> { + acceptPackages.green = true; + dontAcceptPackages.green = false; + }); + acceptPackages.green = menu.contentHolder.acceptsPackages; + acceptPackages.setToolTip(CreateLang.translateDirect("gui.package_port.send_and_receive")); + addRenderableWidget(acceptPackages); + + dontAcceptPackages = new IconButton(x + 37 + 18, y + background.getHeight() - 24, AllIcons.I_SEND_ONLY); + dontAcceptPackages.withCallback(() -> { + acceptPackages.green = false; + dontAcceptPackages.green = true; + }); + dontAcceptPackages.green = !menu.contentHolder.acceptsPackages; + dontAcceptPackages.setToolTip(CreateLang.translateDirect("gui.package_port.send_only")); + addRenderableWidget(dontAcceptPackages); + + containerTick(); + + extraAreas = ImmutableList.of(new Rect2i(x + background.getWidth(), y + background.getHeight() - 50, 70, 60)); + } + + private int nameBoxX(String s, EditBox nameBox) { + return getGuiLeft() + background.getWidth() / 2 - (Math.min(font.width(s), nameBox.getWidth()) + 10) / 2; + } + + @Override + protected void containerTick() { + acceptPackages.visible = menu.contentHolder.target != null; + dontAcceptPackages.visible = menu.contentHolder.target != null; + super.containerTick(); + } + + @Override + protected void renderBg(GuiGraphics graphics, float pPartialTick, int pMouseX, int pMouseY) { + int x = getGuiLeft(); + int y = getGuiTop(); + + AllGuiTextures header = frogMode ? AllGuiTextures.FROGPORT_HEADER : AllGuiTextures.POSTBOX_HEADER; + header.render(graphics, x, y - header.getHeight()); + background.render(graphics, x, y); + + String text = addressBox.getValue(); + if (!addressBox.isFocused()) { + if (addressBox.getValue() + .isEmpty()) { + text = icon.getHoverName() + .getString(); + graphics.drawString(font, text, nameBoxX(text, addressBox), y - 11, 0x3D3C48, false); + } + AllGuiTextures.FROGPORT_EDIT_NAME.render(graphics, nameBoxX(text, addressBox) + font.width(text) + 5, + y - 14); + } + + GuiGameElement.of(icon).at(x + background.getWidth() + 6, y + background.getHeight() - 56, -200) + .scale(4) + .render(graphics); + + int invX = leftPos + 30; + int invY = topPos + 8 + imageHeight - AllGuiTextures.PLAYER_INVENTORY.getHeight(); + renderPlayerInventory(graphics, invX, invY); + + if (menu.contentHolder.target == null) + return; + + x += 13; + y += 58; + AllGuiTextures.FROGPORT_SLOT.render(graphics, x, y); + graphics.renderItem(menu.contentHolder.target.getIcon(), x + 1, y + 1); + + if (addressBox.isHovered()) { + graphics.renderComponentTooltip(font, List.of(CreateLang.translate("gui.package_port.catch_packages") + .color(AbstractSimiWidget.HEADER_RGB) + .component(), + CreateLang.translate("gui.package_port.catch_packages_empty") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.package_port.catch_packages_wildcard") + .style(ChatFormatting.GRAY) + .component()), + pMouseX, pMouseY); + } + } + + @Override + public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { + boolean hitEnter = getFocused() instanceof EditBox + && (pKeyCode == InputConstants.KEY_RETURN || pKeyCode == InputConstants.KEY_NUMPADENTER); + + if (hitEnter && addressBox.isFocused()) { + addressBox.setFocused(false); + return true; + } + + return super.keyPressed(pKeyCode, pScanCode, pModifiers); + } + + @Override + public void removed() { + AllPackets.getChannel() + .sendToServer(new PackagePortConfigurationPacket(menu.contentHolder.getBlockPos(), addressBox.getValue(), + acceptPackages.green)); + super.removed(); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortTarget.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortTarget.java new file mode 100644 index 0000000000..a537294ece --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortTarget.java @@ -0,0 +1,259 @@ +package com.simibubi.create.content.logistics.packagePort; + +import java.util.Map; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity.ConnectedPort; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity.ConnectionStats; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorPackage; +import com.simibubi.create.content.trains.station.StationBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec3; + +public abstract class PackagePortTarget { + + public BlockPos relativePos; + private String typeKey; + + public PackagePortTarget(String typeKey, BlockPos relativePos) { + this.typeKey = typeKey; + this.relativePos = relativePos; + } + + public abstract boolean export(LevelAccessor level, BlockPos portPos, ItemStack box, boolean simulate); + + public void setup(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) {} + + public void register(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) {} + + public void deregister(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) {} + + public abstract Vec3 getExactTargetLocation(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos); + + public abstract ItemStack getIcon(); + + public abstract boolean canSupport(BlockEntity be); + + public boolean depositImmediately() { + return false; + } + + public CompoundTag write() { + CompoundTag compoundTag = new CompoundTag(); + writeInternal(compoundTag); + compoundTag.putString("Type", typeKey); + compoundTag.put("RelativePos", NbtUtils.writeBlockPos(relativePos)); + return compoundTag; + } + + public static PackagePortTarget read(CompoundTag tag) { + if (tag.isEmpty()) + return null; + + BlockPos relativePos = NbtUtils.readBlockPos(tag.getCompound("RelativePos")); + PackagePortTarget target = switch (tag.getString("Type")) { + + case "ChainConveyor" -> new ChainConveyorFrogportTarget(relativePos, 0, null); + case "TrainStation" -> new TrainStationFrogportTarget(relativePos); + + default -> null; + }; + + if (target == null) + return null; + + target.readInternal(tag); + return target; + } + + protected abstract void writeInternal(CompoundTag tag); + + protected abstract void readInternal(CompoundTag tag); + + public BlockEntity be(LevelAccessor level, BlockPos portPos) { + if (level instanceof Level l && !l.isLoaded(portPos.offset(relativePos))) + return null; + return level.getBlockEntity(portPos.offset(relativePos)); + } + + public static class ChainConveyorFrogportTarget extends PackagePortTarget { + + public float chainPos; + public BlockPos connection; + public boolean flipped; + + public ChainConveyorFrogportTarget(BlockPos relativePos, float chainPos, @Nullable BlockPos connection) { + super("ChainConveyor", relativePos); + this.chainPos = chainPos; + this.connection = connection; + } + + @Override + public void setup(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) { + if (be(level, portPos) instanceof ChainConveyorBlockEntity clbe) + flipped = clbe.getSpeed() < 0; + } + + @Override + public ItemStack getIcon() { + return AllBlocks.CHAIN_CONVEYOR.asStack(); + } + + @Override + public boolean export(LevelAccessor level, BlockPos portPos, ItemStack box, boolean simulate) { + if (!(be(level, portPos) instanceof ChainConveyorBlockEntity clbe)) + return false; + if (connection != null && !clbe.connections.contains(connection)) + return false; + if (simulate) + return clbe.getSpeed() != 0 && clbe.canAcceptPackagesFor(connection); + ChainConveyorPackage box2 = new ChainConveyorPackage(chainPos, box.copy()); + if (connection == null) + return clbe.addLoopingPackage(box2); + return clbe.addTravellingPackage(box2, connection); + } + + @Override + public void register(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) { + if (!(be(level, portPos) instanceof ChainConveyorBlockEntity clbe)) + return; + ChainConveyorBlockEntity actualBe = clbe; + + // Jump to opposite chain if motion reversed + if (connection != null && clbe.getSpeed() < 0 != flipped) { + deregister(ppbe, level, portPos); + actualBe = AllBlocks.CHAIN_CONVEYOR.get() + .getBlockEntity(level, clbe.getBlockPos() + .offset(connection)); + if (actualBe == null) + return; + clbe.prepareStats(); + ConnectionStats stats = clbe.connectionStats.get(connection); + if (stats != null) + chainPos = stats.chainLength() - chainPos; + connection = connection.multiply(-1); + flipped = !flipped; + relativePos = actualBe.getBlockPos() + .subtract(portPos); + ppbe.notifyUpdate(); + } + + if (connection != null && !actualBe.connections.contains(connection)) + return; + String portFilter = ppbe.getFilterString(); + if (portFilter == null) + return; + actualBe.routingTable.receivePortInfo(portFilter, connection == null ? BlockPos.ZERO : connection); + Map portMap = connection == null ? actualBe.loopPorts : actualBe.travelPorts; + portMap.put(relativePos.multiply(-1), new ConnectedPort(chainPos, connection, portFilter)); + } + + @Override + public void deregister(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) { + if (!(be(level, portPos) instanceof ChainConveyorBlockEntity clbe)) + return; + clbe.loopPorts.remove(relativePos.multiply(-1)); + clbe.travelPorts.remove(relativePos.multiply(-1)); + String portFilter = ppbe.getFilterString(); + if (portFilter == null) + return; + clbe.routingTable.entriesByDistance.removeIf(e -> e.endOfRoute() && e.port() + .equals(portFilter)); + clbe.routingTable.changed = true; + } + + @Override + protected void writeInternal(CompoundTag tag) { + tag.putFloat("ChainPos", chainPos); + if (connection != null) { + tag.put("Connection", NbtUtils.writeBlockPos(connection)); + tag.putBoolean("Flipped", flipped); + } + } + + @Override + protected void readInternal(CompoundTag tag) { + chainPos = tag.getFloat("ChainPos"); + if (tag.contains("Connection")) { + connection = NbtUtils.readBlockPos(tag.getCompound("Connection")); + flipped = tag.getBoolean("Flipped"); + } + } + + @Override + public Vec3 getExactTargetLocation(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) { + if (!(be(level, portPos) instanceof ChainConveyorBlockEntity clbe)) + return Vec3.ZERO; + return clbe.getPackagePosition(chainPos, connection); + } + + @Override + public boolean canSupport(BlockEntity be) { + return AllBlockEntityTypes.PACKAGE_FROGPORT.is(be); + } + + } + + public static class TrainStationFrogportTarget extends PackagePortTarget { + + public TrainStationFrogportTarget(BlockPos relativePos) { + super("TrainStation", relativePos); + } + + @Override + public ItemStack getIcon() { + return AllBlocks.TRACK_STATION.asStack(); + } + + @Override + public boolean export(LevelAccessor level, BlockPos portPos, ItemStack box, boolean simulate) { + return false; + } + + @Override + public Vec3 getExactTargetLocation(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) { + return Vec3.atCenterOf(portPos.offset(relativePos)); + } + + @Override + public void register(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) { + if (be(level, portPos) instanceof StationBlockEntity sbe) + sbe.attachPackagePort(ppbe); + } + + @Override + public void deregister(PackagePortBlockEntity ppbe, LevelAccessor level, BlockPos portPos) { + if (be(level, portPos) instanceof StationBlockEntity sbe) + sbe.removePackagePort(ppbe); + } + + @Override + public boolean depositImmediately() { + return true; + } + + @Override + protected void writeInternal(CompoundTag tag) {} + + @Override + protected void readInternal(CompoundTag tag) {} + + @Override + public boolean canSupport(BlockEntity be) { + return AllBlockEntityTypes.PACKAGE_POSTBOX.is(be); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortTargetSelectionHandler.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortTargetSelectionHandler.java new file mode 100644 index 0000000000..b3f0b4d2f8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/PackagePortTargetSelectionHandler.java @@ -0,0 +1,178 @@ +package com.simibubi.create.content.logistics.packagePort; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.trains.station.StationBlockEntity; +import com.simibubi.create.foundation.utility.CreateLang; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.theme.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.DustParticleOptions; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.HitResult.Type; +import net.minecraft.world.phys.Vec3; + +public class PackagePortTargetSelectionHandler { + + public static PackagePortTarget activePackageTarget; + public static Vec3 exactPositionOfTarget; + public static boolean isPostbox; + + public static void flushSettings(BlockPos pos) { + if (activePackageTarget == null) { + CreateLang.translate("gui.package_port.not_targeting_anything") + .sendStatus(Minecraft.getInstance().player); + return; + } + + if (validateDiff(exactPositionOfTarget, pos) == null) { + activePackageTarget.relativePos = activePackageTarget.relativePos.subtract(pos); + AllPackets.getChannel() + .sendToServer(new PackagePortPlacementPacket(activePackageTarget, pos)); + } + + activePackageTarget = null; + isPostbox = false; + return; + } + + public static boolean onUse() { + Minecraft mc = Minecraft.getInstance(); + HitResult hitResult = mc.hitResult; + ItemStack mainHandItem = mc.player.getMainHandItem(); + + if (hitResult == null || hitResult.getType() == Type.MISS) + return false; + if (!(hitResult instanceof BlockHitResult bhr)) + return false; + + BlockPos pos = bhr.getBlockPos(); + if (!(mc.level.getBlockEntity(pos) instanceof StationBlockEntity sbe)) + return false; + if (sbe.edgePoint == null) + return false; + if (!AllItemTags.POSTBOXES.matches(mainHandItem)) + return false; + + PackagePortTargetSelectionHandler.exactPositionOfTarget = Vec3.atCenterOf(pos); + PackagePortTargetSelectionHandler.activePackageTarget = new PackagePortTarget.TrainStationFrogportTarget(pos); + PackagePortTargetSelectionHandler.isPostbox = true; + return true; + } + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + boolean isPostbox = AllItemTags.POSTBOXES.matches(player.getMainHandItem()); + boolean isWrench = AllItemTags.WRENCH.matches(player.getMainHandItem()); + + if (!isWrench) { + if (activePackageTarget == null) + return; + if (!AllBlocks.PACKAGE_FROGPORT.isIn(player.getMainHandItem()) && !isPostbox) + return; + } + + HitResult objectMouseOver = mc.hitResult; + if (!(objectMouseOver instanceof BlockHitResult blockRayTraceResult)) + return; + + if (isWrench) { + if (blockRayTraceResult.getType() == Type.MISS) + return; + BlockPos pos = blockRayTraceResult.getBlockPos(); + if (!(mc.level.getBlockEntity(pos) instanceof PackagePortBlockEntity ppbe)) + return; + if (ppbe.target == null) + return; + Vec3 source = Vec3.atBottomCenterOf(pos); + Vec3 target = ppbe.target.getExactTargetLocation(ppbe, mc.level, pos); + if (target == Vec3.ZERO) + return; + Color color = new Color(0x9ede73); + animateConnection(mc, source, target, color); + Outliner.getInstance().chaseAABB("ChainPointSelected", new AABB(target, target)) + .colored(color) + .lineWidth(1 / 5f) + .disableLineNormals(); + return; + } + + Vec3 target = exactPositionOfTarget; + if (blockRayTraceResult.getType() == Type.MISS) { + Outliner.getInstance().chaseAABB("ChainPointSelected", new AABB(target, target)) + .colored(0x9ede73) + .lineWidth(1 / 5f) + .disableLineNormals(); + return; + } + + BlockPos pos = blockRayTraceResult.getBlockPos(); + if (!mc.level.getBlockState(pos) + .canBeReplaced()) + pos = pos.relative(blockRayTraceResult.getDirection()); + + String validateDiff = validateDiff(target, pos); + boolean valid = validateDiff == null; + Color color = new Color(valid ? 0x9ede73 : 0xff7171); + Vec3 source = Vec3.atBottomCenterOf(pos); + + CreateLang.translate(validateDiff != null ? validateDiff : "package_port.valid") + .color(color.getRGB()) + .sendStatus(player); + + Outliner.getInstance().chaseAABB("ChainPointSelected", new AABB(target, target)) + .colored(color) + .lineWidth(1 / 5f) + .disableLineNormals(); + + if (!mc.level.getBlockState(pos) + .canBeReplaced()) + return; + + Outliner.getInstance().chaseAABB("TargetedFrogPos", new AABB(pos).contract(0, 1, 0) + .deflate(0.125, 0, 0.125)) + .colored(color) + .lineWidth(1 / 16f) + .disableLineNormals(); + + animateConnection(mc, source, target, color); + + } + + public static void animateConnection(Minecraft mc, Vec3 source, Vec3 target, Color color) { + DustParticleOptions data = new DustParticleOptions(color.asVectorF(), 1); + ClientLevel world = mc.level; + double totalFlyingTicks = 10; + int segments = (((int) totalFlyingTicks) / 3) + 1; + double tickOffset = totalFlyingTicks / segments; + + for (int i = 0; i < segments; i++) { + double ticks = ((AnimationTickHolder.getRenderTime() / 3) % tickOffset) + i * tickOffset; + Vec3 vec = source.lerp(target, ticks / totalFlyingTicks); + world.addParticle(data, vec.x, vec.y, vec.z, 0, 0, 0); + } + + } + + public static String validateDiff(Vec3 target, BlockPos placedPos) { + Vec3 source = Vec3.atBottomCenterOf(placedPos); + Vec3 diff = target.subtract(source); + if (diff.y < 0 && !isPostbox) + return "package_port.cannot_reach_down"; + if (diff.length() > AllConfigs.server().logistics.packagePortRange.get()) + return "package_port.too_far"; + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportBlock.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportBlock.java new file mode 100644 index 0000000000..d2d0c9beb1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportBlock.java @@ -0,0 +1,99 @@ +package com.simibubi.create.content.logistics.packagePort.frogport; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.block.IBE; + +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class FrogportBlock extends Block implements IBE, IWrenchable { + + public FrogportBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.PACKAGE_PORT; + } + + @Override + public @Nullable PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.NORMAL; + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + if (pPlacer == null) + return; + AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); + withBlockEntityDo(pLevel, pPos, be -> { + Vec3 diff = VecHelper.getCenterOf(pPos) + .subtract(pPlacer.position()); + be.passiveYaw = (float) (Mth.atan2(diff.x, diff.z) * Mth.RAD_TO_DEG); + be.passiveYaw = Math.round(be.passiveYaw / 11.25f) * 11.25f; + be.notifyUpdate(); + }); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + return onBlockEntityUse(worldIn, pos, be -> be.use(player)); + } + + @Override + public Class getBlockEntityClass() { + return FrogportBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.PACKAGE_FROGPORT.get(); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + public boolean hasAnalogOutputSignal(BlockState pState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { + return getBlockEntityOptional(pLevel, pPos).map(pbe -> pbe.getComparatorOutput()) + .orElse(0); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportBlockEntity.java new file mode 100644 index 0000000000..7d791f42fa --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportBlockEntity.java @@ -0,0 +1,380 @@ +package com.simibubi.create.content.logistics.packagePort.frogport; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.api.equipment.goggles.IHaveHoveringInformation; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.box.PackageStyles; +import com.simibubi.create.content.logistics.packagePort.PackagePortBlockEntity; +import com.simibubi.create.content.logistics.packager.PackagerItemHandler; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.item.TooltipHelper; + +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class FrogportBlockEntity extends PackagePortBlockEntity implements IHaveHoveringInformation { + + public ItemStack animatedPackage; + public LerpedFloat manualOpenAnimationProgress; + public LerpedFloat animationProgress; + public LerpedFloat anticipationProgress; + public boolean currentlyDepositing; + public boolean goggles; + + public boolean sendAnticipate; + + public float passiveYaw; + + private boolean failedLastExport; + private FrogportSounds sounds; + + private ItemStack deferAnimationStart; + private boolean deferAnimationInward; + + private AdvancementBehaviour advancements; + + public FrogportBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + sounds = new FrogportSounds(); + animationProgress = LerpedFloat.linear(); + anticipationProgress = LerpedFloat.linear(); + manualOpenAnimationProgress = LerpedFloat.linear() + .startWithValue(0) + .chase(0, 0.35, Chaser.LINEAR); + goggles = false; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(advancements = new AdvancementBehaviour(this, AllAdvancements.FROGPORT)); + super.addBehaviours(behaviours); + } + + public boolean isAnimationInProgress() { + return animationProgress.getChaseTarget() == 1; + } + + @Override + public AABB getRenderBoundingBox() { + AABB bb = super.getRenderBoundingBox().expandTowards(0, 1, 0); + if (target != null) + bb = bb.minmax(new AABB(BlockPos.containing(target.getExactTargetLocation(this, level, worldPosition)))) + .inflate(0.5); + return bb; + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide() || isAnimationInProgress()) + return; + + boolean prevFail = failedLastExport; + tryPushingToAdjacentInventories(); + tryPullingFromOwnAndAdjacentInventories(); + + if (failedLastExport != prevFail) + sendData(); + } + + public void sendAnticipate() { + if (isAnimationInProgress()) + return; + for (int i = 0; i < inventory.getSlots(); i++) + if (inventory.getStackInSlot(i) + .isEmpty()) { + sendAnticipate = true; + sendData(); + return; + } + } + + public void anticipate() { + anticipationProgress.chase(1, 0.1, Chaser.LINEAR); + } + + @Override + public void tick() { + super.tick(); + + if (deferAnimationStart != null) { + startAnimation(deferAnimationStart, deferAnimationInward); + deferAnimationStart = null; + } + + if (anticipationProgress.getValue() == 1) + anticipationProgress.startWithValue(0); + + manualOpenAnimationProgress.updateChaseTarget(openTracker.openCount > 0 ? 1 : 0); + boolean wasOpen = manualOpenAnimationProgress.getValue() > 0; + + anticipationProgress.tickChaser(); + manualOpenAnimationProgress.tickChaser(); + + if (level.isClientSide() && wasOpen && manualOpenAnimationProgress.getValue() == 0) + sounds.close(level, worldPosition); + + if (!isAnimationInProgress()) + return; + + animationProgress.tickChaser(); + + float value = animationProgress.getValue(); + if (currentlyDepositing) { + if (!level.isClientSide() || isVirtual()) { + if (value > 0.5 && animatedPackage != null) { + if (target == null + || !target.depositImmediately() && !target.export(level, worldPosition, animatedPackage, false)) + drop(animatedPackage); + animatedPackage = null; + } + } else { + if (value > 0.7 && animatedPackage != null) + animatedPackage = null; + if (animationProgress.getValue(0) < 0.2 && value > 0.2) { + Vec3 v = target.getExactTargetLocation(this, level, worldPosition); + level.playLocalSound(v.x, v.y, v.z, SoundEvents.CHAIN_STEP, SoundSource.BLOCKS, 0.25f, 1.2f, false); + } + } + } + + if (value < 1) + return; + + anticipationProgress.startWithValue(0); + animationProgress.startWithValue(0); + if (level.isClientSide()) { +// sounds.close(level, worldPosition); + animatedPackage = null; + return; + } + + if (!currentlyDepositing) { + if (!ItemHandlerHelper.insertItem(inventory, animatedPackage.copy(), false) + .isEmpty()) + drop(animatedPackage); + } + + animatedPackage = null; + } + + public void startAnimation(ItemStack box, boolean deposit) { + if (!PackageItem.isPackage(box)) + return; + + if (deposit && (target == null + || target.depositImmediately() && !target.export(level, worldPosition, box.copy(), false))) + return; + + animationProgress.startWithValue(0); + animationProgress.chase(1, 0.1, Chaser.LINEAR); + animatedPackage = box; + currentlyDepositing = deposit; + + if (level != null && !deposit && !level.isClientSide()) + advancements.awardPlayer(AllAdvancements.FROGPORT); + + if (level != null && level.isClientSide()) { + sounds.open(level, worldPosition); + + if (currentlyDepositing) { + sounds.depositPackage(level, worldPosition); + + } else { + sounds.catchPackage(level, worldPosition); + Vec3 vec = target.getExactTargetLocation(this, level, worldPosition); + if (vec != null) + for (int i = 0; i < 5; i++) + level.addParticle( + new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.ROPE.getDefaultState()), vec.x, + vec.y - level.random.nextFloat() * 0.25, vec.z, 0, 0, 0); + } + } + + if (level != null && !level.isClientSide()) { + level.blockEntityChanged(worldPosition); + sendData(); + } + } + + protected void tryPushingToAdjacentInventories() { + failedLastExport = false; + IItemHandler inventory = itemHandler.orElse(null); + + if (inventory == null) + return; + + boolean empty = true; + for (int i = 0; i < inventory.getSlots(); i++) + if (!inventory.getStackInSlot(i) + .isEmpty()) + empty = false; + if (empty) + return; + IItemHandler handler = getAdjacentInventory(Direction.DOWN); + if (handler == null) + return; + + for (int i = 0; i < inventory.getSlots(); i++) { + ItemStack stackInSlot = inventory.extractItem(i, 1, true); + if (stackInSlot.isEmpty()) + continue; + ItemStack remainder = ItemHandlerHelper.insertItemStacked(handler, stackInSlot, false); + if (remainder.isEmpty()) { + inventory.extractItem(i, 1, false); + level.blockEntityChanged(worldPosition); + } else + failedLastExport = true; + } + } + + @Override + protected void onOpenChange(boolean open) { + } + + public void tryPullingFromOwnAndAdjacentInventories() { + if (isAnimationInProgress()) + return; + if (target == null || !target.export(level, worldPosition, PackageStyles.getDefaultBox(), true)) + return; + if (tryPullingFrom(inventory)) + return; + for (Direction side : Iterate.directions) { + if (side != Direction.DOWN) + continue; + IItemHandler handler = getAdjacentInventory(side); + if (handler == null) + continue; + if (tryPullingFrom(handler)) + return; + } + } + + public boolean tryPullingFrom(IItemHandler handler) { + ItemStack extract = ItemHelper.extract(handler, stack -> { + if (!PackageItem.isPackage(stack)) + return false; + String filterString = getFilterString(); + return filterString == null || handler instanceof PackagerItemHandler + || !PackageItem.matchAddress(stack, filterString); + }, false); + if (extract.isEmpty()) + return false; + startAnimation(extract, true); + return true; + + } + + protected IItemHandler getAdjacentInventory(Direction side) { + BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(side)); + if (blockEntity == null || blockEntity instanceof FrogportBlockEntity) + return null; + return blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER, side.getOpposite()) + .orElse(null); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.putFloat("PlacedYaw", passiveYaw); + if (animatedPackage != null && isAnimationInProgress()) { + tag.put("AnimatedPackage", animatedPackage.serializeNBT()); + tag.putBoolean("Deposit", currentlyDepositing); + } + if (sendAnticipate) { + sendAnticipate = false; + tag.putBoolean("Anticipate", true); + } + if (failedLastExport) + NBTHelper.putMarker(tag, "FailedLastExport"); + if (goggles) + NBTHelper.putMarker(tag, "Goggles"); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + passiveYaw = tag.getFloat("PlacedYaw"); + failedLastExport = tag.getBoolean("FailedLastExport"); + goggles = tag.getBoolean("Goggles"); + if (!clientPacket) + animatedPackage = null; + if (tag.contains("AnimatedPackage")) { + deferAnimationInward = tag.getBoolean("Deposit"); + deferAnimationStart = ItemStack.of(tag.getCompound("AnimatedPackage")); + } + if (clientPacket && tag.contains("Anticipate")) + anticipate(); + } + + public float getYaw() { + if (target == null) + return passiveYaw; + Vec3 diff = target.getExactTargetLocation(this, level, worldPosition) + .subtract(Vec3.atCenterOf(worldPosition)); + return (float) (Mth.atan2(diff.x, diff.z) * Mth.RAD_TO_DEG) + 180; + } + + @Override + public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + boolean superTip = IHaveHoveringInformation.super.addToTooltip(tooltip, isPlayerSneaking); + if (!failedLastExport) + return superTip; + TooltipHelper.addHint(tooltip, "hint.blocked_frogport"); + return true; + } + + @Override + protected void onOpenedManually() { + if (level.isClientSide()) + sounds.open(level, worldPosition); + } + + @Override + public InteractionResult use(Player player) { + if (player == null) + return InteractionResult.PASS; + + ItemStack mainHandItem = player.getMainHandItem(); + if (!goggles && AllItems.GOGGLES.isIn(mainHandItem)) { + goggles = true; + if (!level.isClientSide()) { + notifyUpdate(); + level.playSound(null, worldPosition, SoundEvents.ARMOR_EQUIP_GOLD, SoundSource.BLOCKS, 0.5f, 1.0f); + } + return InteractionResult.SUCCESS; + } + + return super.use(player); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportRenderer.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportRenderer.java new file mode 100644 index 0000000000..7352ba2d5f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportRenderer.java @@ -0,0 +1,182 @@ +package com.simibubi.create.content.logistics.packagePort.frogport; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; + +import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.registries.ForgeRegistries; + +public class FrogportRenderer extends SmartBlockEntityRenderer { + + public FrogportRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(FrogportBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + SuperByteBuffer body = CachedBuffers.partial(AllPartialModels.FROGPORT_BODY, blockEntity.getBlockState()); + + float yaw = blockEntity.getYaw(); + + float headPitch = 80; + float tonguePitch = 0; + float tongueLength = 0; + float headPitchModifier = 1; + + boolean hasTarget = blockEntity.target != null; + boolean animating = blockEntity.isAnimationInProgress(); + boolean depositing = blockEntity.currentlyDepositing; + + Vec3 diff = Vec3.ZERO; + + if (blockEntity.addressFilter != null && !blockEntity.addressFilter.isBlank()) { + renderNameplateOnHover(blockEntity, Component.literal(blockEntity.addressFilter), 1, ms, buffer, light); + } + + if (VisualizationManager.supportsVisualization(blockEntity.getLevel())) { + return; + } + + if (hasTarget) { + diff = blockEntity.target + .getExactTargetLocation(blockEntity, blockEntity.getLevel(), blockEntity.getBlockPos()) + .subtract(0, animating && depositing ? 0 : 0.75, 0) + .subtract(Vec3.atCenterOf(blockEntity.getBlockPos())); + tonguePitch = (float) Mth.atan2(diff.y, diff.multiply(1, 0, 1) + .length() + (3 / 16f)) * Mth.RAD_TO_DEG; + tongueLength = Math.max((float) diff.length(), 1); + headPitch = Mth.clamp(tonguePitch * 2, 60, 100); + } + + if (animating) { + float progress = blockEntity.animationProgress.getValue(partialTicks); + float scale = 1; + float itemDistance = 0; + + if (depositing) { + double modifier = Math.max(0, 1 - Math.pow((progress - 0.25) * 4 - 1, 4)); + itemDistance = + (float) Math.max(tongueLength * Math.min(1, (progress - 0.25) * 3), tongueLength * modifier); + tongueLength *= Math.max(0, 1 - Math.pow((progress * 1.25 - 0.25) * 4 - 1, 4)); + headPitchModifier = (float) Math.max(0, 1 - Math.pow((progress * 1.25) * 2 - 1, 4)); + scale = 0.25f + progress * 3 / 4; + + } else { + tongueLength *= Math.pow(Math.max(0, 1 - progress * 1.25), 5); + headPitchModifier = 1 - (float) Math.min(1, Math.max(0, (Math.pow(progress * 1.5, 2) - 0.5) * 2)); + scale = (float) Math.max(0.5, 1 - progress * 1.25); + itemDistance = tongueLength; + } + + renderPackage(blockEntity, ms, buffer, light, overlay, diff, scale, itemDistance); + + } else { + tongueLength = 0; + float anticipation = blockEntity.anticipationProgress.getValue(partialTicks); + headPitchModifier = + anticipation > 0 ? (float) Math.max(0, 1 - Math.pow((anticipation * 1.25) * 2 - 1, 4)) : 0; + } + + headPitch *= headPitchModifier; + + headPitch = Math.max(headPitch, blockEntity.manualOpenAnimationProgress.getValue(partialTicks) * 60); + tongueLength = Math.max(tongueLength, blockEntity.manualOpenAnimationProgress.getValue(partialTicks) * 0.25f); + + + body.center() + .rotateYDegrees(yaw) + .uncenter() + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + + SuperByteBuffer head = CachedBuffers.partial(blockEntity.goggles ? AllPartialModels.FROGPORT_HEAD_GOGGLES : AllPartialModels.FROGPORT_HEAD, blockEntity.getBlockState()); + + head.center() + .rotateYDegrees(yaw) + .uncenter() + .translate(8 / 16f, 10 / 16f, 11 / 16f) + .rotateXDegrees(headPitch) + .translateBack(8 / 16f, 10 / 16f, 11 / 16f); + + head.light(light) +// .color(color) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + + SuperByteBuffer tongue = CachedBuffers.partial(AllPartialModels.FROGPORT_TONGUE, blockEntity.getBlockState()); + + tongue.center() + .rotateYDegrees(yaw) + .uncenter() + .translate(8 / 16f, 10 / 16f, 11 / 16f) + .rotateXDegrees(tonguePitch) + .scale(1f, 1f, tongueLength / (7 / 16f)) + .translateBack(8 / 16f, 10 / 16f, 11 / 16f); + + tongue.light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + + // hat + +// SuperByteBuffer hatBuffer = CachedBuffers.partial(AllPartialModels.TRAIN_HAT, blockEntity.getBlockState()); +// hatBuffer +// .translate(8 / 16f, 14 / 16f, 8 / 16f) +// .rotateYDegrees(yaw + 180) +// .translate(0, 0, -3 / 16f) +// .rotateX(-4) +// .translateBack(0, 0, -3 / 16f) +// .translate(0, 0, 1 / 16f) +// .light(light) +// .color(color) +// .overlay(overlay) +// .renderInto(ms, buffer.getBuffer(RenderType.solid())); + + } + + private void renderPackage(FrogportBlockEntity blockEntity, PoseStack ms, MultiBufferSource buffer, int light, + int overlay, Vec3 diff, float scale, float itemDistance) { + if (blockEntity.animatedPackage == null) + return; + if (scale < 0.45) + return; + ResourceLocation key = ForgeRegistries.ITEMS.getKey(blockEntity.animatedPackage.getItem()); + if (key == null) + return; + SuperByteBuffer rigBuffer = + CachedBuffers.partial(AllPartialModels.PACKAGE_RIGGING.get(key), blockEntity.getBlockState()); + SuperByteBuffer boxBuffer = + CachedBuffers.partial(AllPartialModels.PACKAGES.get(key), blockEntity.getBlockState()); + + boolean animating = blockEntity.isAnimationInProgress(); + boolean depositing = blockEntity.currentlyDepositing; + + for (SuperByteBuffer buf : new SuperByteBuffer[] { boxBuffer, rigBuffer }) { + buf.translate(0, 3 / 16f, 0) + .translate(diff.normalize() + .scale(itemDistance) + .subtract(0, animating && depositing ? 0.75 : 0, 0)) + .center() + .scale(scale) + .uncenter() + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutout())); + if (!blockEntity.currentlyDepositing) + break; + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportSounds.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportSounds.java new file mode 100644 index 0000000000..a509e840f5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportSounds.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.logistics.packagePort.frogport; + +import com.simibubi.create.AllSoundEvents; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +public class FrogportSounds { + + public void open(Level level, BlockPos pos) { + AllSoundEvents.FROGPORT_OPEN.playAt(level, Vec3.atCenterOf(pos), 0.5f, 1, false); + } + + public void close(Level level, BlockPos pos) { + if (!isPlayerNear(pos)) + return; + AllSoundEvents.FROGPORT_CLOSE.playAt(level, Vec3.atCenterOf(pos), 1.0f, 1.25f + level.random.nextFloat() * 0.25f, + true); + } + + public void catchPackage(Level level, BlockPos pos) { + if (!isPlayerNear(pos)) + return; + AllSoundEvents.FROGPORT_CATCH.playAt(level, Vec3.atCenterOf(pos), 1, 1, false); + } + + public void depositPackage(Level level, BlockPos pos) { + if (!isPlayerNear(pos)) + return; + AllSoundEvents.FROGPORT_DEPOSIT.playAt(level, Vec3.atCenterOf(pos), 1, 1, false); + } + + private boolean isPlayerNear(BlockPos pos) { + return pos.closerThan(Minecraft.getInstance().player.blockPosition(), 20); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportVisual.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportVisual.java new file mode 100644 index 0000000000..b1e0b7f069 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/frogport/FrogportVisual.java @@ -0,0 +1,268 @@ +package com.simibubi.create.content.logistics.packagePort.frogport; + +import java.util.function.Consumer; + +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; + +import com.simibubi.create.AllPartialModels; + +import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.instance.InstanceTypes; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.model.Models; +import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; +import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.registries.ForgeRegistries; + +public class FrogportVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { + private final TransformedInstance body; + private TransformedInstance head; + private final TransformedInstance tongue; + private final TransformedInstance rig; + private final TransformedInstance box; + + private final Matrix4f basePose = new Matrix4f(); + private float lastYaw = Float.NaN; + private float lastHeadPitch = Float.NaN; + private float lastTonguePitch = Float.NaN; + private float lastTongueLength = Float.NaN; + private boolean lastGoggles = false; + + public FrogportVisual(VisualizationContext ctx, FrogportBlockEntity blockEntity, float partialTick) { + super(ctx, blockEntity, partialTick); + + body = ctx.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FROGPORT_BODY)) + .createInstance(); + + head = ctx.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FROGPORT_HEAD)) + .createInstance(); + + tongue = ctx.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FROGPORT_TONGUE)) + .createInstance(); + + rig = ctx.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, Models.block(Blocks.AIR.defaultBlockState())) + .createInstance(); + + box = ctx.instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, Models.block(Blocks.AIR.defaultBlockState())) + .createInstance(); + + rig.handle().setVisible(false); + box.handle().setVisible(false); + + animate(partialTick); + } + + @Override + public void beginFrame(Context ctx) { + animate(ctx.partialTick()); + } + + private void animate(float partialTicks) { + updateGoggles(); + + float yaw = blockEntity.getYaw(); + + float headPitch = 80; + float tonguePitch = 0; + float tongueLength = 0; + float headPitchModifier = 1; + + boolean hasTarget = blockEntity.target != null; + boolean animating = blockEntity.isAnimationInProgress(); + boolean depositing = blockEntity.currentlyDepositing; + + Vec3 diff = Vec3.ZERO; + + if (hasTarget) { + diff = blockEntity.target + .getExactTargetLocation(blockEntity, blockEntity.getLevel(), blockEntity.getBlockPos()) + .subtract(0, animating && depositing ? 0 : 0.75, 0) + .subtract(Vec3.atCenterOf(blockEntity.getBlockPos())); + tonguePitch = (float) Mth.atan2(diff.y, diff.multiply(1, 0, 1) + .length() + (3 / 16f)) * Mth.RAD_TO_DEG; + tongueLength = Math.max((float) diff.length(), 1); + headPitch = Mth.clamp(tonguePitch * 2, 60, 100); + } + + if (animating) { + float progress = blockEntity.animationProgress.getValue(partialTicks); + float scale = 1; + float itemDistance = 0; + + if (depositing) { + double modifier = Math.max(0, 1 - Math.pow((progress - 0.25) * 4 - 1, 4)); + itemDistance = + (float) Math.max(tongueLength * Math.min(1, (progress - 0.25) * 3), tongueLength * modifier); + tongueLength *= Math.max(0, 1 - Math.pow((progress * 1.25 - 0.25) * 4 - 1, 4)); + headPitchModifier = (float) Math.max(0, 1 - Math.pow((progress * 1.25) * 2 - 1, 4)); + scale = 0.25f + progress * 3 / 4; + + } else { + tongueLength *= Math.pow(Math.max(0, 1 - progress * 1.25), 5); + headPitchModifier = 1 - (float) Math.min(1, Math.max(0, (Math.pow(progress * 1.5, 2) - 0.5) * 2)); + scale = (float) Math.max(0.5, 1 - progress * 1.25); + itemDistance = tongueLength; + } + + renderPackage(diff, scale, itemDistance); + + } else { + tongueLength = 0; + float anticipation = blockEntity.anticipationProgress.getValue(partialTicks); + headPitchModifier = + anticipation > 0 ? (float) Math.max(0, 1 - Math.pow((anticipation * 1.25) * 2 - 1, 4)) : 0; + rig.handle() + .setVisible(false); + box.handle() + .setVisible(false); + } + + headPitch *= headPitchModifier; + + headPitch = Math.max(headPitch, blockEntity.manualOpenAnimationProgress.getValue(partialTicks) * 60); + tongueLength = Math.max(tongueLength, blockEntity.manualOpenAnimationProgress.getValue(partialTicks) * 0.25f); + + if (yaw != lastYaw) { + body.setIdentityTransform() + .translate(getVisualPosition()) + .center() + .rotateYDegrees(yaw) + .uncenter() + .setChanged(); + + // Save the base pose to avoid recalculating it twice every frame + basePose.set(body.pose) + .translate(8 / 16f, 10 / 16f, 11 / 16f); + + // I'm not entirely sure that yaw ever changes + lastYaw = yaw; + + // Force the head and tongue to update + lastTonguePitch = Float.NaN; + lastHeadPitch = Float.NaN; + } + + if (headPitch != lastHeadPitch) { + head.setTransform(basePose) + .rotateXDegrees(headPitch) + .translateBack(8 / 16f, 10 / 16f, 11 / 16f) + .setChanged(); + + lastHeadPitch = headPitch; + } + + if (tonguePitch != lastTonguePitch || tongueLength != lastTongueLength) { + tongue.setTransform(basePose) + .rotateXDegrees(tonguePitch) + .scale(1f, 1f, tongueLength / (7 / 16f)) + .translateBack(8 / 16f, 10 / 16f, 11 / 16f) + .setChanged(); + + lastTonguePitch = tonguePitch; + lastTongueLength = tongueLength; + } + } + + public void updateGoggles() { + if (blockEntity.goggles && !lastGoggles) { + head.delete(); + head = instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FROGPORT_HEAD_GOGGLES)) + .createInstance(); + lastHeadPitch = -1; + updateLight(0); + lastGoggles = true; + } + + if (!blockEntity.goggles && lastGoggles) { + head.delete(); + head = instancerProvider() + .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.FROGPORT_HEAD)) + .createInstance(); + lastHeadPitch = -1; + updateLight(0); + lastGoggles = false; + } + } + + private void renderPackage(Vec3 diff, float scale, float itemDistance) { + if (blockEntity.animatedPackage == null || scale < 0.45) { + rig.handle() + .setVisible(false); + box.handle() + .setVisible(false); + return; + } + ResourceLocation key = ForgeRegistries.ITEMS.getKey(blockEntity.animatedPackage.getItem()); + if (key == null) { + rig.handle() + .setVisible(false); + box.handle() + .setVisible(false); + return; + } + + boolean animating = blockEntity.isAnimationInProgress(); + boolean depositing = blockEntity.currentlyDepositing; + + instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.PACKAGES.get(key))) + .stealInstance(box); + box.handle().setVisible(true); + + box.setIdentityTransform() + .translate(getVisualPosition()) + .translate(0, 3 / 16f, 0) + .translate(diff.normalize() + .scale(itemDistance) + .subtract(0, animating && depositing ? 0.75 : 0, 0)) + .center() + .scale(scale) + .uncenter() + .setChanged(); + + if (!depositing) { + rig.handle() + .setVisible(false); + return; + } + + instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.PACKAGE_RIGGING.get(key))) + .stealInstance(rig); + rig.handle().setVisible(true); + + rig.pose.set(box.pose); + rig.setChanged(); + } + + @Override + public void collectCrumblingInstances(Consumer<@Nullable Instance> consumer) { + consumer.accept(body); + consumer.accept(head); + } + + @Override + public void updateLight(float partialTick) { + relight(body, head, tongue, rig, box); + } + + @Override + protected void _delete() { + body.delete(); + head.delete(); + tongue.delete(); + rig.delete(); + box.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxBlock.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxBlock.java new file mode 100644 index 0000000000..5f00e165e7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxBlock.java @@ -0,0 +1,116 @@ +package com.simibubi.create.content.logistics.packagePort.postbox; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class PostboxBlock extends HorizontalDirectionalBlock + implements IBE, IWrenchable, ProperWaterloggedBlock { + + public static final BooleanProperty OPEN = BlockStateProperties.OPEN; + + protected final DyeColor color; + + public PostboxBlock(Properties properties, DyeColor color) { + super(properties); + this.color = color; + registerDefaultState(defaultBlockState().setValue(OPEN, false) + .setValue(WATERLOGGED, false)); + } + + public DyeColor getColor() { + return color; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + Direction facing = pContext.getHorizontalDirection() + .getOpposite(); + return withWater(super.getStateForPlacement(pContext).setValue(FACING, facing), pContext); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pPos); + return pState; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.POSTBOX.get(pState.getValue(FACING)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(FACING, OPEN, WATERLOGGED)); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + return onBlockEntityUse(pLevel, pPos, be -> be.use(pPlayer)); + } + + @Override + public Class getBlockEntityClass() { + return PostboxBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.PACKAGE_POSTBOX.get(); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + public boolean hasAnalogOutputSignal(BlockState pState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { + return getBlockEntityOptional(pLevel, pPos).map(pbe -> pbe.getComparatorOutput()) + .orElse(0); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxBlockEntity.java new file mode 100644 index 0000000000..1e91d1a753 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxBlockEntity.java @@ -0,0 +1,113 @@ +package com.simibubi.create.content.logistics.packagePort.postbox; + +import java.lang.ref.WeakReference; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.packagePort.PackagePortBlockEntity; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.station.GlobalStation.GlobalPackagePort; + +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.item.BoneMealItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class PostboxBlockEntity extends PackagePortBlockEntity { + + public WeakReference trackedGlobalStation; + + public LerpedFloat flag; + public boolean forceFlag; + + private boolean sendParticles; + + public PostboxBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + trackedGlobalStation = new WeakReference<>(null); + flag = LerpedFloat.linear() + .startWithValue(0); + } + + @Override + public void tick() { + super.tick(); + if (!level.isClientSide && !isVirtual()) { + if (sendParticles) + sendData(); + return; + } + + float currentTarget = flag.getChaseTarget(); + if (currentTarget == 0 || flag.settled()) { + int target = (inventory.isEmpty() && !forceFlag) ? 0 : 1; + if (target != currentTarget) { + flag.chase(target, 0.1f, Chaser.LINEAR); + if (target == 1) + AllSoundEvents.CONTRAPTION_ASSEMBLE.playAt(level, worldPosition, 1, 2, true); + } + } + boolean settled = flag.getValue() > .15f; + flag.tickChaser(); + if (currentTarget == 0 && settled != flag.getValue() > .15f) + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playAt(level, worldPosition, 0.75f, 1.5f, true); + + if (sendParticles) { + sendParticles = false; + BoneMealItem.addGrowthParticles(level, worldPosition, 40); + } + } + + @Override + protected void onOpenChange(boolean open) { + level.setBlockAndUpdate(worldPosition, getBlockState().setValue(PostboxBlock.OPEN, open)); + level.playSound(null, worldPosition, open ? SoundEvents.BARREL_OPEN : SoundEvents.BARREL_CLOSE, + SoundSource.BLOCKS); + } + + public void spawnParticles() { + sendParticles = true; + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + if (clientPacket && sendParticles) + NBTHelper.putMarker(tag, "Particles"); + sendParticles = false; + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + sendParticles = clientPacket && tag.contains("Particles"); + } + + @Override + public void onChunkUnloaded() { + if (level == null || level.isClientSide) + return; + GlobalStation station = trackedGlobalStation.get(); + if (station == null) + return; + if (!station.connectedPorts.containsKey(worldPosition)) + return; + GlobalPackagePort globalPackagePort = station.connectedPorts.get(worldPosition); + for (int i = 0; i < inventory.getSlots(); i++) { + globalPackagePort.offlineBuffer.setStackInSlot(i, inventory.getStackInSlot(i)); + inventory.setStackInSlot(i, ItemStack.EMPTY); + } + + globalPackagePort.primed = true; + Create.RAILWAYS.markTracksDirty(); + super.onChunkUnloaded(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxRenderer.java b/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxRenderer.java new file mode 100644 index 0000000000..edeeb888f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagePort/postbox/PostboxRenderer.java @@ -0,0 +1,56 @@ +package com.simibubi.create.content.logistics.packagePort.postbox; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; + +import dev.engine_room.flywheel.lib.transform.Transform; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; + +public class PostboxRenderer extends SmartBlockEntityRenderer { + + public PostboxRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(PostboxBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + + if (blockEntity.addressFilter != null && !blockEntity.addressFilter.isBlank()) { + renderNameplateOnHover(blockEntity, Component.literal(blockEntity.addressFilter), 1, ms, buffer, light); + } + + SuperByteBuffer sbb = CachedBuffers.partial(AllPartialModels.POSTBOX_FLAG, blockEntity.getBlockState()); + + sbb.light(light) + .overlay(overlay) + .rotateCentered(Mth.DEG_TO_RAD * (180 - blockEntity.getBlockState() + .getValue(PostboxBlock.FACING) + .toYRot()), Axis.YP); + + transformFlag(sbb, blockEntity, partialTicks); + + sbb.renderInto(ms, buffer.getBuffer(RenderType.cutout())); + } + + public static void transformFlag(Transform flag, PostboxBlockEntity be, float partialTicks) { + float value = be.flag.getValue(partialTicks); + float progress = (float) (Math.pow(Math.min(value * 5, 1), 2)); + if (be.flag.getChaseTarget() > 0 && !be.flag.settled() && progress == 1) { + float wiggleProgress = (value - .2f) / .8f; + progress += (Math.sin(wiggleProgress * (2 * Mth.PI) * 4) / 8f) / Math.max(1, 8f * wiggleProgress); + } + flag.translate(0, 10 / 16f, 2 / 16f); + flag.rotateXDegrees(-progress * 90); + flag.translateBack(0, 10 / 16f, 2 / 16f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/InventorySummary.java b/src/main/java/com/simibubi/create/content/logistics/packager/InventorySummary.java new file mode 100644 index 0000000000..e57f1cc1df --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/InventorySummary.java @@ -0,0 +1,195 @@ +package com.simibubi.create.content.logistics.packager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +import org.apache.commons.lang3.mutable.MutableInt; + +import com.google.common.collect.Lists; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.stockTicker.LogisticalStockResponsePacket; + +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.network.PacketDistributor; +import net.minecraftforge.network.PacketDistributor.PacketTarget; + +public class InventorySummary { + + public static final InventorySummary EMPTY = new InventorySummary(); + + private Map> items = new IdentityHashMap<>(); + private List stacksByCount; + private int totalCount; + + public int contributingLinks; + + public void add(InventorySummary summary) { + summary.items.forEach((i, list) -> list.forEach(this::add)); + contributingLinks += summary.contributingLinks; + } + + public void add(ItemStack stack) { + add(stack, stack.getCount()); + } + + public void add(BigItemStack entry) { + add(entry.stack, entry.count); + } + + public Map> getItemMap() { + return items; + } + + public InventorySummary copy() { + InventorySummary inventorySummary = new InventorySummary(); + items.forEach((i, list) -> list.forEach(entry -> inventorySummary.add(entry.stack, entry.count))); + return inventorySummary; + } + + public void add(ItemStack stack, int count) { + if (count == 0 || stack.isEmpty()) + return; + + if (totalCount < BigItemStack.INF) + totalCount += count; + + List stacks = items.computeIfAbsent(stack.getItem(), $ -> Lists.newArrayList()); + for (BigItemStack existing : stacks) { + ItemStack existingStack = existing.stack; + if (ItemHandlerHelper.canItemStacksStack(existingStack, stack)) { + if (existing.count < BigItemStack.INF) + existing.count += count; + return; + } + } + + if (stack.getCount() > stack.getMaxStackSize()) + stack = stack.copyWithCount(1); + + BigItemStack newEntry = new BigItemStack(stack, count); + stacks.add(newEntry); + } + + public boolean erase(ItemStack stack) { + List stacks = items.get(stack.getItem()); + if (stacks == null) + return false; + for (Iterator iterator = stacks.iterator(); iterator.hasNext();) { + BigItemStack existing = iterator.next(); + ItemStack existingStack = existing.stack; + if (!ItemHandlerHelper.canItemStacksStack(existingStack, stack)) + continue; + totalCount -= existing.count; + iterator.remove(); + return true; + } + return false; + } + + public int getCountOf(ItemStack stack) { + List list = items.get(stack.getItem()); + if (list == null) + return 0; + for (BigItemStack entry : list) + if (ItemHandlerHelper.canItemStacksStack(entry.stack, stack)) + return entry.count; + return 0; + } + + public int getTotalOfMatching(Predicate filter) { + MutableInt sum = new MutableInt(); + items.forEach(($, list) -> { + for (BigItemStack entry : list) + if (filter.test(entry.stack)) + sum.add(entry.count); + }); + return sum.getValue(); + } + + public List getStacks() { + if (stacksByCount == null) { + List stacks = new ArrayList<>(); + items.forEach((i, list) -> list.forEach(stacks::add)); + return stacks; + } + return stacksByCount; + } + + public List getStacksByCount() { + if (stacksByCount == null) { + stacksByCount = new ArrayList<>(); + items.forEach((i, list) -> list.forEach(stacksByCount::add)); + Collections.sort(stacksByCount, BigItemStack.comparator()); + } + return stacksByCount; + } + + public int getTotalCount() { + return totalCount; + } + + public void divideAndSendTo(ServerPlayer player, BlockPos pos) { + List stacks = getStacksByCount(); + int remaining = stacks.size(); + + List currentList = null; + PacketTarget target = PacketDistributor.PLAYER.with(() -> player); + + if (stacks.isEmpty()) + AllPackets.getChannel() + .send(target, new LogisticalStockResponsePacket(true, pos, Collections.emptyList())); + + for (BigItemStack entry : stacks) { + if (currentList == null) + currentList = new ArrayList<>(Math.min(100, remaining)); + + currentList.add(entry); + remaining--; + + if (remaining == 0) + break; + if (currentList.size() < 100) + continue; + + AllPackets.getChannel() + .send(target, new LogisticalStockResponsePacket(false, pos, currentList)); + currentList = null; + } + + if (currentList != null) + AllPackets.getChannel() + .send(target, new LogisticalStockResponsePacket(true, pos, currentList)); + } + + public CompoundTag write() { + List all = new ArrayList<>(); + items.forEach((key, list) -> all.addAll(list)); + CompoundTag tag = new CompoundTag(); + tag.put("List", NBTHelper.writeCompoundList(all, BigItemStack::write)); + return tag; + } + + public static InventorySummary read(CompoundTag tag) { + InventorySummary summary = new InventorySummary(); + NBTHelper.iterateCompoundList(tag.getList("List", Tag.TAG_COMPOUND), c -> summary.add(BigItemStack.read(c))); + return summary; + } + + public boolean isEmpty() { + return items.isEmpty(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackageDefragmenter.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackageDefragmenter.java new file mode 100644 index 0000000000..77fc51f258 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackageDefragmenter.java @@ -0,0 +1,180 @@ +package com.simibubi.create.content.logistics.packager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Lists; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +public class PackageDefragmenter { + + protected Map> collectedPackages = new HashMap<>(); + + public void clear() { + collectedPackages.clear(); + } + + public boolean isFragmented(ItemStack box) { + if (!box.hasTag() || !box.getTag() + .contains("Fragment")) + return false; + + CompoundTag fragTag = box.getTag() + .getCompound("Fragment"); + + return !(fragTag.getInt("LinkIndex") == 0 && fragTag.getBoolean("IsFinalLink") && fragTag.getInt("Index") == 0 + && fragTag.getBoolean("IsFinal")); + } + + public int addPackageFragment(ItemStack box) { + int collectedOrderId = PackageItem.getOrderId(box); + if (collectedOrderId == -1) + return -1; + + List collectedOrder = collectedPackages.computeIfAbsent(collectedOrderId, $ -> Lists.newArrayList()); + collectedOrder.add(box); + + if (!isOrderComplete(collectedOrderId)) + return -1; + + return collectedOrderId; + } + + public List repack(int orderId) { + List exportingPackages = new ArrayList<>(); + String address = ""; + PackageOrder orderContext = null; + List allItems = new ArrayList<>(); + + for (ItemStack box : collectedPackages.get(orderId)) { + address = PackageItem.getAddress(box); + if (box.hasTag() && box.getTag() + .getCompound("Fragment") + .contains("OrderContext")) + orderContext = PackageOrder.read(box.getTag() + .getCompound("Fragment") + .getCompound("OrderContext")); + ItemStackHandler contents = PackageItem.getContents(box); + Slots: for (int slot = 0; slot < contents.getSlots(); slot++) { + ItemStack stackInSlot = contents.getStackInSlot(slot); + for (BigItemStack existing : allItems) { + if (!ItemHandlerHelper.canItemStacksStack(stackInSlot, existing.stack)) + continue; + existing.count += stackInSlot.getCount(); + continue Slots; + } + allItems.add(new BigItemStack(stackInSlot, stackInSlot.getCount())); + } + } + + List orderedStacks = new ArrayList<>(); + List originalContext = new ArrayList<>(); + if (orderContext != null) { + for (BigItemStack stack : orderContext.stacks()) { + orderedStacks.add(new BigItemStack(stack.stack, stack.count)); + originalContext.add(new BigItemStack(stack.stack, stack.count)); + } + } + + List outputSlots = new ArrayList<>(); + + Repack: while (true) { + allItems.removeIf(e -> e.count == 0); + if (allItems.isEmpty()) + break; + + BigItemStack targetedEntry = null; + if (!orderedStacks.isEmpty()) + targetedEntry = orderedStacks.remove(0); + + ItemSearch: for (BigItemStack entry : allItems) { + int targetAmount = entry.count; + if (targetAmount == 0) + continue; + if (targetedEntry != null) { + targetAmount = targetedEntry.count; + if (!ItemHandlerHelper.canItemStacksStack(entry.stack, targetedEntry.stack)) + continue; + } + + while (targetAmount > 0) { + int removedAmount = Math.min(Math.min(targetAmount, entry.stack.getMaxStackSize()), entry.count); + if (removedAmount == 0) + continue ItemSearch; + + ItemStack output = ItemHandlerHelper.copyStackWithSize(entry.stack, removedAmount); + targetAmount -= removedAmount; + targetedEntry.count = targetAmount; + entry.count -= removedAmount; + outputSlots.add(output); + } + + continue Repack; + } + } + + int currentSlot = 0; + ItemStackHandler target = new ItemStackHandler(PackageItem.SLOTS); + + for (ItemStack item : outputSlots) { + target.setStackInSlot(currentSlot++, item); + if (currentSlot < PackageItem.SLOTS) + continue; + exportingPackages.add(PackageItem.containing(target)); + target = new ItemStackHandler(PackageItem.SLOTS); + currentSlot = 0; + } + + for (int slot = 0; slot < target.getSlots(); slot++) + if (!target.getStackInSlot(slot) + .isEmpty()) { + exportingPackages.add(PackageItem.containing(target)); + break; + } + + for (ItemStack box : exportingPackages) + PackageItem.addAddress(box, address); + + for (int i = 0; i < exportingPackages.size(); i++) { + ItemStack box = exportingPackages.get(i); + boolean isfinal = i == exportingPackages.size() - 1; + PackageItem.setOrder(box, orderId, 0, true, 0, true, isfinal ? new PackageOrder(originalContext) : null); + } + + return exportingPackages; + } + + private boolean isOrderComplete(int orderId) { + boolean finalLinkReached = false; + Links: for (int linkCounter = 0; linkCounter < 1000; linkCounter++) { + if (finalLinkReached) + break; + Packages: for (int packageCounter = 0; packageCounter < 1000; packageCounter++) { + for (ItemStack box : collectedPackages.get(orderId)) { + CompoundTag tag = box.getOrCreateTag() + .getCompound("Fragment"); + if (linkCounter != tag.getInt("LinkIndex")) + continue; + if (packageCounter != tag.getInt("Index")) + continue; + finalLinkReached = tag.getBoolean("IsFinalLink"); + if (tag.getBoolean("IsFinal")) + continue Links; + continue Packages; + } + return false; + } + } + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackagerBlock.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerBlock.java new file mode 100644 index 0000000000..dff5c7f707 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerBlock.java @@ -0,0 +1,218 @@ +package com.simibubi.create.content.logistics.packager; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.SignalGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.items.IItemHandler; + +public class PackagerBlock extends WrenchableDirectionalBlock implements IBE, IWrenchable { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty LINKED = BooleanProperty.create("linked"); + + public PackagerBlock(Properties properties) { + super(properties); + BlockState defaultBlockState = defaultBlockState(); + if (defaultBlockState.hasProperty(LINKED)) + defaultBlockState = defaultBlockState.setValue(LINKED, false); + registerDefaultState(defaultBlockState.setValue(POWERED, false)); + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + Capability itemCap = ForgeCapabilities.ITEM_HANDLER; + Direction preferredFacing = null; + for (Direction face : context.getNearestLookingDirections()) { + BlockEntity be = context.getLevel() + .getBlockEntity(context.getClickedPos() + .relative(face)); + if (be instanceof PackagerBlockEntity) + continue; + if (be != null && (be.getCapability(itemCap) + .isPresent())) { + preferredFacing = face.getOpposite(); + break; + } + } + + Player player = context.getPlayer(); + if (preferredFacing == null) { + Direction facing = context.getNearestLookingDirection(); + preferredFacing = player != null && player + .isShiftKeyDown() ? facing : facing.getOpposite(); + } + + if (player != null && !(player instanceof FakePlayer)) { + if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(context.getLevel() + .getBlockState(context.getClickedPos() + .relative(preferredFacing.getOpposite())))) { + CreateLang.translate("packager.no_portable_storage") + .sendStatus(player); + return null; + } + } + + return super.getStateForPlacement(context).setValue(POWERED, context.getLevel() + .hasNeighborSignal(context.getClickedPos())) + .setValue(FACING, preferredFacing); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (player == null) + return InteractionResult.PASS; + + ItemStack itemInHand = player.getItemInHand(handIn); + if (AllItems.WRENCH.isIn(itemInHand)) + return InteractionResult.PASS; + if (AllBlocks.FACTORY_GAUGE.isIn(itemInHand)) + return InteractionResult.PASS; + if (AllBlocks.STOCK_LINK.isIn(itemInHand) && !state.getValue(LINKED)) + return InteractionResult.PASS; + if (AllBlocks.PACKAGE_FROGPORT.isIn(itemInHand)) + return InteractionResult.PASS; + + if (onBlockEntityUse(worldIn, pos, be -> { + if (be.heldBox.isEmpty()) { + if (be.animationTicks > 0) + return InteractionResult.SUCCESS; + if (PackageItem.isPackage(itemInHand)) { + if (worldIn.isClientSide()) + return InteractionResult.SUCCESS; + if (!be.unwrapBox(itemInHand.copy(), true)) + return InteractionResult.SUCCESS; + be.unwrapBox(itemInHand.copy(), false); + be.triggerStockCheck(); + itemInHand.shrink(1); + AllSoundEvents.DEPOT_PLOP.playOnServer(worldIn, pos); + if (itemInHand.isEmpty()) + player.setItemInHand(handIn, ItemStack.EMPTY); + return InteractionResult.SUCCESS; + } + return InteractionResult.SUCCESS; + } + if (be.animationTicks > 0) + return InteractionResult.SUCCESS; + if (!worldIn.isClientSide()) { + player.getInventory() + .placeItemBackInInventory(be.heldBox.copy()); + AllSoundEvents.playItemPickup(player); + be.heldBox = ItemStack.EMPTY; + be.notifyUpdate(); + } + return InteractionResult.SUCCESS; + }).consumesAction()) + return InteractionResult.SUCCESS; + + return InteractionResult.SUCCESS; + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED, LINKED)); + } + + @Override + public void onNeighborChange(BlockState state, LevelReader level, BlockPos pos, BlockPos neighbor) { + super.onNeighborChange(state, level, pos, neighbor); + if (neighbor.relative(state.getOptionalValue(FACING) + .orElse(Direction.UP)) + .equals(pos)) + withBlockEntityDo(level, pos, PackagerBlockEntity::triggerStockCheck); + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + if (worldIn.isClientSide) + return; + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered == worldIn.hasNeighborSignal(pos)) + return; + worldIn.setBlock(pos, state.cycle(POWERED), 2); + if (!previouslyPowered) + withBlockEntityDo(worldIn, pos, PackagerBlockEntity::activate); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + @Override + public boolean shouldCheckWeakPower(BlockState state, SignalGetter level, BlockPos pos, Direction side) { + return false; + } + + @Override + public Class getBlockEntityClass() { + return PackagerBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.PACKAGER.get(); + } + + @Override + public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) { + return false; + } + + @Override + public boolean hasAnalogOutputSignal(BlockState pState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { + return getBlockEntityOptional(pLevel, pPos).map(pbe -> { + boolean empty = pbe.inventory.getStackInSlot(0) + .isEmpty(); + if (pbe.animationTicks != 0) + empty = false; + return empty ? 0 : 15; + }) + .orElse(0); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackagerBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerBlockEntity.java new file mode 100644 index 0000000000..6d77e6be26 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerBlockEntity.java @@ -0,0 +1,687 @@ +package com.simibubi.create.content.logistics.packager; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceBlockEntity; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.crate.BottomlessItemHandler; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBehaviour; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlock; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBlockEntity; +import com.simibubi.create.content.logistics.packagePort.frogport.FrogportBlockEntity; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.packagerLink.PackagerLinkBlock; +import com.simibubi.create.content.logistics.packagerLink.PackagerLinkBlockEntity; +import com.simibubi.create.content.logistics.packagerLink.RequestPromiseQueue; +import com.simibubi.create.content.logistics.packagerLink.WiFiEffectPacket; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.content.processing.basin.BasinBlockEntity; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; + +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.Containers; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.SignBlockEntity; +import net.minecraft.world.level.block.entity.SignText; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +public class PackagerBlockEntity extends SmartBlockEntity { + + public boolean redstonePowered; + public int buttonCooldown; + public String signBasedAddress; + + public InvManipulationBehaviour targetInventory; + public ItemStack heldBox; + public ItemStack previouslyUnwrapped; + + public List queuedExitingPackages; + + public PackagerItemHandler inventory; + private final LazyOptional invProvider; + + public static final int CYCLE = 20; + public int animationTicks; + public boolean animationInward; + + private InventorySummary availableItems; + private VersionedInventoryTrackerBehaviour invVersionTracker; + + private AdvancementBehaviour advancements; + + // + + public PackagerBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + redstonePowered = state.getOptionalValue(PackagerBlock.POWERED) + .orElse(false); + heldBox = ItemStack.EMPTY; + previouslyUnwrapped = ItemStack.EMPTY; + inventory = new PackagerItemHandler(this); + invProvider = LazyOptional.of(() -> inventory); + animationTicks = 0; + animationInward = true; + queuedExitingPackages = new LinkedList<>(); + signBasedAddress = ""; + buttonCooldown = 0; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(targetInventory = new InvManipulationBehaviour(this, InterfaceProvider.oppositeOfBlockFacing()) + .withFilter(this::supportsBlockEntity)); + behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this)); + behaviours.add(advancements = new AdvancementBehaviour(this, AllAdvancements.PACKAGER)); + } + + private boolean supportsBlockEntity(BlockEntity target) { + return target != null && !(target instanceof PortableStorageInterfaceBlockEntity); + } + + @Override + public void initialize() { + super.initialize(); + recheckIfLinksPresent(); + } + + @Override + public void tick() { + super.tick(); + + if (buttonCooldown > 0) + buttonCooldown--; + + if (animationTicks == 0) { + previouslyUnwrapped = ItemStack.EMPTY; + + if (!level.isClientSide() && !queuedExitingPackages.isEmpty() && heldBox.isEmpty()) { + heldBox = queuedExitingPackages.remove(0); + animationInward = false; + animationTicks = CYCLE; + notifyUpdate(); + } + + return; + } + + if (level.isClientSide) { + if (animationTicks == CYCLE - (animationInward ? 5 : 1)) + AllSoundEvents.PACKAGER.playAt(level, worldPosition, 1, 1, true); + if (animationTicks == (animationInward ? 1 : 5)) + level.playLocalSound(worldPosition, SoundEvents.IRON_TRAPDOOR_CLOSE, SoundSource.BLOCKS, 0.25f, 0.75f, + true); + } + + animationTicks--; + + if (animationTicks == 0 && !level.isClientSide()) { + wakeTheFrogs(); + setChanged(); + } + } + + public void triggerStockCheck() { + getAvailableItems(); + } + + public InventorySummary getAvailableItems() { + return getAvailableItems(false); + } + + public InventorySummary getAvailableItems(boolean scanInputSlots) { + if (availableItems != null && invVersionTracker.stillWaiting(targetInventory.getInventory())) + return availableItems; + + InventorySummary availableItems = new InventorySummary(); + + IItemHandler targetInv = targetInventory.getInventory(); + if (targetInv == null || targetInv instanceof PackagerItemHandler) { + this.availableItems = availableItems; + return availableItems; + } + + if (targetInv instanceof BottomlessItemHandler bih) { + availableItems.add(bih.getStackInSlot(0), BigItemStack.INF); + this.availableItems = availableItems; + return availableItems; + } + + for (int slot = 0; slot < targetInv.getSlots(); slot++) { + int slotLimit = targetInv.getSlotLimit(slot); + availableItems.add(scanInputSlots ? targetInv.getStackInSlot(slot) : targetInv.extractItem(slot, slotLimit, true)); + } + + invVersionTracker.awaitNewVersion(targetInventory.getInventory()); + submitNewArrivals(this.availableItems, availableItems); + this.availableItems = availableItems; + return availableItems; + } + + private void submitNewArrivals(InventorySummary before, InventorySummary after) { + if (before == null || after.isEmpty()) + return; + + Set promiseQueues = new HashSet<>(); + + for (Direction d : Iterate.directions) { + if (!level.isLoaded(worldPosition.relative(d))) + continue; + + BlockState adjacentState = level.getBlockState(worldPosition.relative(d)); + if (AllBlocks.FACTORY_GAUGE.has(adjacentState)) { + if (FactoryPanelBlock.connectedDirection(adjacentState) != d) + continue; + if (!(level.getBlockEntity(worldPosition.relative(d)) instanceof FactoryPanelBlockEntity fpbe)) + continue; + if (!fpbe.restocker) + continue; + for (FactoryPanelBehaviour behaviour : fpbe.panels.values()) { + if (!behaviour.isActive()) + continue; + promiseQueues.add(behaviour.restockerPromises); + } + } + + if (AllBlocks.STOCK_LINK.has(adjacentState)) { + if (PackagerLinkBlock.getConnectedDirection(adjacentState) != d) + continue; + if (!(level.getBlockEntity(worldPosition.relative(d)) instanceof PackagerLinkBlockEntity plbe)) + continue; + UUID freqId = plbe.behaviour.freqId; + if (!Create.LOGISTICS.hasQueuedPromises(freqId)) + continue; + promiseQueues.add(Create.LOGISTICS.getQueuedPromises(freqId)); + } + } + + if (promiseQueues.isEmpty()) + return; + + for (BigItemStack entry : after.getStacks()) + before.add(entry.stack, -entry.count); + for (RequestPromiseQueue queue : promiseQueues) + for (BigItemStack entry : before.getStacks()) + if (entry.count < 0) + queue.itemEnteredSystem(entry.stack, -entry.count); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide()) + return; + recheckIfLinksPresent(); + if (!redstonePowered) + return; + redstonePowered = getBlockState().getOptionalValue(PackagerBlock.POWERED) + .orElse(false); + if (!redstoneModeActive()) + return; + updateSignAddress(); + attemptToSend(null); + } + + public void recheckIfLinksPresent() { + if (level.isClientSide()) + return; + BlockState blockState = getBlockState(); + if (!blockState.hasProperty(PackagerBlock.LINKED)) + return; + boolean shouldBeLinked = getLinkPos() != null; + boolean isLinked = blockState.getValue(PackagerBlock.LINKED); + if (shouldBeLinked == isLinked) + return; + level.setBlockAndUpdate(worldPosition, blockState.cycle(PackagerBlock.LINKED)); + } + + public boolean redstoneModeActive() { + return !getBlockState().getOptionalValue(PackagerBlock.LINKED) + .orElse(false); + } + + private BlockPos getLinkPos() { + for (Direction d : Iterate.directions) { + BlockState adjacentState = level.getBlockState(worldPosition.relative(d)); + if (!AllBlocks.STOCK_LINK.has(adjacentState)) + continue; + if (PackagerLinkBlock.getConnectedDirection(adjacentState) != d) + continue; + return worldPosition.relative(d); + } + return null; + } + + public void flashLink() { + for (Direction d : Iterate.directions) { + BlockState adjacentState = level.getBlockState(worldPosition.relative(d)); + if (!AllBlocks.STOCK_LINK.has(adjacentState)) + continue; + if (PackagerLinkBlock.getConnectedDirection(adjacentState) != d) + continue; + WiFiEffectPacket.send(level, worldPosition.relative(d)); + return; + } + } + + public boolean isTooBusyFor(RequestType type) { + int queue = queuedExitingPackages.size(); + return queue >= switch (type) { + case PLAYER -> 50; + case REDSTONE -> 20; + case RESTOCK -> 10; + }; + } + + public void activate() { + redstonePowered = true; + setChanged(); + + recheckIfLinksPresent(); + if (!redstoneModeActive()) + return; + + updateSignAddress(); + attemptToSend(null); + + // dont send multiple packages when a button signal length is received + buttonCooldown = 40; + } + + public boolean unwrapBox(ItemStack box, boolean simulate) { + if (animationTicks > 0) + return false; + + ItemStackHandler contents = PackageItem.getContents(box); + PackageOrder orderContext = PackageItem.getOrderContext(box); + IItemHandler targetInv = targetInventory.getInventory(); + BlockEntity targetBE = + level.getBlockEntity(worldPosition.relative(getBlockState().getOptionalValue(PackagerBlock.FACING) + .orElse(Direction.UP) + .getOpposite())); + + if (targetInv == null) + return false; + + boolean targetIsCreativeCrate = targetInv instanceof BottomlessItemHandler; + boolean targetIsCrafter = targetBE instanceof MechanicalCrafterBlockEntity; + + if (targetBE instanceof BasinBlockEntity basin) + basin.inputInventory.packagerMode = true; + + for (int slot = 0; slot < targetInv.getSlots(); slot++) { + ItemStack itemInSlot = targetInv.getStackInSlot(slot); + if (!simulate) + itemInSlot = itemInSlot.copy(); + + int itemsAddedToSlot = 0; + + for (int boxSlot = 0; boxSlot < contents.getSlots(); boxSlot++) { + ItemStack toInsert = contents.getStackInSlot(boxSlot); + if (toInsert.isEmpty()) + continue; + + // Follow crafting arrangement + if (targetIsCrafter && orderContext != null && orderContext.stacks() + .size() > slot) { + BigItemStack targetStack = orderContext.stacks() + .get(slot); + if (targetStack.stack.isEmpty()) + break; + if (!ItemHandlerHelper.canItemStacksStack(toInsert, targetStack.stack)) + continue; + } + + if (targetInv.insertItem(slot, toInsert, true) + .getCount() == toInsert.getCount()) + continue; + + if (itemInSlot.isEmpty()) { + int maxStackSize = targetInv.getSlotLimit(slot); + if (maxStackSize < toInsert.getCount()) { + toInsert.shrink(maxStackSize); + toInsert = ItemHandlerHelper.copyStackWithSize(toInsert, maxStackSize); + } else + contents.setStackInSlot(boxSlot, ItemStack.EMPTY); + + itemInSlot = toInsert; + if (!simulate) + itemInSlot = itemInSlot.copy(); + + targetInv.insertItem(slot, toInsert, simulate); + continue; + } + + if (!ItemHandlerHelper.canItemStacksStack(toInsert, itemInSlot)) + continue; + + int insertedAmount = toInsert.getCount() - targetInv.insertItem(slot, toInsert, simulate) + .getCount(); + int slotLimit = (int) ((targetInv.getStackInSlot(slot) + .isEmpty() ? itemInSlot.getMaxStackSize() / 64f : 1) * targetInv.getSlotLimit(slot)); + int insertableAmountWithPreviousItems = + Math.min(toInsert.getCount(), slotLimit - itemInSlot.getCount() - itemsAddedToSlot); + + int added = Math.min(insertedAmount, Math.max(0, insertableAmountWithPreviousItems)); + itemsAddedToSlot += added; + + contents.setStackInSlot(boxSlot, + ItemHandlerHelper.copyStackWithSize(toInsert, toInsert.getCount() - added)); + } + } + + if (targetBE instanceof BasinBlockEntity basin) + basin.inputInventory.packagerMode = false; + + if (!targetIsCreativeCrate) + for (int boxSlot = 0; boxSlot < contents.getSlots(); boxSlot++) + if (!contents.getStackInSlot(boxSlot) + .isEmpty()) + return false; + + if (simulate) + return true; + + if (targetBE instanceof MechanicalCrafterBlockEntity mcbe) + mcbe.checkCompletedRecipe(true); + + previouslyUnwrapped = box; + animationInward = true; + animationTicks = CYCLE; + notifyUpdate(); + return true; + } + + public void attemptToSend(List queuedRequests) { + if (queuedRequests == null && (!heldBox.isEmpty() || animationTicks != 0 || buttonCooldown > 0)) + return; + + IItemHandler targetInv = targetInventory.getInventory(); + if (targetInv == null || targetInv instanceof PackagerItemHandler) + return; + + boolean anyItemPresent = false; + ItemStackHandler extractedItems = new ItemStackHandler(PackageItem.SLOTS); + ItemStack extractedPackageItem = ItemStack.EMPTY; + PackagingRequest nextRequest = null; + String fixedAddress = null; + int fixedOrderId = 0; + + // Data written to packages for defrags + int linkIndexInOrder = 0; + boolean finalLinkInOrder = false; + int packageIndexAtLink = 0; + boolean finalPackageAtLink = false; + PackageOrder orderContext = null; + boolean requestQueue = queuedRequests != null; + + if (requestQueue && !queuedRequests.isEmpty()) { + nextRequest = queuedRequests.get(0); + fixedAddress = nextRequest.address(); + fixedOrderId = nextRequest.orderId(); + linkIndexInOrder = nextRequest.linkIndex(); + finalLinkInOrder = nextRequest.finalLink() + .booleanValue(); + packageIndexAtLink = nextRequest.packageCounter() + .getAndIncrement(); + orderContext = nextRequest.context(); + } + + Outer: for (int i = 0; i < PackageItem.SLOTS; i++) { + boolean continuePacking = true; + + while (continuePacking) { + continuePacking = false; + + for (int slot = 0; slot < targetInv.getSlots(); slot++) { + int initialCount = requestQueue ? Math.min(64, nextRequest.getCount()) : 64; + ItemStack extracted = targetInv.extractItem(slot, initialCount, true); + if (extracted.isEmpty()) + continue; + if (requestQueue && !ItemHandlerHelper.canItemStacksStack(extracted, nextRequest.item())) + continue; + + boolean bulky = !extracted.getItem() + .canFitInsideContainerItems(); + if (bulky && anyItemPresent) + continue; + + anyItemPresent = true; + int leftovers = ItemHandlerHelper.insertItemStacked(extractedItems, extracted.copy(), false) + .getCount(); + int transferred = extracted.getCount() - leftovers; + targetInv.extractItem(slot, transferred, false); + + if (extracted.getItem() instanceof PackageItem) + extractedPackageItem = extracted; + + if (!requestQueue) { + if (bulky) + break Outer; + continue; + } + + nextRequest.subtract(transferred); + + if (!nextRequest.isEmpty()) { + if (bulky) + break Outer; + continue; + } + + finalPackageAtLink = true; + queuedRequests.remove(0); + if (queuedRequests.isEmpty()) + break Outer; + int previousCount = nextRequest.packageCounter() + .intValue(); + nextRequest = queuedRequests.get(0); + if (!fixedAddress.equals(nextRequest.address())) + break Outer; + if (fixedOrderId != nextRequest.orderId()) + break Outer; + + nextRequest.packageCounter() + .setValue(previousCount); + finalPackageAtLink = false; + continuePacking = true; + if (nextRequest.context() != null) + orderContext = nextRequest.context(); + + if (bulky) + break Outer; + break; + } + } + } + + if (!anyItemPresent) { + if (nextRequest != null) + queuedRequests.remove(0); + return; + } + + ItemStack createdBox = + extractedPackageItem.isEmpty() ? PackageItem.containing(extractedItems) : extractedPackageItem.copy(); + PackageItem.clearAddress(createdBox); + + if (fixedAddress != null) + PackageItem.addAddress(createdBox, fixedAddress); + if (requestQueue) + PackageItem.setOrder(createdBox, fixedOrderId, linkIndexInOrder, finalLinkInOrder, packageIndexAtLink, + finalPackageAtLink, orderContext); + if (!requestQueue && !signBasedAddress.isBlank()) + PackageItem.addAddress(createdBox, signBasedAddress); + + BlockPos linkPos = getLinkPos(); + if (extractedPackageItem.isEmpty() && linkPos != null + && level.getBlockEntity(linkPos) instanceof PackagerLinkBlockEntity plbe) + plbe.behaviour.deductFromAccurateSummary(extractedItems); + + if (!heldBox.isEmpty() || animationTicks != 0) { + queuedExitingPackages.add(createdBox); + return; + } + + heldBox = createdBox; + animationInward = false; + animationTicks = CYCLE; + + advancements.awardPlayer(AllAdvancements.PACKAGER); + triggerStockCheck(); + notifyUpdate(); + } + + protected void updateSignAddress() { + signBasedAddress = ""; + for (Direction side : Iterate.directions) { + String address = getSign(side); + if (address == null || address.isBlank()) + continue; + signBasedAddress = address; + } + } + + protected String getSign(Direction side) { + BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(side)); + if (!(blockEntity instanceof SignBlockEntity sign)) + return null; + for (boolean front : Iterate.trueAndFalse) { + SignText text = sign.getText(front); + for (Component component : text.getMessages(false)) { + String address = component.getString(); + if (!address.isBlank()) + return address; + } + } + return null; + } + + protected void wakeTheFrogs() { + if (level.getBlockEntity(worldPosition.relative(Direction.UP)) instanceof FrogportBlockEntity port) + port.tryPullingFromOwnAndAdjacentInventories(); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + redstonePowered = compound.getBoolean("Active"); + animationInward = compound.getBoolean("AnimationInward"); + animationTicks = compound.getInt("AnimationTicks"); + signBasedAddress = compound.getString("SignAddress"); + heldBox = ItemStack.of(compound.getCompound("HeldBox")); + previouslyUnwrapped = ItemStack.of(compound.getCompound("InsertedBox")); + if (clientPacket) + return; + queuedExitingPackages = NBTHelper.readItemList(compound.getList("QueuedPackages", Tag.TAG_COMPOUND)); + if (compound.contains("LastSummary")) + availableItems = InventorySummary.read(compound.getCompound("LastSummary")); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putBoolean("Active", redstonePowered); + compound.putBoolean("AnimationInward", animationInward); + compound.putInt("AnimationTicks", animationTicks); + compound.putString("SignAddress", signBasedAddress); + compound.put("HeldBox", heldBox.serializeNBT()); + compound.put("InsertedBox", previouslyUnwrapped.serializeNBT()); + if (clientPacket) + return; + compound.put("QueuedPackages", NBTHelper.writeItemList(queuedExitingPackages)); + if (availableItems != null) + compound.put("LastSummary", availableItems.write()); + } + + @Override + public void invalidate() { + super.invalidate(); + invProvider.invalidate(); + } + + @Override + public void destroy() { + super.destroy(); + ItemHelper.dropContents(level, worldPosition, inventory); + queuedExitingPackages.forEach(stack -> Containers.dropItemStack(level, worldPosition.getX(), + worldPosition.getY(), worldPosition.getZ(), stack)); + queuedExitingPackages.clear(); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == ForgeCapabilities.ITEM_HANDLER) + return invProvider.cast(); + return super.getCapability(cap, side); + } + + public float getTrayOffset(float partialTicks) { + float tickCycle = animationInward ? animationTicks - partialTicks : animationTicks - 5 - partialTicks; + float progress = Mth.clamp(tickCycle / (CYCLE - 5) * 2 - 1, -1, 1); + progress = 1 - progress * progress; + return progress * progress; + } + + public ItemStack getRenderedBox() { + if (animationInward) + return animationTicks <= CYCLE / 2 ? ItemStack.EMPTY : previouslyUnwrapped; + return animationTicks >= CYCLE / 2 ? ItemStack.EMPTY : heldBox; + } + + public boolean isTargetingSameInventory(IItemHandler inventory) { + IItemHandler myInventory = targetInventory.getInventory(); + if (myInventory == null || inventory == null) + return false; + + if (myInventory == inventory) + return true; + + // If a contained ItemStack instance is the same, we can be pretty sure these + // inventories are the same (works for compound inventories) + for (int i = 0; i < inventory.getSlots(); i++) { + ItemStack stackInSlot = inventory.getStackInSlot(i); + if (stackInSlot.isEmpty()) + continue; + for (int j = 0; j < myInventory.getSlots(); j++) + if (stackInSlot == myInventory.getStackInSlot(j)) + return true; + break; + } + + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackagerGenerator.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerGenerator.java new file mode 100644 index 0000000000..bcfddd8d0f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerGenerator.java @@ -0,0 +1,35 @@ +package com.simibubi.create.content.logistics.packager; + +import com.simibubi.create.foundation.data.AssetLookup; +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.generators.ModelFile; + +public class PackagerGenerator extends SpecialBlockStateGen { + + @Override + protected int getXRotation(BlockState state) { + return 0; + } + + @Override + protected int getYRotation(BlockState state) { + return horizontalAngle(state.getValue(PackagerBlock.FACING)); + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + String suffix = state.getOptionalValue(PackagerBlock.LINKED) + .orElse(false) ? "linked" : state.getValue(PackagerBlock.POWERED) ? "powered" : ""; + return state.getValue(PackagerBlock.FACING) + .getAxis() == Axis.Y ? AssetLookup.partialBaseModel(ctx, prov, "vertical", suffix) + : AssetLookup.partialBaseModel(ctx, prov, suffix); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackagerItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerItemHandler.java new file mode 100644 index 0000000000..6b487c8fd8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerItemHandler.java @@ -0,0 +1,70 @@ +package com.simibubi.create.content.logistics.packager; + +import com.simibubi.create.content.logistics.box.PackageItem; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; + +public class PackagerItemHandler implements IItemHandlerModifiable { + + private PackagerBlockEntity blockEntity; + + public PackagerItemHandler(PackagerBlockEntity blockEntity) { + this.blockEntity = blockEntity; + } + + @Override + public int getSlots() { + return 1; + } + + @Override + public ItemStack getStackInSlot(int slot) { + return blockEntity.heldBox; + } + + @Override + public void setStackInSlot(int slot, ItemStack stack) { + if (slot != 0) + return; + blockEntity.heldBox = stack; + blockEntity.notifyUpdate(); + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (!blockEntity.heldBox.isEmpty() || !blockEntity.queuedExitingPackages.isEmpty()) + return stack; + if (!isItemValid(slot, stack)) + return stack; + if (!blockEntity.unwrapBox(stack, true)) + return stack; + if (!simulate) { + blockEntity.unwrapBox(stack, false); + blockEntity.triggerStockCheck(); + } + return ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - 1); + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (blockEntity.animationTicks != 0) + return ItemStack.EMPTY; + ItemStack box = blockEntity.heldBox; + if (!simulate) + setStackInSlot(slot, ItemStack.EMPTY); + return box; + } + + @Override + public int getSlotLimit(int slot) { + return 1; + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return PackageItem.isPackage(stack); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackagerRenderer.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerRenderer.java new file mode 100644 index 0000000000..7d3e9dc935 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerRenderer.java @@ -0,0 +1,91 @@ +package com.simibubi.create.content.logistics.packager; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; + +import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PackagerRenderer extends SmartBlockEntityRenderer { + + public PackagerRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(PackagerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + ItemStack renderedBox = be.getRenderedBox(); + float trayOffset = be.getTrayOffset(partialTicks); + BlockState blockState = be.getBlockState(); + Direction facing = blockState.getValue(PackagerBlock.FACING) + .getOpposite(); + + if (!VisualizationManager.supportsVisualization(be.getLevel())) { + var hatchModel = getHatchModel(be); + + SuperByteBuffer sbb = CachedBuffers.partial(hatchModel, blockState); + sbb.translate(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(.49999f)) + .rotateYCenteredDegrees(AngleHelper.horizontalAngle(facing)) + .rotateXCenteredDegrees(AngleHelper.verticalAngle(facing)) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + + sbb = CachedBuffers.partial(getTrayModel(blockState), blockState); + sbb.translate(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(trayOffset)) + .rotateYCenteredDegrees(facing.toYRot()) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + } + + if (!renderedBox.isEmpty()) { + ms.pushPose(); + var msr = TransformStack.of(ms); + msr.translate(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(trayOffset)) + .translate(.5f, .5f, .5f) + .rotateYDegrees(facing.toYRot()) + .translate(0, 2 / 16f, 0) + .scale(1.49f, 1.49f, 1.49f); + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(null, renderedBox, ItemDisplayContext.FIXED, false, ms, buffer, be.getLevel(), light, + overlay, 0); + ms.popPose(); + } + } + + public static PartialModel getTrayModel(BlockState blockState) { + return AllBlocks.PACKAGER.has(blockState) ? AllPartialModels.PACKAGER_TRAY_REGULAR + : AllPartialModels.PACKAGER_TRAY_DEFRAG; + } + + public static PartialModel getHatchModel(PackagerBlockEntity be) { + return isHatchOpen(be) ? AllPartialModels.PACKAGER_HATCH_OPEN : AllPartialModels.PACKAGER_HATCH_CLOSED; + } + + public static boolean isHatchOpen(PackagerBlockEntity be) { + return be.animationTicks > (be.animationInward ? 1 : 5) + && be.animationTicks < PackagerBlockEntity.CYCLE - (be.animationInward ? 5 : 1); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackagerVisual.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerVisual.java new file mode 100644 index 0000000000..e7e909d389 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackagerVisual.java @@ -0,0 +1,102 @@ +package com.simibubi.create.content.logistics.packager; + +import java.util.function.Consumer; + +import org.jetbrains.annotations.Nullable; + +import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.instance.InstanceTypes; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import dev.engine_room.flywheel.lib.model.Models; +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; +import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.Direction; +import net.minecraft.world.phys.Vec3; + +public class PackagerVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { + public final TransformedInstance hatch; + public final TransformedInstance tray; + + public float lastTrayOffset = Float.NaN; + public PartialModel lastHatchPartial; + + + public PackagerVisual(VisualizationContext ctx, T blockEntity, float partialTick) { + super(ctx, blockEntity, partialTick); + + lastHatchPartial = PackagerRenderer.getHatchModel(blockEntity); + hatch = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(lastHatchPartial)) + .createInstance(); + + tray = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(PackagerRenderer.getTrayModel(blockState))) + .createInstance(); + + Direction facing = blockState.getValue(PackagerBlock.FACING) + .getOpposite(); + + var lowerCorner = Vec3.atLowerCornerOf(facing.getNormal()); + hatch.setIdentityTransform() + .translate(getVisualPosition()) + .translate(lowerCorner + .scale(.49999f)) + .rotateYCenteredDegrees(AngleHelper.horizontalAngle(facing)) + .rotateXCenteredDegrees(AngleHelper.verticalAngle(facing)) + .setChanged(); + + // TODO: I think we need proper ItemVisuals to handle rendering the boxes in here + + animate(partialTick); + } + + @Override + public void beginFrame(Context ctx) { + animate(ctx.partialTick()); + } + + public void animate(float partialTick) { + var hatchPartial = PackagerRenderer.getHatchModel(blockEntity); + + if (hatchPartial != this.lastHatchPartial) { + instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(hatchPartial)) + .stealInstance(hatch); + + this.lastHatchPartial = hatchPartial; + } + + float trayOffset = blockEntity.getTrayOffset(partialTick); + + if (trayOffset != lastTrayOffset) { + Direction facing = blockState.getValue(PackagerBlock.FACING) + .getOpposite(); + + var lowerCorner = Vec3.atLowerCornerOf(facing.getNormal()); + + tray.setIdentityTransform() + .translate(getVisualPosition()) + .translate(lowerCorner.scale(trayOffset)) + .rotateYCenteredDegrees(facing.toYRot()) + .setChanged(); + + lastTrayOffset = trayOffset; + } + } + + @Override + public void updateLight(float partialTick) { + relight(hatch, tray); + } + + @Override + protected void _delete() { + hatch.delete(); + tray.delete(); + } + + @Override + public void collectCrumblingInstances(Consumer<@Nullable Instance> consumer) { + + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/PackagingRequest.java b/src/main/java/com/simibubi/create/content/logistics/packager/PackagingRequest.java new file mode 100644 index 0000000000..adb84d4691 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/PackagingRequest.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.logistics.packager; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.mutable.MutableBoolean; +import org.apache.commons.lang3.mutable.MutableInt; + +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; + +public record PackagingRequest(ItemStack item, MutableInt count, String address, int linkIndex, + MutableBoolean finalLink, MutableInt packageCounter, int orderId, @Nullable PackageOrder context) { + + public static PackagingRequest create(ItemStack item, int count, String address, int linkIndex, + MutableBoolean finalLink, int packageCount, int orderId, @Nullable PackageOrder context) { + return new PackagingRequest(item, new MutableInt(count), address, linkIndex, finalLink, + new MutableInt(packageCount), orderId, context); + } + + public int getCount() { + return count.intValue(); + } + + public void subtract(int toSubtract) { + count.setValue(getCount() - toSubtract); + } + + public boolean isEmpty() { + return getCount() == 0; + } + + public static PackagingRequest fromNBT(CompoundTag tag) { + ItemStack item = ItemStack.of(tag.getCompound("Item")); + int count = tag.getInt("Count"); + String address = tag.getString("Address"); + int linkIndex = tag.getInt("LinkIndex"); + MutableBoolean finalLink = new MutableBoolean(tag.getBoolean("FinalLink")); + int packageCount = tag.getInt("PackageCount"); + int orderId = tag.getInt("OrderId"); + PackageOrder orderContext = + tag.contains("OrderContext") ? PackageOrder.read(tag.getCompound("OrderContext")) : null; + return create(item, count, address, linkIndex, finalLink, packageCount, orderId, orderContext); + } + + public CompoundTag toNBT() { + CompoundTag tag = new CompoundTag(); + tag.putInt("Count", count.intValue()); + tag.put("Item", item.serializeNBT()); + tag.putString("Address", address); + tag.putInt("LinkIndex", linkIndex); + tag.putBoolean("FinalLink", finalLink.booleanValue()); + tag.putInt("PackageCount", packageCounter.intValue()); + tag.putInt("OrderId", orderId); + return tag; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/repackager/RepackagerBlock.java b/src/main/java/com/simibubi/create/content/logistics/packager/repackager/RepackagerBlock.java new file mode 100644 index 0000000000..c54c231aea --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/repackager/RepackagerBlock.java @@ -0,0 +1,28 @@ +package com.simibubi.create.content.logistics.packager.repackager; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.logistics.packager.PackagerBlock; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; + +public class RepackagerBlock extends PackagerBlock { + + public RepackagerBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.REPACKAGER.get(); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + builder.add(FACING, POWERED); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packager/repackager/RepackagerBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/packager/repackager/RepackagerBlockEntity.java new file mode 100644 index 0000000000..d7fd31a925 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packager/repackager/RepackagerBlockEntity.java @@ -0,0 +1,135 @@ +package com.simibubi.create.content.logistics.packager.repackager; + +import java.util.List; + +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.crate.BottomlessItemHandler; +import com.simibubi.create.content.logistics.packager.PackageDefragmenter; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; +import com.simibubi.create.content.logistics.packager.PackagerItemHandler; +import com.simibubi.create.content.logistics.packager.PackagingRequest; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class RepackagerBlockEntity extends PackagerBlockEntity { + + public PackageDefragmenter defragmenter; + + public RepackagerBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + defragmenter = new PackageDefragmenter(); + } + + public boolean unwrapBox(ItemStack box, boolean simulate) { + if (animationTicks > 0) + return false; + + IItemHandler targetInv = targetInventory.getInventory(); + if (targetInv == null || targetInv instanceof PackagerItemHandler) + return false; + + boolean targetIsCreativeCrate = targetInv instanceof BottomlessItemHandler; + boolean anySpace = false; + + for (int slot = 0; slot < targetInv.getSlots(); slot++) { + ItemStack remainder = targetInv.insertItem(slot, box, simulate); + if (!remainder.isEmpty()) + continue; + anySpace = true; + break; + } + + if (!targetIsCreativeCrate && !anySpace) + return false; + if (simulate) + return true; + + previouslyUnwrapped = box; + animationInward = true; + animationTicks = CYCLE; + notifyUpdate(); + return true; + } + + @Override + public void recheckIfLinksPresent() {} + + @Override + public boolean redstoneModeActive() { + return true; + } + + public void attemptToSend(List queuedRequests) { + if (queuedRequests == null && (!heldBox.isEmpty() || animationTicks != 0)) + return; + + IItemHandler targetInv = targetInventory.getInventory(); + if (targetInv == null || targetInv instanceof PackagerItemHandler) + return; + + attemptToDefrag(targetInv); + if (heldBox.isEmpty()) + return; + + updateSignAddress(); + if (!signBasedAddress.isBlank()) + PackageItem.addAddress(heldBox, signBasedAddress); + } + + protected void attemptToDefrag(IItemHandler targetInv) { + defragmenter.clear(); + int completedOrderId = -1; + + for (int slot = 0; slot < targetInv.getSlots(); slot++) { + ItemStack extracted = targetInv.extractItem(slot, 1, true); + if (extracted.isEmpty() || !PackageItem.isPackage(extracted)) + continue; + + if (!defragmenter.isFragmented(extracted)) { + targetInv.extractItem(slot, 1, false); + heldBox = extracted.copy(); + animationInward = false; + animationTicks = CYCLE; + notifyUpdate(); + return; + } + + completedOrderId = defragmenter.addPackageFragment(extracted); + if (completedOrderId != -1) + break; + } + + if (completedOrderId == -1) + return; + + List boxesToExport = defragmenter.repack(completedOrderId); + + for (int slot = 0; slot < targetInv.getSlots(); slot++) { + ItemStack extracted = targetInv.extractItem(slot, 1, true); + if (extracted.isEmpty() || !PackageItem.isPackage(extracted)) + continue; + if (PackageItem.getOrderId(extracted) != completedOrderId) + continue; + targetInv.extractItem(slot, 1, false); + } + + if (boxesToExport.isEmpty()) + return; + + heldBox = boxesToExport.get(0) + .copy(); + animationInward = false; + animationTicks = CYCLE; + + for (int i = 1; i < boxesToExport.size(); i++) + ItemHandlerHelper.insertItem(targetInv, boxesToExport.get(i), false); + + notifyUpdate(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/GlobalLogisticsManager.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/GlobalLogisticsManager.java new file mode 100644 index 0000000000..016f87f398 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/GlobalLogisticsManager.java @@ -0,0 +1,117 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import net.minecraft.core.GlobalPos; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; + +public class GlobalLogisticsManager { + + public Map logisticsNetworks; + + private LogisticsNetworkSavedData savedData; + + public GlobalLogisticsManager() { + logisticsNetworks = new HashMap<>(); + } + + public void levelLoaded(LevelAccessor level) { + MinecraftServer server = level.getServer(); + if (server == null || server.overworld() != level) + return; + logisticsNetworks = new HashMap<>(); + savedData = null; + loadLogisticsData(server); + } + + public boolean mayInteract(UUID networkId, Player player) { + LogisticsNetwork network = logisticsNetworks.get(networkId); + return network == null || network.owner == null || !network.locked || network.owner.equals(player.getUUID()); + } + + public boolean mayAdministrate(UUID networkId, Player player) { + LogisticsNetwork network = logisticsNetworks.get(networkId); + return network == null || network.owner == null || network.owner.equals(player.getUUID()); + } + + public boolean isLockable(UUID networkId) { + LogisticsNetwork network = logisticsNetworks.get(networkId); + return network != null; + } + + public boolean isLocked(UUID networkId) { + LogisticsNetwork network = logisticsNetworks.get(networkId); + return network != null && network.locked; + } + + public void linkAdded(UUID networkId, GlobalPos pos, UUID ownedBy) { + LogisticsNetwork network = logisticsNetworks.computeIfAbsent(networkId, $ -> new LogisticsNetwork(networkId)); + network.totalLinks.add(pos); + if (ownedBy != null && network.owner == null) + network.owner = ownedBy; + markDirty(); + } + + public void linkLoaded(UUID networkId, GlobalPos pos) { + logisticsNetworks.computeIfAbsent(networkId, $ -> new LogisticsNetwork(networkId)).loadedLinks.add(pos); + } + + public void linkRemoved(UUID networkId, GlobalPos pos) { + LogisticsNetwork logisticsNetwork = logisticsNetworks.get(networkId); + if (logisticsNetwork == null) + return; + logisticsNetwork.totalLinks.remove(pos); + logisticsNetwork.loadedLinks.remove(pos); + if (logisticsNetwork.totalLinks.size() <= 0) + logisticsNetworks.remove(networkId); + markDirty(); + } + + public void linkInvalidated(UUID networkId, GlobalPos pos) { + LogisticsNetwork logisticsNetwork = logisticsNetworks.get(networkId); + if (logisticsNetwork == null) + return; + logisticsNetwork.loadedLinks.remove(pos); + } + + public int getUnloadedLinkCount(UUID networkId) { + LogisticsNetwork logisticsNetwork = logisticsNetworks.get(networkId); + if (logisticsNetwork == null) + return 0; + return logisticsNetwork.totalLinks.size() - logisticsNetwork.loadedLinks.size(); + } + + public RequestPromiseQueue getQueuedPromises(UUID networkId) { + return !logisticsNetworks.containsKey(networkId) ? null : logisticsNetworks.get(networkId).panelPromises; + } + + public boolean hasQueuedPromises(UUID networkId) { + return logisticsNetworks.containsKey(networkId) && !logisticsNetworks.get(networkId).panelPromises.isEmpty(); + } + + private void loadLogisticsData(MinecraftServer server) { + if (savedData != null) + return; + savedData = LogisticsNetworkSavedData.load(server); + logisticsNetworks = savedData.getLogisticsNetworks(); + } + + public void tick(Level level) { + if (level.dimension() != Level.OVERWORLD) + return; + logisticsNetworks.forEach((id, network) -> { + network.panelPromises.tick(); + }); + } + + public void markDirty() { + if (savedData != null) + savedData.setDirty(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedBehaviour.java new file mode 100644 index 0000000000..a4d3152417 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedBehaviour.java @@ -0,0 +1,257 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.google.common.cache.Cache; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; +import com.simibubi.create.content.logistics.packager.PackagingRequest; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; +import com.simibubi.create.foundation.utility.TickBasedCache; + +import net.createmod.catnip.data.Pair; +import net.minecraft.ChatFormatting; +import net.minecraft.core.GlobalPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; + +public class LogisticallyLinkedBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + public static final AtomicInteger LINK_ID_GENERATOR = new AtomicInteger(); + public int linkId; // Runtime context, not saved to disk + + public int redstonePower; + public UUID freqId; + + private boolean addedGlobally = false; + private boolean loadedGlobally = false; + private boolean global = false; + + public static enum RequestType { + RESTOCK, REDSTONE, PLAYER + } + + private static final Cache>> LINKS = + new TickBasedCache<>(20, true); + + private static final Cache>> CLIENT_LINKS = + new TickBasedCache<>(20, true, true); + + public LogisticallyLinkedBehaviour(SmartBlockEntity be, boolean global) { + super(be); + this.global = global; + linkId = LINK_ID_GENERATOR.getAndIncrement(); + freqId = UUID.randomUUID(); + } + + public static Collection getAllPresent(UUID freq, boolean sortByPriority) { + return getAllPresent(freq, sortByPriority, false); + } + + public static Collection getAllPresent(UUID freq, boolean sortByPriority, + boolean clientSide) { + Cache> cache = + (clientSide ? CLIENT_LINKS : LINKS).getIfPresent(freq); + if (cache == null) + return Collections.emptyList(); + Stream stream = new LinkedList<>(cache.asMap() + .values()).stream() + .map(WeakReference::get) + .filter(LogisticallyLinkedBehaviour::isValidLink); + + if (sortByPriority) + stream = stream.sorted((e1, e2) -> Integer.compare(e1.redstonePower, e2.redstonePower)); + + return stream.toList(); + } + + public static void keepAlive(LogisticallyLinkedBehaviour behaviour) { + boolean onClient = behaviour.blockEntity.getLevel().isClientSide; + if (behaviour.redstonePower == 15) + return; + try { + Cache> cache = + (onClient ? CLIENT_LINKS : LINKS).get(behaviour.freqId, () -> new TickBasedCache<>(400, false)); + + if (cache == null) + return; + + WeakReference reference = + cache.get(behaviour.linkId, () -> new WeakReference<>(behaviour)); + cache.put(behaviour.linkId, reference.get() != behaviour ? new WeakReference<>(behaviour) : reference); + + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + public static void remove(LogisticallyLinkedBehaviour behaviour) { + Cache> cache = LINKS.getIfPresent(behaviour.freqId); + if (cache != null) + cache.invalidate(behaviour.linkId); + } + + // + + @Override + public void unload() { + if (loadedGlobally && global && getWorld() != null) + Create.LOGISTICS.linkInvalidated(freqId, getGlobalPos()); + super.unload(); + remove(this); + } + + @Override + public void lazyTick() { + keepAlive(this); + } + + @Override + public void initialize() { + super.initialize(); + if (getWorld().isClientSide) + return; + + if (!loadedGlobally && global) { + loadedGlobally = true; + Create.LOGISTICS.linkLoaded(freqId, getGlobalPos()); + } + + if (!addedGlobally && global) { + addedGlobally = true; + blockEntity.setChanged(); + if (blockEntity instanceof PackagerLinkBlockEntity plbe) + Create.LOGISTICS.linkAdded(freqId, getGlobalPos(), plbe.placedBy); + } + + } + + private GlobalPos getGlobalPos() { + return GlobalPos.of(getWorld().dimension(), getPos()); + } + + @Override + public void destroy() { + super.destroy(); + if (addedGlobally && global && getWorld() != null) + Create.LOGISTICS.linkRemoved(freqId, getGlobalPos()); + } + + public void redstonePowerChanged(int power) { + if (power == redstonePower) + return; + redstonePower = power; + blockEntity.setChanged(); + + if (power == 15) + remove(this); + else + keepAlive(this); + } + + public Pair processRequest(ItemStack stack, int amount, String address, + int linkIndex, MutableBoolean finalLink, int orderId, @Nullable PackageOrder orderContext, + @Nullable IItemHandler ignoredHandler) { + + if (blockEntity instanceof PackagerLinkBlockEntity plbe) + return plbe.processRequest(stack, amount, address, linkIndex, finalLink, orderId, orderContext, + ignoredHandler); + + return null; + } + + public InventorySummary getSummary(@Nullable IItemHandler ignoredHandler) { + if (blockEntity instanceof PackagerLinkBlockEntity plbe) + return plbe.fetchSummaryFromPackager(ignoredHandler); + return InventorySummary.EMPTY; + } + + public void deductFromAccurateSummary(ItemStackHandler packageContents) { + InventorySummary summary = LogisticsManager.ACCURATE_SUMMARIES.getIfPresent(freqId); + if (summary == null) + return; + for (int i = 0; i < packageContents.getSlots(); i++) { + ItemStack orderedStack = packageContents.getStackInSlot(i); + if (orderedStack.isEmpty()) + continue; + summary.add(orderedStack, -Math.min(summary.getCountOf(orderedStack), orderedStack.getCount())); + } + } + + // + + public boolean mayInteract(Player player) { + return Create.LOGISTICS.mayInteract(freqId, player); + } + + public boolean mayInteractMessage(Player player) { + boolean mayInteract = Create.LOGISTICS.mayInteract(freqId, player); + if (!mayInteract) + player.displayClientMessage(CreateLang.translate("logistically_linked.protected") + .style(ChatFormatting.RED) + .component(), true); + return mayInteract; + } + + public boolean mayAdministrate(Player player) { + return Create.LOGISTICS.mayAdministrate(freqId, player); + } + + public static boolean isValidLink(LogisticallyLinkedBehaviour link) { + return link != null && !link.blockEntity.isRemoved() && !link.blockEntity.isChunkUnloaded(); + } + + @Override + public boolean isSafeNBT() { + return true; + } + + @Override + public void writeSafe(CompoundTag tag) { + tag.putUUID("Freq", freqId); + } + + @Override + public void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.putUUID("Freq", freqId); + tag.putInt("Power", redstonePower); + tag.putBoolean("Added", addedGlobally); + } + + @Override + public void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + if (tag.hasUUID("Freq")) + freqId = tag.getUUID("Freq"); + redstonePower = tag.getInt("Power"); + addedGlobally = tag.getBoolean("Added"); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedBlockItem.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedBlockItem.java new file mode 100644 index 0000000000..0ba642bab0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedBlockItem.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; + +public class LogisticallyLinkedBlockItem extends BlockItem { + + public LogisticallyLinkedBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public boolean isFoil(ItemStack pStack) { + return isTuned(pStack); + } + + public static boolean isTuned(ItemStack pStack) { + return pStack.hasTag() && pStack.getTag() + .contains(BLOCK_ENTITY_TAG); + } + + @Nullable + public static UUID networkFromStack(ItemStack pStack) { + if (!isTuned(pStack)) + return null; + CompoundTag tag = pStack.getTag() + .getCompound(BLOCK_ENTITY_TAG); + if (!tag.hasUUID("Freq")) + return null; + return tag.getUUID("Freq"); + } + + @Override + public void appendHoverText(ItemStack pStack, Level pLevel, List pTooltip, TooltipFlag pFlag) { + super.appendHoverText(pStack, pLevel, pTooltip, pFlag); + if (!isTuned(pStack)) + return; + + CompoundTag tag = pStack.getTag() + .getCompound(BLOCK_ENTITY_TAG); + if (!tag.hasUUID("Freq")) + return; + + CreateLang.translate("logistically_linked.tooltip") + .style(ChatFormatting.GOLD) + .addTo(pTooltip); + + CreateLang.translate("logistically_linked.tooltip_clear") + .style(ChatFormatting.GRAY) + .addTo(pTooltip); + } + + @Override + public InteractionResult useOn(UseOnContext pContext) { + ItemStack stack = pContext.getItemInHand(); + BlockPos pos = pContext.getClickedPos(); + Level level = pContext.getLevel(); + Player player = pContext.getPlayer(); + + if (player == null) + return InteractionResult.FAIL; + if (player.isShiftKeyDown()) + return super.useOn(pContext); + + LogisticallyLinkedBehaviour link = BlockEntityBehaviour.get(level, pos, LogisticallyLinkedBehaviour.TYPE); + boolean tuned = isTuned(stack); + + if (link != null) { + if (level.isClientSide) + return InteractionResult.SUCCESS; + if (!link.mayInteractMessage(player)) + return InteractionResult.SUCCESS; + + assignFrequency(stack, player, link.freqId); + return InteractionResult.SUCCESS; + } + + InteractionResult useOn = super.useOn(pContext); + if (level.isClientSide || useOn == InteractionResult.FAIL) + return useOn; + + player.displayClientMessage(tuned ? CreateLang.translateDirect("logistically_linked.connected") + : CreateLang.translateDirect("logistically_linked.new_network_started"), true); + return useOn; + } + + public static void assignFrequency(ItemStack stack, Player player, UUID frequency) { + CompoundTag stackTag = stack.getOrCreateTag(); + CompoundTag teTag = new CompoundTag(); + teTag.putUUID("Freq", frequency); + stackTag.put(BLOCK_ENTITY_TAG, teTag); + + player.displayClientMessage(CreateLang.translateDirect("logistically_linked.tuned"), true); + stack.setTag(stackTag); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedClientHandler.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedClientHandler.java new file mode 100644 index 0000000000..1f8b2c8389 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticallyLinkedClientHandler.java @@ -0,0 +1,88 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.UUID; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBehaviour; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelConnectionHandler; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; + +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.outliner.Outliner; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class LogisticallyLinkedClientHandler { + + private static UUID previouslyHeldFrequency; + + public static void tick() { + previouslyHeldFrequency = null; + + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) + return; + ItemStack mainHandItem = player.getMainHandItem(); + if (!(mainHandItem.getItem() instanceof LogisticallyLinkedBlockItem) + || !LogisticallyLinkedBlockItem.isTuned(mainHandItem)) + return; + + CompoundTag tag = mainHandItem.getTag() + .getCompound(BlockItem.BLOCK_ENTITY_TAG); + if (!tag.hasUUID("Freq")) + return; + + UUID uuid = tag.getUUID("Freq"); + previouslyHeldFrequency = uuid; + + for (LogisticallyLinkedBehaviour behaviour : LogisticallyLinkedBehaviour.getAllPresent(uuid, false, true)) { + SmartBlockEntity be = behaviour.blockEntity; + VoxelShape shape = be.getBlockState() + .getShape(player.level(), be.getBlockPos()); + if (shape.isEmpty()) + continue; + if (!player.blockPosition() + .closerThan(be.getBlockPos(), 64)) + continue; + for (int i = 0; i < shape.toAabbs() + .size(); i++) { + AABB aabb = shape.toAabbs() + .get(i); + Outliner.getInstance() + .showAABB(Pair.of(behaviour, i), aabb.inflate(-1 / 128f) + .move(be.getBlockPos()), 2) + .lineWidth(1 / 32f) + .disableLineNormals() + .colored(AnimationTickHolder.getTicks() % 16 < 8 ? 0x708DAD : 0x90ADCD); + } + + } + } + + public static void tickPanel(FactoryPanelBehaviour fpb) { + if (previouslyHeldFrequency == null) + return; + if (!previouslyHeldFrequency.equals(fpb.network)) + return; + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) + return; + if (!player.blockPosition() + .closerThan(fpb.getPos(), 64)) + return; + + Outliner.getInstance() + .showAABB(fpb, FactoryPanelConnectionHandler.getBB(fpb.blockEntity.getBlockState(), fpb.getPanelPosition()) + .inflate(-1.5 / 128f)) + .lineWidth(1 / 32f) + .disableLineNormals() + .colored(AnimationTickHolder.getTicks() % 16 < 8 ? 0x708DAD : 0x90ADCD); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsManager.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsManager.java new file mode 100644 index 0000000000..153a80cfb4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsManager.java @@ -0,0 +1,164 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.google.common.cache.Cache; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; +import com.simibubi.create.content.logistics.packager.PackagingRequest; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.foundation.utility.TickBasedCache; + +import net.createmod.catnip.data.Pair; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +public class LogisticsManager { + + private static Random r = new Random(); + + public static final Cache ACCURATE_SUMMARIES = new TickBasedCache<>(1, false); + public static final Cache SUMMARIES = new TickBasedCache<>(20, false); + + public static InventorySummary getSummaryOfNetwork(UUID freqId, boolean accurate) { + try { + return (accurate ? LogisticsManager.ACCURATE_SUMMARIES : LogisticsManager.SUMMARIES).get(freqId, () -> { + InventorySummary summaryOfLinks = new InventorySummary(); + LogisticallyLinkedBehaviour.getAllPresent(freqId, false) + .forEach(link -> { + InventorySummary summary = link.getSummary(null); + if (summary != InventorySummary.EMPTY) + summaryOfLinks.contributingLinks++; + summaryOfLinks.add(summary); + }); + return summaryOfLinks; + }); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return InventorySummary.EMPTY; + } + + public static int getStockOf(UUID freqId, ItemStack stack, @Nullable IItemHandler ignoredHandler) { + int sum = 0; + for (LogisticallyLinkedBehaviour link : LogisticallyLinkedBehaviour.getAllPresent(freqId, false)) + sum += link.getSummary(ignoredHandler) + .getCountOf(stack); + return sum; + } + + public static boolean broadcastPackageRequest(UUID freqId, RequestType type, PackageOrder order, + IItemHandler ignoredHandler, String address, @Nullable PackageOrder orderContext) { + if (order.isEmpty()) + return false; + + Multimap requests = + findPackagersForRequest(freqId, order, orderContext, ignoredHandler, address); + + // Check if packagers have accumulated too many packages already + for (PackagerBlockEntity packager : requests.keySet()) + if (packager.isTooBusyFor(type)) + return false; + + // Actually perform package creation + performPackageRequests(requests); + return true; + } + + public static Multimap findPackagersForRequest(UUID freqId, + PackageOrder order, @Nullable PackageOrder customContext, @Nullable IItemHandler ignoredHandler, + String address) { + List stacks = new ArrayList<>(); + for (BigItemStack stack : order.stacks()) + if (!stack.stack.isEmpty() && stack.count > 0) + stacks.add(stack); + + Multimap requests = HashMultimap.create(); + + // Packages need to track their index and successors for successful defrag + Iterable availableLinks = LogisticallyLinkedBehaviour.getAllPresent(freqId, true); + List usedLinks = new ArrayList<>(); + MutableBoolean finalLinkTracker = new MutableBoolean(false); + + // First box needs to carry the order specifics for successful defrag + PackageOrder contextToSend = order; + if (customContext != null) + contextToSend = customContext; + + // Packages from future orders should not be merged in the packager queue + int orderId = r.nextInt(); + + for (int i = 0; i < stacks.size(); i++) { + BigItemStack entry = stacks.get(i); + int remainingCount = entry.count; + boolean finalEntry = i == stacks.size() - 1; + ItemStack requestedItem = entry.stack; + + for (LogisticallyLinkedBehaviour link : availableLinks) { + int usedIndex = usedLinks.indexOf(link); + int linkIndex = usedIndex == -1 ? usedLinks.size() : usedIndex; + MutableBoolean isFinalLink = new MutableBoolean(false); + if (linkIndex == usedLinks.size() - 1) + isFinalLink = finalLinkTracker; + + Pair request = link.processRequest(requestedItem, remainingCount, + address, linkIndex, isFinalLink, orderId, contextToSend, ignoredHandler); + if (request == null) + continue; + + requests.put(request.getFirst(), request.getSecond()); + + int processedCount = request.getSecond() + .getCount(); + if (processedCount > 0 && usedIndex == -1) { + contextToSend = null; + usedLinks.add(link); + finalLinkTracker = isFinalLink; + } + + remainingCount -= processedCount; + if (remainingCount > 0) + continue; + if (finalEntry) + finalLinkTracker.setTrue(); + break; + } + } + return requests; + } + + public static void performPackageRequests(Multimap requests) { + Map> asMap = requests.asMap(); + for (Entry> entry : asMap.entrySet()) { + ArrayList queuedRequests = new ArrayList<>(entry.getValue()); + PackagerBlockEntity packager = entry.getKey(); + + if (!queuedRequests.isEmpty()) + packager.flashLink(); + for (int i = 0; i < 100; i++) { + if (queuedRequests.isEmpty()) + break; + packager.attemptToSend(queuedRequests); + } + + packager.triggerStockCheck(); + packager.notifyUpdate(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsNetwork.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsNetwork.java new file mode 100644 index 0000000000..f37a809e84 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsNetwork.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import com.simibubi.create.Create; + +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.GlobalPos; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; + +public class LogisticsNetwork { + + public UUID id; + public RequestPromiseQueue panelPromises; + + public Set totalLinks; + public Set loadedLinks; + + public UUID owner; + public boolean locked; + + public LogisticsNetwork(UUID networkId) { + id = networkId; + panelPromises = new RequestPromiseQueue(Create.LOGISTICS::markDirty); + totalLinks = new HashSet<>(); + loadedLinks = new HashSet<>(); + owner = null; + locked = false; + } + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + tag.putUUID("Id", id); + tag.put("Promises", panelPromises.write()); + + tag.put("Links", NBTHelper.writeCompoundList(totalLinks, p -> { + CompoundTag nbt = NbtUtils.writeBlockPos(p.pos()); + if (p.dimension() != Level.OVERWORLD) + nbt.putString("Dim", p.dimension() + .location() + .toString()); + return nbt; + })); + + if (owner != null) + tag.putUUID("Owner", owner); + + tag.putBoolean("Locked", locked); + return tag; + } + + public static LogisticsNetwork read(CompoundTag tag) { + LogisticsNetwork network = new LogisticsNetwork(tag.getUUID("Id")); + network.panelPromises = RequestPromiseQueue.read(tag.getCompound("Promises"), Create.LOGISTICS::markDirty); + + NBTHelper.iterateCompoundList(tag.getList("Links", Tag.TAG_COMPOUND), nbt -> { + network.totalLinks.add(GlobalPos.of(nbt.contains("Dim") + ? ResourceKey.create(Registries.DIMENSION, new ResourceLocation(nbt.getString("Dim"))) + : Level.OVERWORLD, NbtUtils.readBlockPos(nbt))); + }); + + network.owner = tag.contains("Owner") ? tag.getUUID("Owner") : null; + network.locked = tag.getBoolean("Locked"); + + return network; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsNetworkSavedData.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsNetworkSavedData.java new file mode 100644 index 0000000000..d62b36ca49 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/LogisticsNetworkSavedData.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import com.simibubi.create.Create; + +import com.simibubi.create.foundation.utility.SavedDataUtil; + +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.saveddata.SavedData; + +import org.jetbrains.annotations.NotNull; + +public class LogisticsNetworkSavedData extends SavedData { + + private Map logisticsNetworks = new HashMap<>(); + + @Override + public CompoundTag save(CompoundTag nbt) { + GlobalLogisticsManager logistics = Create.LOGISTICS; + nbt.put("LogisticsNetworks", + NBTHelper.writeCompoundList(logistics.logisticsNetworks.values(), tg -> tg.write())); + return nbt; + } + + private static LogisticsNetworkSavedData load(CompoundTag nbt) { + LogisticsNetworkSavedData sd = new LogisticsNetworkSavedData(); + sd.logisticsNetworks = new HashMap<>(); + NBTHelper.iterateCompoundList(nbt.getList("LogisticsNetworks", Tag.TAG_COMPOUND), c -> { + LogisticsNetwork network = LogisticsNetwork.read(c); + sd.logisticsNetworks.put(network.id, network); + }); + return sd; + } + + @Override + public void save(@NotNull File file) { + SavedDataUtil.saveWithDatOld(this, file); + } + + public Map getLogisticsNetworks() { + return logisticsNetworks; + } + + private LogisticsNetworkSavedData() {} + + public static LogisticsNetworkSavedData load(MinecraftServer server) { + return server.overworld() + .getDataStorage() + .computeIfAbsent(LogisticsNetworkSavedData::load, LogisticsNetworkSavedData::new, "create_logistics"); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkBlock.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkBlock.java new file mode 100644 index 0000000000..d21b1198b9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkBlock.java @@ -0,0 +1,140 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; + +import net.createmod.catnip.data.Iterate; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class PackagerLinkBlock extends FaceAttachedHorizontalDirectionalBlock + implements IBE, ProperWaterloggedBlock, IWrenchable { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public PackagerLinkBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(POWERED, false) + .setValue(WATERLOGGED, false)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockPos pos = context.getClickedPos(); + BlockState placed = super.getStateForPlacement(context); + if (placed == null) + return null; + if (placed.getValue(FACE) == AttachFace.CEILING) + placed = placed.setValue(FACING, placed.getValue(FACING) + .getOpposite()); + return withWater(placed.setValue(POWERED, getPower(placed, context.getLevel(), pos) > 0), context); + } + + public static Direction getConnectedDirection(BlockState state) { + return FaceAttachedHorizontalDirectionalBlock.getConnectedDirection(state); + } + + @Override + public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { + return true; + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pPos); + return pState; + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + if (worldIn.isClientSide) + return; + + int power = getPower(state, worldIn, pos); + boolean powered = power > 0; + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered != powered) + worldIn.setBlock(pos, state.cycle(POWERED), 2); + withBlockEntityDo(worldIn, pos, link -> link.behaviour.redstonePowerChanged(power)); + } + + public static int getPower(BlockState state, Level worldIn, BlockPos pos) { + int power = 0; + for (Direction d : Iterate.directions) + if (d.getOpposite() != getConnectedDirection(state)) + power = Math.max(power, worldIn.getSignal(pos.relative(d), d)); + return power; + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + withBlockEntityDo(pLevel, pPos, plbe -> { + if (pPlacer instanceof Player player) { + plbe.placedBy = player.getUUID(); + plbe.notifyUpdate(); + } + }); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.STOCK_LINK.get(getConnectedDirection(pState)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED, WATERLOGGED, FACE, FACING)); + } + + @Override + public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) { + return false; + } + + @Override + public Class getBlockEntityClass() { + return PackagerLinkBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.PACKAGER_LINK.get(); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkBlockEntity.java new file mode 100644 index 0000000000..821f416aa9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkBlockEntity.java @@ -0,0 +1,160 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packager.PackagerBlockEntity; +import com.simibubi.create.content.logistics.packager.PackagingRequest; +import com.simibubi.create.content.logistics.packager.repackager.RepackagerBlockEntity; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.content.redstone.displayLink.LinkWithBulbBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.IItemHandler; + +public class PackagerLinkBlockEntity extends LinkWithBulbBlockEntity { + + public LogisticallyLinkedBehaviour behaviour; + public UUID placedBy; + + public PackagerLinkBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(10); + placedBy = null; + } + + public InventorySummary fetchSummaryFromPackager(@Nullable IItemHandler ignoredHandler) { + PackagerBlockEntity packager = getPackager(); + if (packager == null) + return InventorySummary.EMPTY; + if (packager.isTargetingSameInventory(ignoredHandler)) + return InventorySummary.EMPTY; + return packager.getAvailableItems(); + } + + public void playEffect() { + AllSoundEvents.STOCK_LINK.playAt(level, worldPosition, 0.75f, 1.25f, false); + Vec3 vec3 = Vec3.atCenterOf(worldPosition); + + BlockState state = getBlockState(); + float f = 1; + + AttachFace face = state.getOptionalValue(PackagerLinkBlock.FACE) + .orElse(AttachFace.FLOOR); + if (face != AttachFace.FLOOR) + f = -1; + if (face == AttachFace.WALL) + vec3 = vec3.add(0, 0.25, 0); + + vec3 = vec3.add(Vec3.atLowerCornerOf(state.getOptionalValue(PackagerLinkBlock.FACING) + .orElse(Direction.SOUTH) + .getNormal()) + .scale(f * 0.125)); + + pulse(); + level.addParticle(new WiFiParticle.Data(), vec3.x, vec3.y, vec3.z, 1, face == AttachFace.CEILING ? -1 : 1, 1); + } + + public Pair processRequest(ItemStack stack, int amount, String address, + int linkIndex, MutableBoolean finalLink, int orderId, @Nullable PackageOrder orderContext, + @Nullable IItemHandler ignoredHandler) { + PackagerBlockEntity packager = getPackager(); + if (packager == null) + return null; + if (packager.isTargetingSameInventory(ignoredHandler)) + return null; + + InventorySummary summary = packager.getAvailableItems(); + int availableCount = summary.getCountOf(stack); + if (availableCount == 0) + return null; + int toWithdraw = Math.min(amount, availableCount); + return Pair.of(packager, + PackagingRequest.create(stack, toWithdraw, address, linkIndex, finalLink, 0, orderId, orderContext)); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + if (placedBy != null) + tag.putUUID("PlacedBy", placedBy); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + placedBy = tag.contains("PlacedBy") ? tag.getUUID("PlacedBy") : null; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(behaviour = new LogisticallyLinkedBehaviour(this, true)); + } + + @Override + public void initialize() { + super.initialize(); + behaviour.redstonePowerChanged(PackagerLinkBlock.getPower(getBlockState(), level, worldPosition)); + PackagerBlockEntity packager = getPackager(); + if (packager != null) + packager.recheckIfLinksPresent(); + } + + @Nullable + public PackagerBlockEntity getPackager() { + BlockState blockState = getBlockState(); + if (behaviour.redstonePower == 15) + return null; + BlockPos source = worldPosition.relative(PackagerLinkBlock.getConnectedDirection(blockState) + .getOpposite()); + if (!(level.getBlockEntity(source) instanceof PackagerBlockEntity packager)) + return null; + if (packager instanceof RepackagerBlockEntity) + return null; + return packager; + } + + @Override + public Direction getBulbFacing(BlockState state) { + return PackagerLinkBlock.getConnectedDirection(state); + } + + private static final Map bulbOffsets = new HashMap<>(); + + @Override + public Vec3 getBulbOffset(BlockState state) { + return bulbOffsets.computeIfAbsent(state, s -> { + Vec3 offset = VecHelper.voxelSpace(5, 6, 11); + Vec3 wallOffset = VecHelper.voxelSpace(11, 6, 5); + AttachFace face = s.getValue(PackagerLinkBlock.FACE); + Vec3 vec = face == AttachFace.WALL ? wallOffset : offset; + float angle = AngleHelper.horizontalAngle(s.getValue(PackagerLinkBlock.FACING)); + if (face == AttachFace.CEILING) + angle = -angle; + if (face == AttachFace.WALL) + angle = 0; + return VecHelper.rotateCentered(vec, angle, Axis.Y); + }); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkGenerator.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkGenerator.java new file mode 100644 index 0000000000..ec1e441972 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/PackagerLinkGenerator.java @@ -0,0 +1,37 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraftforge.client.model.generators.ModelFile; + +public class PackagerLinkGenerator extends SpecialBlockStateGen { + + @Override + protected int getXRotation(BlockState state) { + return state.getValue(PackagerLinkBlock.FACE) == AttachFace.CEILING ? 180 : 0; + } + + @Override + protected int getYRotation(BlockState state) { + Direction facing = state.getValue(PackagerLinkBlock.FACING); + return horizontalAngle(facing); + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + String variant = + state.getValue(PackagerLinkBlock.FACE) == AttachFace.WALL ? "block_horizontal" : "block_vertical"; + if (state.getValue(PackagerLinkBlock.POWERED)) + variant += "_powered"; + return prov.models() + .getExistingFile(prov.modLoc("block/stock_link/" + variant)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/RequestPromise.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/RequestPromise.java new file mode 100644 index 0000000000..ee40d7b74a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/RequestPromise.java @@ -0,0 +1,25 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.Comparator; + +import com.simibubi.create.content.logistics.BigItemStack; + +public class RequestPromise { + + public int ticksExisted; + public BigItemStack promisedStack; + + public RequestPromise(BigItemStack promisedStack) { + this.promisedStack = promisedStack; + ticksExisted = 0; + } + + public void tick() { + ticksExisted++; + } + + public static Comparator ageComparator() { + return (i1, i2) -> Integer.compare(i2.ticksExisted, i1.ticksExisted); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/RequestPromiseQueue.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/RequestPromiseQueue.java new file mode 100644 index 0000000000..a98bbb6884 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/RequestPromiseQueue.java @@ -0,0 +1,140 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import com.simibubi.create.content.logistics.BigItemStack; + +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.ItemHandlerHelper; + +public class RequestPromiseQueue { + + private Map> promisesByItem; + private Runnable onChanged; + + public RequestPromiseQueue(Runnable onChanged) { + promisesByItem = new IdentityHashMap<>(); + this.onChanged = onChanged; + } + + public void add(RequestPromise promise) { + promisesByItem.computeIfAbsent(promise.promisedStack.stack.getItem(), $ -> new LinkedList<>()) + .add(promise); + onChanged.run(); + } + + public void setOnChanged(Runnable onChanged) { + this.onChanged = onChanged; + } + + public int getTotalPromisedAndRemoveExpired(ItemStack stack, int expiryTime) { + int promised = 0; + List list = promisesByItem.get(stack.getItem()); + if (list == null) + return promised; + + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + RequestPromise promise = iterator.next(); + if (!ItemHandlerHelper.canItemStacksStack(promise.promisedStack.stack, stack)) + continue; + if (expiryTime != -1 && promise.ticksExisted >= expiryTime) { + iterator.remove(); + onChanged.run(); + continue; + } + + promised += promise.promisedStack.count; + } + return promised; + } + + public void forceClear(ItemStack stack) { + List list = promisesByItem.get(stack.getItem()); + if (list == null) + return; + + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + RequestPromise promise = iterator.next(); + if (!ItemHandlerHelper.canItemStacksStack(promise.promisedStack.stack, stack)) + continue; + iterator.remove(); + onChanged.run(); + } + + if (list.isEmpty()) + promisesByItem.remove(stack.getItem()); + } + + public void itemEnteredSystem(ItemStack stack, int amount) { + List list = promisesByItem.get(stack.getItem()); + if (list == null) + return; + + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + RequestPromise requestPromise = iterator.next(); + if (!ItemHandlerHelper.canItemStacksStack(requestPromise.promisedStack.stack, stack)) + continue; + + int toSubtract = Math.min(amount, requestPromise.promisedStack.count); + amount -= toSubtract; + requestPromise.promisedStack.count -= toSubtract; + + if (requestPromise.promisedStack.count <= 0) { + iterator.remove(); + onChanged.run(); + } + if (amount <= 0) + break; + } + + if (list.isEmpty()) + promisesByItem.remove(stack.getItem()); + } + + public List flatten(boolean sorted) { + List all = new ArrayList<>(); + promisesByItem.forEach((key, list) -> all.addAll(list)); + if (sorted) + Collections.sort(all, RequestPromise.ageComparator()); + return all; + } + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + tag.put("List", NBTHelper.writeCompoundList(flatten(false), rp -> { + CompoundTag c = rp.promisedStack.write(); + c.putInt("Age", rp.ticksExisted); + return c; + })); + return tag; + } + + public static RequestPromiseQueue read(CompoundTag tag, Runnable onChanged) { + RequestPromiseQueue queue = new RequestPromiseQueue(onChanged); + NBTHelper.iterateCompoundList(tag.getList("List", Tag.TAG_COMPOUND), c -> { + RequestPromise promise = new RequestPromise(BigItemStack.read(c)); + promise.ticksExisted = c.getInt("Age"); + queue.add(promise); + }); + return queue; + } + + public void tick() { + promisesByItem.forEach((key, list) -> list.forEach(RequestPromise::tick)); // delete old entries? + } + + public boolean isEmpty() { + return promisesByItem.isEmpty(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/WiFiEffectPacket.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/WiFiEffectPacket.java new file mode 100644 index 0000000000..fc19698c24 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/WiFiEffectPacket.java @@ -0,0 +1,50 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkEvent.Context; + +public class WiFiEffectPacket extends SimplePacketBase { + + private BlockPos pos; + + public static void send(Level level, BlockPos pos) { + AllPackets.sendToNear(level, pos, 32, new WiFiEffectPacket(pos)); + } + + public WiFiEffectPacket(BlockPos pos) { + this.pos = pos; + } + + public WiFiEffectPacket(FriendlyByteBuf buffer) { + pos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + } + + @Override + @OnlyIn(Dist.CLIENT) + public boolean handle(Context context) { + context.enqueueWork(() -> { + BlockEntity blockEntity = Minecraft.getInstance().level.getBlockEntity(pos); + if (blockEntity instanceof PackagerLinkBlockEntity plbe) + plbe.playEffect(); + if (blockEntity instanceof StockTickerBlockEntity plbe) + plbe.playEffect(); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/packagerLink/WiFiParticle.java b/src/main/java/com/simibubi/create/content/logistics/packagerLink/WiFiParticle.java new file mode 100644 index 0000000000..a9f157bf93 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/packagerLink/WiFiParticle.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.logistics.packagerLink; + +import org.joml.Quaternionf; + +import com.simibubi.create.AllParticleTypes; +import com.simibubi.create.content.equipment.bell.BasicParticleData; +import com.simibubi.create.content.equipment.bell.CustomRotationParticle; + +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.util.Mth; + +public class WiFiParticle extends CustomRotationParticle { + + private SpriteSet animatedSprite; + private boolean downward; + + public WiFiParticle(ClientLevel worldIn, double x, double y, double z, double vx, double vy, double vz, + SpriteSet spriteSet) { + super(worldIn, x, y + (vy < 0 ? -1 : 1), z, spriteSet, 0); + this.animatedSprite = spriteSet; + this.quadSize = 0.5f; + this.setSize(this.quadSize, this.quadSize); + this.loopLength = 16; + this.lifetime = 16; + this.setSpriteFromAge(spriteSet); + this.stoppedByCollision = true; // disable movement + this.downward = vy < 0; + } + + @Override + public void tick() { + setSpriteFromAge(animatedSprite); + if (age++ >= lifetime) + remove(); + } + + @Override + public Quaternionf getCustomRotation(Camera camera, float partialTicks) { + return new Quaternionf().rotateY(-camera.getYRot() * Mth.DEG_TO_RAD) + .mul(new Quaternionf().rotateZ(downward ? Mth.PI : 0)); + } + + public static class Data extends BasicParticleData implements ParticleOptions { + + @Override + public IBasicParticleFactory getBasicFactory() { + return WiFiParticle::new; + } + + @Override + public ParticleType getType() { + return AllParticleTypes.WIFI.get(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/AutoRequestData.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/AutoRequestData.java new file mode 100644 index 0000000000..71817c0552 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/AutoRequestData.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class AutoRequestData { + + public PackageOrder encodedRequest = PackageOrder.empty(); + public PackageOrder encodedRequestContext = PackageOrder.empty(); + public String encodedTargetAdress = ""; + public BlockPos targetOffset = BlockPos.ZERO; + public String targetDim = ""; + public boolean isValid = false; + + public static AutoRequestData read(CompoundTag tag) { + AutoRequestData requestData = new AutoRequestData(); + requestData.targetOffset = NbtUtils.readBlockPos(tag.getCompound("TargetOffset")); + requestData.targetDim = tag.getString("TargetDim"); + requestData.isValid = tag.getBoolean("Valid"); + requestData.encodedTargetAdress = tag.getString("EncodedAddress"); + requestData.encodedRequest = PackageOrder.read(tag.getCompound("EncodedRequest")); + requestData.encodedRequestContext = PackageOrder.read(tag.getCompound("EncodedRequestContext")); + return requestData; + } + + public void write(CompoundTag tag) { + tag.put("TargetOffset", NbtUtils.writeBlockPos(targetOffset)); + tag.putString("TargetDim", targetDim); + tag.putBoolean("Valid", isValid); + tag.putString("EncodedAddress", encodedTargetAdress); + tag.put("EncodedRequest", encodedRequest.write()); + tag.put("EncodedRequestContext", encodedRequestContext.write()); + } + + public void writeToItem(BlockPos position, ItemStack itemStack) { + CompoundTag tag = itemStack.getOrCreateTag(); + write(tag); + tag.put("TargetOffset", NbtUtils.writeBlockPos(position.offset(targetOffset))); + tag.remove("Valid"); + itemStack.setTag(tag); + } + + public static AutoRequestData readFromItem(Level level, Player player, BlockPos position, ItemStack itemStack) { + CompoundTag tag = itemStack.getTag(); + if (tag == null || !tag.contains("TargetOffset")) + return null; + + AutoRequestData requestData = read(tag); + requestData.targetOffset = requestData.targetOffset.subtract(position); + requestData.isValid = + requestData.targetOffset.closerThan(BlockPos.ZERO, 128) && requestData.targetDim.equals(level.dimension() + .location() + .toString()); + + if (player != null) + CreateLang + .translate(requestData.isValid ? "redstone_requester.keeper_connected" + : "redstone_requester.keeper_too_far_away") + .style(requestData.isValid ? ChatFormatting.WHITE : ChatFormatting.RED) + .sendStatus(player); + + return requestData; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlock.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlock.java new file mode 100644 index 0000000000..360ddea093 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlock.java @@ -0,0 +1,189 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import java.util.List; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.SignalGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; + +public class RedstoneRequesterBlock extends Block implements IBE, IWrenchable { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final EnumProperty AXIS = BlockStateProperties.HORIZONTAL_AXIS; + + public RedstoneRequesterBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(POWERED, false)); + } + + @Override + protected void createBlockStateDefinition( + net.minecraft.world.level.block.state.StateDefinition.Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(POWERED, AXIS)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + BlockState stateForPlacement = super.getStateForPlacement(pContext); + if (stateForPlacement == null) + return null; + return stateForPlacement.setValue(AXIS, pContext.getHorizontalDirection() + .getAxis()) + .setValue(POWERED, pContext.getLevel() + .hasNeighborSignal(pContext.getClickedPos())); + } + + @Override + public boolean shouldCheckWeakPower(BlockState state, SignalGetter level, BlockPos pos, Direction side) { + return false; + } + + @Override + public boolean hasAnalogOutputSignal(BlockState pState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState pBlockState, Level pLevel, BlockPos pPos) { + RedstoneRequesterBlockEntity req = getBlockEntity(pLevel, pPos); + return req != null && req.lastRequestSucceeded ? 15 : 0; + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + return onBlockEntityUse(pLevel, pPos, be -> be.use(pPlayer)); + } + + public static void programRequester(ServerPlayer player, StockTickerBlockEntity be, PackageOrder order, + String address, PackageOrder orderContext) { + ItemStack stack = player.getMainHandItem(); + boolean isRequester = AllBlocks.REDSTONE_REQUESTER.isIn(stack); + boolean isShopCloth = AllItemTags.TABLE_CLOTHS.matches(stack); + if (!isRequester && !isShopCloth) + return; + + AutoRequestData autoRequestData = new AutoRequestData(); + autoRequestData.encodedRequest = order; + autoRequestData.encodedRequestContext = orderContext; + autoRequestData.encodedTargetAdress = address; + autoRequestData.targetOffset = be.getBlockPos(); + autoRequestData.targetDim = player.level() + .dimension() + .location() + .toString(); + + autoRequestData.writeToItem(BlockPos.ZERO, stack); + + if (isRequester) { + CompoundTag stackTag = stack.getTag(); + CompoundTag beTag = stackTag.getCompound(BlockItem.BLOCK_ENTITY_TAG); + beTag.putUUID("Freq", be.behaviour.freqId); + stackTag.put(BlockItem.BLOCK_ENTITY_TAG, beTag); + } + + player.setItemInHand(InteractionHand.MAIN_HAND, stack); + } + + public static void appendRequesterTooltip(ItemStack pStack, List pTooltip) { + if (!pStack.hasTag()) + return; + + CompoundTag compoundnbt = pStack.getTag(); + if (!compoundnbt.contains("EncodedRequest", Tag.TAG_COMPOUND)) + return; + + PackageOrder contents = PackageOrder.read(compoundnbt.getCompound("EncodedRequest")); + for (BigItemStack entry : contents.stacks()) { + pTooltip.add(entry.stack.getHoverName() + .copy() + .append(" x") + .append(String.valueOf(entry.count)) + .withStyle(ChatFormatting.GRAY)); + } + + CreateLang.translate("logistically_linked.tooltip_clear") + .style(ChatFormatting.DARK_GRAY) + .addTo(pTooltip); + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos requesterPos, BlockState pState, LivingEntity pPlacer, + ItemStack pStack) { + Player player = pPlacer instanceof Player ? (Player) pPlacer : null; + withBlockEntityDo(pLevel, requesterPos, rrbe -> { + AutoRequestData data = AutoRequestData.readFromItem(pLevel, player, requesterPos, pStack); + if (data == null) + return; + rrbe.encodedRequest = data.encodedRequest; + rrbe.encodedRequestContext = data.encodedRequestContext; + rrbe.encodedTargetAdress = data.encodedTargetAdress; + }); + } + + @Override + public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pNeighborBlock, + BlockPos pNeighborPos, boolean pMovedByPiston) { + if (pLevel.isClientSide()) + return; + pLevel.setBlockAndUpdate(pPos, pState.setValue(POWERED, pLevel.hasNeighborSignal(pPos))); + withBlockEntityDo(pLevel, pPos, RedstoneRequesterBlockEntity::onRedstonePowerChanged); + } + + @Override + public Class getBlockEntityClass() { + return RedstoneRequesterBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.REDSTONE_REQUESTER.get(); + } + + @Override + public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) { + return false; + } + + @Override + public BlockState rotate(BlockState pState, Rotation pRotation) { + return pState.setValue(AXIS, pRotation.rotate(Direction.get(AxisDirection.POSITIVE, pState.getValue(AXIS))) + .getAxis()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlockEntity.java new file mode 100644 index 0000000000..e5a0152fd8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlockEntity.java @@ -0,0 +1,152 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.packagerLink.WiFiParticle; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.content.logistics.stockTicker.StockCheckingBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.network.NetworkHooks; + +public class RedstoneRequesterBlockEntity extends StockCheckingBlockEntity implements MenuProvider { + + public boolean allowPartialRequests; + public PackageOrder encodedRequest = PackageOrder.empty(); + public PackageOrder encodedRequestContext = PackageOrder.empty(); + public String encodedTargetAdress = ""; + + public boolean lastRequestSucceeded; + + protected boolean redstonePowered; + + public RedstoneRequesterBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + allowPartialRequests = false; + } + + protected void onRedstonePowerChanged() { + boolean hasNeighborSignal = level.hasNeighborSignal(worldPosition); + if (redstonePowered == hasNeighborSignal) + return; + + lastRequestSucceeded = false; + if (hasNeighborSignal) + triggerRequest(); + + redstonePowered = hasNeighborSignal; + notifyUpdate(); + } + + public void triggerRequest() { + if (encodedRequest.isEmpty()) + return; + + boolean anySucceeded = false; + + InventorySummary summaryOfOrder = new InventorySummary(); + encodedRequest.stacks() + .forEach(summaryOfOrder::add); + + InventorySummary summary = getAccurateSummary(); + for (BigItemStack entry : summaryOfOrder.getStacks()) { + if (summary.getCountOf(entry.stack) >= entry.count) { + anySucceeded = true; + continue; + } + if (!allowPartialRequests) { + AllPackets.sendToNear(level, worldPosition, 32, + new RedstoneRequesterEffectPacket(worldPosition, false)); + return; + } + } + + broadcastPackageRequest(RequestType.REDSTONE, encodedRequest, null, encodedTargetAdress, encodedRequestContext.isEmpty() ? null : encodedRequestContext); + AllPackets.sendToNear(level, worldPosition, 32, new RedstoneRequesterEffectPacket(worldPosition, anySucceeded)); + lastRequestSucceeded = true; + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + redstonePowered = tag.getBoolean("Powered"); + lastRequestSucceeded = tag.getBoolean("Success"); + allowPartialRequests = tag.getBoolean("AllowPartial"); + encodedRequest = PackageOrder.read(tag.getCompound("EncodedRequest")); + encodedRequestContext = PackageOrder.read(tag.getCompound("EncodedRequestContext")); + encodedTargetAdress = tag.getString("EncodedAddress"); + } + + @Override + public void writeSafe(CompoundTag tag) { + super.writeSafe(tag); + tag.putBoolean("AllowPartial", allowPartialRequests); + tag.putString("EncodedAddress", encodedTargetAdress); + tag.put("EncodedRequest", encodedRequest.write()); + tag.put("EncodedRequestContext", encodedRequestContext.write()); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.putBoolean("Powered", redstonePowered); + tag.putBoolean("Success", lastRequestSucceeded); + tag.putBoolean("AllowPartial", allowPartialRequests); + tag.putString("EncodedAddress", encodedTargetAdress); + tag.put("EncodedRequest", encodedRequest.write()); + tag.put("EncodedRequestContext", encodedRequestContext.write()); + } + + public InteractionResult use(Player player) { + if (player == null || player.isCrouching()) + return InteractionResult.PASS; + if (player instanceof FakePlayer) + return InteractionResult.PASS; + if (level.isClientSide) + return InteractionResult.SUCCESS; + if (!behaviour.mayInteractMessage(player)) + return InteractionResult.SUCCESS; + + NetworkHooks.openScreen((ServerPlayer) player, this, worldPosition); + return InteractionResult.SUCCESS; + } + + @Override + public Component getDisplayName() { + return Component.empty(); + } + + @Override + public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { + return RedstoneRequesterMenu.create(pContainerId, pPlayerInventory, this); + } + + public void playEffect(boolean success) { + Vec3 vec3 = Vec3.atCenterOf(worldPosition); + if (success) { + AllSoundEvents.CONFIRM.playAt(level, worldPosition, 0.5f, 1.5f, false); + AllSoundEvents.STOCK_LINK.playAt(level, worldPosition, 1.0f, 1.0f, false); + level.addParticle(new WiFiParticle.Data(), vec3.x, vec3.y, vec3.z, 1, 1, 1); + } else { + AllSoundEvents.DENY.playAt(level, worldPosition, 0.5f, 1, false); + level.addParticle(ParticleTypes.ENCHANTED_HIT, vec3.x, vec3.y + 1, vec3.z, 0, 0, 0); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlockItem.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlockItem.java new file mode 100644 index 0000000000..1394e327d6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterBlockItem.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import java.util.List; + +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBlockItem; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; + +public class RedstoneRequesterBlockItem extends LogisticallyLinkedBlockItem { + + public RedstoneRequesterBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public void appendHoverText(ItemStack pStack, Level pLevel, List pTooltip, TooltipFlag pFlag) { + if (!isTuned(pStack)) + return; + + if (!pStack.getTag() + .contains("EncodedRequest", Tag.TAG_COMPOUND)) { + super.appendHoverText(pStack, pLevel, pTooltip, pFlag); + return; + } + + CreateLang.translate("logistically_linked.tooltip") + .style(ChatFormatting.GOLD) + .addTo(pTooltip); + RedstoneRequesterBlock.appendRequesterTooltip(pStack, pTooltip); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterConfigurationPacket.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterConfigurationPacket.java new file mode 100644 index 0000000000..c2cf4a3442 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterConfigurationPacket.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; + +public class RedstoneRequesterConfigurationPacket extends BlockEntityConfigurationPacket { + + private String address; + private boolean allowPartial; + private List amounts; + + public RedstoneRequesterConfigurationPacket(BlockPos pos, String address, boolean allowPartial, + List amounts) { + super(pos); + this.address = address; + this.allowPartial = allowPartial; + this.amounts = amounts; + } + + public RedstoneRequesterConfigurationPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeUtf(address); + buffer.writeBoolean(allowPartial); + buffer.writeVarInt(amounts.size()); + amounts.forEach(buffer::writeVarInt); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + address = buffer.readUtf(); + allowPartial = buffer.readBoolean(); + int size = buffer.readVarInt(); + amounts = new ArrayList<>(); + for (int i = 0; i < size; i++) + amounts.add(buffer.readVarInt()); + } + + @Override + protected void applySettings(RedstoneRequesterBlockEntity be) { + be.encodedTargetAdress = address; + List stacks = be.encodedRequest.stacks(); + for (int i = 0; i < stacks.size() && i < amounts.size(); i++) { + ItemStack stack = stacks.get(i).stack; + if (!stack.isEmpty()) + stacks.set(i, new BigItemStack(stack, amounts.get(i))); + } + be.allowPartialRequests = allowPartial; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterEffectPacket.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterEffectPacket.java new file mode 100644 index 0000000000..3e47d5005c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterEffectPacket.java @@ -0,0 +1,43 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkEvent.Context; + +public class RedstoneRequesterEffectPacket extends SimplePacketBase { + + private BlockPos pos; + private boolean success; + + public RedstoneRequesterEffectPacket(BlockPos pos, boolean success) { + this.pos = pos; + this.success = success; + } + + public RedstoneRequesterEffectPacket(FriendlyByteBuf buffer) { + pos = buffer.readBlockPos(); + success = buffer.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + buffer.writeBoolean(success); + } + + @Override + @OnlyIn(Dist.CLIENT) + public boolean handle(Context context) { + context.enqueueWork(() -> { + if (Minecraft.getInstance().level.getBlockEntity(pos) instanceof RedstoneRequesterBlockEntity plbe) + plbe.playEffect(success); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterMenu.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterMenu.java new file mode 100644 index 0000000000..878f42178f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterMenu.java @@ -0,0 +1,82 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.stockTicker.PackageOrder; +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class RedstoneRequesterMenu extends GhostItemMenu { + + public RedstoneRequesterMenu(MenuType type, int id, Inventory inv, RedstoneRequesterBlockEntity contentHolder) { + super(type, id, inv, contentHolder); + } + + public RedstoneRequesterMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public static RedstoneRequesterMenu create(int id, Inventory inv, RedstoneRequesterBlockEntity be) { + return new RedstoneRequesterMenu(AllMenuTypes.REDSTONE_REQUESTER.get(), id, inv, be); + } + + @Override + protected ItemStackHandler createGhostInventory() { + ItemStackHandler inventory = new ItemStackHandler(9); + List stacks = contentHolder.encodedRequest.stacks(); + for (int i = 0; i < stacks.size(); i++) + inventory.setStackInSlot(i, stacks.get(i).stack.copyWithCount(1)); + return inventory; + } + + @Override + protected boolean allowRepeats() { + return true; + } + + @Override + @OnlyIn(Dist.CLIENT) + protected RedstoneRequesterBlockEntity createOnClient(FriendlyByteBuf extraData) { + BlockPos blockPos = extraData.readBlockPos(); + return AllBlocks.REDSTONE_REQUESTER.get() + .getBlockEntity(Minecraft.getInstance().level, blockPos); + } + + @Override + protected void addSlots() { + int playerX = 5; + int playerY = 142; + int slotX = 27; + int slotY = 28; + + addPlayerSlots(playerX, playerY); + for (int i = 0; i < 9; i++) + addSlot(new SlotItemHandler(ghostInventory, i, slotX + 20 * i, slotY)); + } + + @Override + protected void saveData(RedstoneRequesterBlockEntity contentHolder) { + List stacks = contentHolder.encodedRequest.stacks(); + ArrayList list = new ArrayList<>(); + for (int i = 0; i < ghostInventory.getSlots(); i++) + list.add(new BigItemStack(ghostInventory.getStackInSlot(i) + .copyWithCount(1), i < stacks.size() ? stacks.get(i).count : 1)); + + contentHolder.encodedRequest = new PackageOrder(list); + contentHolder.sendData(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterScreen.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterScreen.java new file mode 100644 index 0000000000..1fb143ca79 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterScreen.java @@ -0,0 +1,246 @@ +package com.simibubi.create.content.logistics.redstoneRequester; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.AddressEditBox; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.trains.station.NoShadowFontWrapper; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.gui.element.GuiGameElement; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.SlotItemHandler; + +public class RedstoneRequesterScreen extends AbstractSimiContainerScreen { + + private EditBox addressBox; + private IconButton confirmButton; + private List extraAreas = Collections.emptyList(); + private List amounts = new ArrayList<>(); + + private IconButton dontAllowPartial; + private IconButton allowPartial; + + public RedstoneRequesterScreen(RedstoneRequesterMenu container, Inventory inv, Component title) { + super(container, inv, title); + + for (int i = 0; i < 9; i++) + amounts.add(1); + + List stacks = menu.contentHolder.encodedRequest.stacks(); + for (int i = 0; i < stacks.size(); i++) + amounts.set(i, Math.max(1, stacks.get(i).count)); + } + + @Override + protected void containerTick() { + super.containerTick(); + addressBox.tick(); + for (int i = 0; i < amounts.size(); i++) + if (menu.ghostInventory.getStackInSlot(i) + .isEmpty()) + amounts.set(i, 1); + } + + @Override + protected void init() { + int bgHeight = AllGuiTextures.REDSTONE_REQUESTER.getHeight(); + int bgWidth = AllGuiTextures.REDSTONE_REQUESTER.getWidth(); + setWindowSize(bgWidth, bgHeight + AllGuiTextures.PLAYER_INVENTORY.getHeight()); + super.init(); + clearWidgets(); + int x = getGuiLeft(); + int y = getGuiTop(); + + if (addressBox == null) { + addressBox = new AddressEditBox(this, new NoShadowFontWrapper(font), x + 55, y + 68, 110, 10, false); + addressBox.setValue(menu.contentHolder.encodedTargetAdress); + addressBox.setTextColor(0x555555); + } + addRenderableWidget(addressBox); + + confirmButton = new IconButton(x + bgWidth - 30, y + bgHeight - 25, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> minecraft.player.closeContainer()); + addRenderableWidget(confirmButton); + + allowPartial = new IconButton(x + 12, y + bgHeight - 25, AllIcons.I_PARTIAL_REQUESTS); + allowPartial.withCallback(() -> { + allowPartial.green = true; + dontAllowPartial.green = false; + }); + allowPartial.green = menu.contentHolder.allowPartialRequests; + allowPartial.setToolTip(CreateLang.translate("gui.redstone_requester.allow_partial") + .component()); + addRenderableWidget(allowPartial); + + dontAllowPartial = new IconButton(x + 12 + 18, y + bgHeight - 25, AllIcons.I_FULL_REQUESTS); + dontAllowPartial.withCallback(() -> { + allowPartial.green = false; + dontAllowPartial.green = true; + }); + dontAllowPartial.green = !menu.contentHolder.allowPartialRequests; + dontAllowPartial.setToolTip(CreateLang.translate("gui.redstone_requester.dont_allow_partial") + .component()); + addRenderableWidget(dontAllowPartial); + + extraAreas = List.of(new Rect2i(x + bgWidth, y + bgHeight - 50, 70, 60)); + } + + @Override + protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY) { + int x = getGuiLeft(); + int y = getGuiTop(); + AllGuiTextures.REDSTONE_REQUESTER.render(pGuiGraphics, x + 3, y); + renderPlayerInventory(pGuiGraphics, x - 3, y + 124); + + ItemStack stack = AllBlocks.REDSTONE_REQUESTER.asStack(); + Component title = CreateLang.text(stack.getHoverName() + .getString()) + .component(); + pGuiGraphics.drawString(font, title, x + 117 - font.width(title) / 2, y + 4, 0x3D3C48, false); + + GuiGameElement.of(stack) + .scale(3) + .render(pGuiGraphics, x + 245, y + 80); + } + + @Override + protected void renderForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + super.renderForeground(graphics, mouseX, mouseY, partialTicks); + int x = getGuiLeft(); + int y = getGuiTop(); + + for (int i = 0; i < amounts.size(); i++) { + int inputX = x + 27 + i * 20; + int inputY = y + 28; + ItemStack itemStack = menu.ghostInventory.getStackInSlot(i); + if (itemStack.isEmpty()) + continue; + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(0, 0, 100); + graphics.renderItemDecorations(font, itemStack, inputX, inputY, "" + amounts.get(i)); + ms.popPose(); + } + + if (addressBox.isHovered() && !addressBox.isFocused()) { + if (addressBox.getValue() + .isBlank()) + graphics.renderComponentTooltip(font, + List.of(CreateLang.translate("gui.redstone_requester.requester_address") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.redstone_requester.requester_address_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.redstone_requester.requester_address_tip_1") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.schedule.lmb_edit") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mouseX, mouseY); + else + graphics.renderComponentTooltip(font, + List.of(CreateLang.translate("gui.redstone_requester.requester_address_given") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.text("'" + addressBox.getValue() + "'") + .style(ChatFormatting.GRAY) + .component()), + mouseX, mouseY); + } + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double pDelta) { + int x = getGuiLeft(); + int y = getGuiTop(); + + if (addressBox.mouseScrolled(mouseX, mouseY, pDelta)) + return true; + + for (int i = 0; i < amounts.size(); i++) { + int inputX = x + 27 + i * 20; + int inputY = y + 28; + if (mouseX >= inputX && mouseX < inputX + 16 && mouseY >= inputY && mouseY < inputY + 16) { + ItemStack itemStack = menu.ghostInventory.getStackInSlot(i); + if (itemStack.isEmpty()) + return true; + amounts.set(i, + Mth.clamp((int) (amounts.get(i) + Math.signum(pDelta) * (hasShiftDown() ? 10 : 1)), 1, 256)); + return true; + } + } + + return super.mouseScrolled(mouseX, mouseY, pDelta); + } + + /* + * Fixes InventorySorter nabbing the scroll event. This screen needs it for + * amount control + */ + @Override + public @Nullable Slot getSlotUnderMouse() { + return null; + } + + @Override + protected List getTooltipFromContainerItem(ItemStack pStack) { + List tooltip = super.getTooltipFromContainerItem(pStack); + if (!(hoveredSlot instanceof SlotItemHandler)) + return tooltip; + + int slotIndex = this.hoveredSlot.getSlotIndex(); + if (slotIndex >= amounts.size()) + return tooltip; + + return List.of(CreateLang.translate("gui.factory_panel.send_item", CreateLang.itemName(pStack) + .add(CreateLang.text(" x" + amounts.get(slotIndex)))) + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.factory_panel.scroll_to_change_amount") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component(), + CreateLang.translate("gui.scrollInput.shiftScrollsFaster") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + + @Override + public void removed() { + AllPackets.getChannel() + .sendToServer(new RedstoneRequesterConfigurationPacket(menu.contentHolder.getBlockPos(), + addressBox.getValue(), allowPartial.green, amounts)); + super.removed(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/CraftableBigItemStack.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/CraftableBigItemStack.java new file mode 100644 index 0000000000..adf98ff580 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/CraftableBigItemStack.java @@ -0,0 +1,30 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.List; + +import com.simibubi.create.content.logistics.BigItemStack; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.Level; + +public class CraftableBigItemStack extends BigItemStack { + + public Recipe recipe; + + public CraftableBigItemStack(ItemStack stack, Recipe recipe) { + super(stack); + this.recipe = recipe; + } + + public List getIngredients() { + return recipe.getIngredients(); + } + + public int getOutputCount(Level level) { + return recipe.getResultItem(level.registryAccess()) + .getCount(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockRequestPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockRequestPacket.java new file mode 100644 index 0000000000..bf1cc7934f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockRequestPacket.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public class LogisticalStockRequestPacket extends BlockEntityConfigurationPacket { + + public LogisticalStockRequestPacket(BlockPos pos) { + super(pos); + } + + public LogisticalStockRequestPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) {} + + @Override + protected void readSettings(FriendlyByteBuf buffer) {} + + @Override + protected void applySettings(StockCheckingBlockEntity be) {} + + @Override + protected void applySettings(ServerPlayer player, StockCheckingBlockEntity be) { + be.getRecentSummary() + .divideAndSendTo(player, pos); + } + + @Override + protected int maxRange() { + return 4096; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockResponsePacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockResponsePacket.java new file mode 100644 index 0000000000..eb5fb4d99e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockResponsePacket.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkEvent.Context; + +public class LogisticalStockResponsePacket extends SimplePacketBase { + + private BlockPos pos; + private List items; + private boolean lastPacket; + + public LogisticalStockResponsePacket(boolean lastPacket, BlockPos pos, List items) { + this.lastPacket = lastPacket; + this.pos = pos; + this.items = items; + } + + public LogisticalStockResponsePacket(FriendlyByteBuf buffer) { + lastPacket = buffer.readBoolean(); + pos = buffer.readBlockPos(); + int count = buffer.readVarInt(); + items = new ArrayList<>(count); + for (int i = 0; i < count; i++) + items.add(BigItemStack.receive(buffer)); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(lastPacket); + buffer.writeBlockPos(pos); + buffer.writeVarInt(items.size()); + items.forEach(stack -> stack.send(buffer)); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(this::handleClient); + return true; + } + + @OnlyIn(Dist.CLIENT) + public void handleClient() { + if (Minecraft.getInstance().level.getBlockEntity(pos) instanceof StockTickerBlockEntity stbe) + stbe.receiveStockPacket(items, lastPacket); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrder.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrder.java new file mode 100644 index 0000000000..68fc5cf201 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrder.java @@ -0,0 +1,50 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.content.logistics.BigItemStack; + +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; + +public record PackageOrder(List stacks) { + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + tag.put("Entries", NBTHelper.writeCompoundList(stacks, BigItemStack::write)); + return tag; + } + + public static PackageOrder empty() { + return new PackageOrder(List.of()); + } + + public boolean isEmpty() { + return stacks.isEmpty(); + } + + public static PackageOrder read(CompoundTag tag) { + List stacks = new ArrayList<>(); + NBTHelper.iterateCompoundList(tag.getList("Entries", Tag.TAG_COMPOUND), + entryTag -> stacks.add(BigItemStack.read(entryTag))); + return new PackageOrder(stacks); + } + + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(stacks.size()); + for (BigItemStack entry : stacks) + entry.send(buffer); + } + + public static PackageOrder read(FriendlyByteBuf buffer) { + int size = buffer.readVarInt(); + List stacks = new ArrayList<>(); + for (int i = 0; i < size; i++) + stacks.add(BigItemStack.receive(buffer)); + return new PackageOrder(stacks); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrderRequestPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrderRequestPacket.java new file mode 100644 index 0000000000..23aee60506 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrderRequestPacket.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.packagerLink.WiFiEffectPacket; +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterBlock; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public class PackageOrderRequestPacket extends BlockEntityConfigurationPacket { + + private PackageOrder order; + private String address; + private boolean encodeRequester; + private PackageOrder craftingRequest; + + public PackageOrderRequestPacket(BlockPos pos, PackageOrder order, String address, boolean encodeRequester, PackageOrder craftingRequest) { + super(pos); + this.order = order; + this.address = address; + this.encodeRequester = encodeRequester; + this.craftingRequest = craftingRequest; + } + + public PackageOrderRequestPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeUtf(address); + order.write(buffer); + buffer.writeBoolean(encodeRequester); + craftingRequest.write(buffer); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + address = buffer.readUtf(); + order = PackageOrder.read(buffer); + encodeRequester = buffer.readBoolean(); + craftingRequest = PackageOrder.read(buffer); + } + + @Override + protected void applySettings(StockTickerBlockEntity be) {} + + @Override + protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { + if (encodeRequester) { + if (!order.isEmpty()) + AllSoundEvents.CONFIRM.playOnServer(be.getLevel(), pos); + player.closeContainer(); + RedstoneRequesterBlock.programRequester(player, be, order, address, craftingRequest); + return; + } + + if (!order.isEmpty()) { + AllSoundEvents.STOCK_TICKER_REQUEST.playOnServer(be.getLevel(), pos); + AllAdvancements.STOCK_TICKER.awardTo(player); + WiFiEffectPacket.send(player.level(), pos); + } + + be.broadcastPackageRequest(RequestType.PLAYER, order, null, address, craftingRequest.isEmpty() ? null : craftingRequest); + return; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockCheckingBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockCheckingBlockEntity.java new file mode 100644 index 0000000000..92529b17f5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockCheckingBlockEntity.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.packagerLink.LogisticsManager; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.IItemHandler; + +public abstract class StockCheckingBlockEntity extends SmartBlockEntity { + + public LogisticallyLinkedBehaviour behaviour; + + public StockCheckingBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(10); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(behaviour = new LogisticallyLinkedBehaviour(this, false)); + } + + public InventorySummary getRecentSummary() { + return LogisticsManager.getSummaryOfNetwork(behaviour.freqId, false); + } + + public InventorySummary getAccurateSummary() { + return LogisticsManager.getSummaryOfNetwork(behaviour.freqId, true); + } + + public boolean broadcastPackageRequest(RequestType type, PackageOrder order, IItemHandler ignoredHandler, + String address) { + return broadcastPackageRequest(type, order, ignoredHandler, address, null); + } + + public boolean broadcastPackageRequest(RequestType type, PackageOrder order, IItemHandler ignoredHandler, + String address, @Nullable PackageOrder orderContext) { + return LogisticsManager.broadcastPackageRequest(behaviour.freqId, type, order, ignoredHandler, address, orderContext); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryEditPacket.java new file mode 100644 index 0000000000..8e0dd52041 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryEditPacket.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; + +public class StockKeeperCategoryEditPacket extends BlockEntityConfigurationPacket { + + private List schedule; + + public StockKeeperCategoryEditPacket(BlockPos pos, List schedule) { + super(pos); + this.schedule = schedule; + } + + public StockKeeperCategoryEditPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + int size = buffer.readVarInt(); + schedule = new ArrayList<>(); + for (int i = 0; i < size; i++) + schedule.add(buffer.readItem()); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeVarInt(schedule.size()); + schedule.forEach(buffer::writeItem); + } + + @Override + protected void applySettings(StockTickerBlockEntity be) { + be.categories = schedule; + be.notifyUpdate(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryHidingPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryHidingPacket.java new file mode 100644 index 0000000000..d8cb2d7cc3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryHidingPacket.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.List; +import java.util.stream.IntStream; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public class StockKeeperCategoryHidingPacket extends BlockEntityConfigurationPacket { + + private List indices; + + public StockKeeperCategoryHidingPacket(BlockPos pos, List indices) { + super(pos); + this.indices = indices; + } + + public StockKeeperCategoryHidingPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeVarIntArray(indices.stream() + .mapToInt(i -> i) + .toArray()); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + indices = IntStream.of(buffer.readVarIntArray()) + .boxed() + .toList(); + } + + @Override + protected void applySettings(StockTickerBlockEntity be) {} + + @Override + protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { + if (indices.isEmpty()) { + be.hiddenCategoriesByPlayer.remove(player.getUUID()); + } else { + be.hiddenCategoriesByPlayer.put(player.getUUID(), indices); + be.notifyUpdate(); + } + return; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryMenu.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryMenu.java new file mode 100644 index 0000000000..a76b1fad23 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryMenu.java @@ -0,0 +1,128 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.foundation.gui.menu.MenuBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class StockKeeperCategoryMenu extends MenuBase { + + public boolean slotsActive = true; + public ItemStackHandler proxyInventory; + + public StockKeeperCategoryMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public static AbstractContainerMenu create(int pContainerId, Inventory pPlayerInventory, + StockTickerBlockEntity stockTickerBlockEntity) { + return new StockKeeperCategoryMenu(AllMenuTypes.STOCK_KEEPER_CATEGORY.get(), pContainerId, pPlayerInventory, + stockTickerBlockEntity); + } + + public StockKeeperCategoryMenu(MenuType type, int id, Inventory inv, StockTickerBlockEntity contentHolder) { + super(type, id, inv, contentHolder); + } + + @Override + protected void initAndReadInventory(StockTickerBlockEntity contentHolder) { + proxyInventory = new ItemStackHandler(1); + } + + @Override + protected StockTickerBlockEntity createOnClient(FriendlyByteBuf extraData) { + BlockPos blockPos = extraData.readBlockPos(); + return AllBlocks.STOCK_TICKER.get() + .getBlockEntity(Minecraft.getInstance().level, blockPos); + } + + @Override + protected void addSlots() { + addSlot(new InactiveItemHandlerSlot(proxyInventory, 0, 16, 24)); + addPlayerSlots(18, 106); + } + + @Override + protected void addPlayerSlots(int x, int y) { + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + this.addSlot(new InactiveSlot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new InactiveSlot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); + } + + @Override + protected void saveData(StockTickerBlockEntity contentHolder) {} + + @Override + public boolean stillValid(Player player) { + return !contentHolder.isRemoved() && player.position() + .closerThan(Vec3.atCenterOf(contentHolder.getBlockPos()), player.getBlockReach() + 4); + } + + class InactiveSlot extends Slot { + + public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) { + super(pContainer, pIndex, pX, pY); + } + + @Override + public boolean isActive() { + return slotsActive; + } + + } + + class InactiveItemHandlerSlot extends SlotItemHandler { + + public InactiveItemHandlerSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return super.mayPlace(stack) && (stack.isEmpty() || stack.getItem() instanceof FilterItem); + } + + @Override + public boolean isActive() { + return slotsActive; + } + + } + + @Override + public ItemStack quickMoveStack(Player pPlayer, int index) { + Slot clickedSlot = getSlot(index); + if (!clickedSlot.hasItem()) + return ItemStack.EMPTY; + + ItemStack stack = clickedSlot.getItem(); + int size = 1; + boolean success = false; + if (index < size) { + success = !moveItemStackTo(stack, size, slots.size(), false); + } else + success = !moveItemStackTo(stack, 0, size, false); + + return success ? ItemStack.EMPTY : stack; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryRefundPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryRefundPacket.java new file mode 100644 index 0000000000..25a96cf7d0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryRefundPacket.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; + +public class StockKeeperCategoryRefundPacket extends BlockEntityConfigurationPacket { + + private ItemStack filter; + + public StockKeeperCategoryRefundPacket(BlockPos pos, ItemStack filter) { + super(pos); + this.filter = filter; + } + + public StockKeeperCategoryRefundPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + filter = buffer.readItem(); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeItem(filter); + } + + @Override + protected void applySettings(StockTickerBlockEntity be) {} + + @Override + protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { + if (!filter.isEmpty() && filter.getItem() instanceof FilterItem) + player.getInventory() + .placeItemBackInInventory(filter); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryScreen.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryScreen.java new file mode 100644 index 0000000000..2c5e351ff2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryScreen.java @@ -0,0 +1,529 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import javax.annotation.Nullable; + +import org.lwjgl.glfw.GLFW; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.ScreenWithStencils; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.menu.GhostItemSubmitPacket; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.gui.UIRenderHelper; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.Renderable; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; + +import net.minecraftforge.items.SlotItemHandler; + +public class StockKeeperCategoryScreen extends AbstractSimiContainerScreen + implements ScreenWithStencils { + + private static final int CARD_HEADER = 20; + private static final int CARD_WIDTH = 160; + + private List extraAreas = Collections.emptyList(); + + private LerpedFloat scroll = LerpedFloat.linear() + .startWithValue(0); + + private List schedule; + private IconButton confirmButton; + private ItemStack editingItem; + private int editingIndex; + private IconButton editorConfirm; + private EditBox editorEditBox; + + final int slices = 4; + + public StockKeeperCategoryScreen(StockKeeperCategoryMenu menu, Inventory inv, Component title) { + super(menu, inv, title); + schedule = new ArrayList<>(menu.contentHolder.categories); + menu.slotsActive = false; + } + + @Override + protected void init() { + AllGuiTextures bg = AllGuiTextures.STOCK_KEEPER_CATEGORY; + setWindowSize(bg.getWidth(), bg.getHeight() * slices + AllGuiTextures.STOCK_KEEPER_CATEGORY_HEADER.getHeight() + + AllGuiTextures.STOCK_KEEPER_CATEGORY_FOOTER.getHeight()); + super.init(); + clearWidgets(); + + confirmButton = new IconButton(leftPos + bg.getWidth() - 25, topPos + imageHeight - 25, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> minecraft.player.closeContainer()); + addRenderableWidget(confirmButton); + + stopEditing(); + + extraAreas = ImmutableList.of(new Rect2i(leftPos + bg.getWidth(), topPos + imageHeight - 40, 48, 40)); + } + + protected void startEditing(int index) { + confirmButton.visible = false; + + editorConfirm = new IconButton(leftPos + 36 + 131, topPos + 59, AllIcons.I_CONFIRM); + menu.slotsActive = true; + + editorEditBox = new EditBox(font, leftPos + 47, topPos + 28, 124, 10, Component.empty()); + editorEditBox.setTextColor(0xffeeeeee); + editorEditBox.setBordered(false); + editorEditBox.setFocused(false); + editorEditBox.mouseClicked(0, 0, 0); + editorEditBox.setMaxLength(28); + editorEditBox.setValue(index == -1 || schedule.get(index) + .isEmpty() ? CreateLang.translate("gui.stock_ticker.new_category") + .string() + : schedule.get(index) + .getHoverName() + .getString()); + + editingIndex = index; + editingItem = index == -1 ? ItemStack.EMPTY : schedule.get(index); + menu.proxyInventory.setStackInSlot(0, editingItem); + AllPackets.getChannel() + .sendToServer(new GhostItemSubmitPacket(editingItem, 0)); + + addRenderableWidget(editorConfirm); + addRenderableWidget(editorEditBox); + } + + protected void stopEditing() { + confirmButton.visible = true; + if (editingItem == null) + return; + + playUiSound(SoundEvents.UI_BUTTON_CLICK.get(), 1, 1); + + removeWidget(editorConfirm); + removeWidget(editorEditBox); + + ItemStack stackInSlot = menu.proxyInventory.getStackInSlot(0) + .copy(); + boolean empty = stackInSlot.isEmpty(); + + if (empty && editingIndex != -1) + schedule.remove(editingIndex); + + if (!empty) { + String value = editorEditBox.getValue(); + stackInSlot.setHoverName(value.isBlank() ? null : Component.literal(value)); + + if (editingIndex == -1) + schedule.add(stackInSlot); + else + schedule.set(editingIndex, stackInSlot); + } + + AllPackets.getChannel() + .sendToServer(new GhostItemSubmitPacket(ItemStack.EMPTY, 0)); + + editingItem = null; + editorConfirm = null; + editorEditBox = null; + menu.slotsActive = false; + init(); + } + + @Override + protected void containerTick() { + super.containerTick(); + scroll.tickChaser(); + if (editorEditBox == null) + return; + if (!editorEditBox.getValue() + .equals(CreateLang.translate("gui.stock_ticker.new_category") + .string())) + return; + if (menu.proxyInventory.getStackInSlot(0) + .hasCustomHoverName()) + editorEditBox.setValue(menu.proxyInventory.getStackInSlot(0) + .getHoverName() + .getString()); + } + + @Override + public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + partialTicks = minecraft.getFrameTime(); + + if (menu.slotsActive) + super.render(graphics, mouseX, mouseY, partialTicks); + else { + renderBackground(graphics); + renderBg(graphics, partialTicks, mouseX, mouseY); + for (Renderable widget : this.renderables) + widget.render(graphics, mouseX, mouseY, partialTicks); + renderForeground(graphics, mouseX, mouseY, partialTicks); + } + } + + protected void renderCategories(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + PoseStack matrixStack = graphics.pose(); + UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer); + + int yOffset = 25; + List entries = schedule; + float scrollOffset = -scroll.getValue(partialTicks); + + for (int i = 0; i <= entries.size(); i++) { + startStencil(graphics, leftPos + 3, topPos + 16, 184, + 3 + AllGuiTextures.STOCK_KEEPER_CATEGORY.getHeight() * slices); + matrixStack.pushPose(); + matrixStack.translate(0, scrollOffset, 0); + + if (i == entries.size()) { + AllGuiTextures.STOCK_KEEPER_CATEGORY_NEW.render(graphics, leftPos + 7, topPos + yOffset); + matrixStack.popPose(); + endStencil(); + break; + } + + ItemStack scheduleEntry = entries.get(i); + int cardY = yOffset; + int cardHeight = renderScheduleEntry(graphics, i, scheduleEntry, cardY, mouseX, mouseY, partialTicks); + yOffset += cardHeight; + + matrixStack.popPose(); + endStencil(); + } + + UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget()); + } + + public int renderScheduleEntry(GuiGraphics graphics, int i, ItemStack entry, int yOffset, int mouseX, int mouseY, + float partialTicks) { + int cardWidth = CARD_WIDTH; + int cardHeader = CARD_HEADER; + int cardHeight = cardHeader; + + PoseStack matrixStack = graphics.pose(); + matrixStack.pushPose(); + matrixStack.translate(leftPos + 7, topPos + yOffset, 0); + + AllGuiTextures.STOCK_KEEPER_CATEGORY_ENTRY.render(graphics, 0, 0); + + if (i > 0) + AllGuiTextures.STOCK_KEEPER_CATEGORY_UP.render(graphics, cardWidth + 12, cardHeader - 18); + if (i < schedule.size() - 1) + AllGuiTextures.STOCK_KEEPER_CATEGORY_DOWN.render(graphics, cardWidth + 12, cardHeader - 9); + + graphics.renderItem(entry, 14, 1); + graphics.drawString(font, + entry.isEmpty() ? CreateLang.translate("gui.stock_ticker.empty_category_name_placeholder") + .string() + : entry.getHoverName() + .getString(20) + .stripTrailing() + + (entry.getHoverName() + .getString() + .length() > 20 ? "..." : ""), + 35, 5, 0x656565, false); + + matrixStack.popPose(); + return cardHeight; + } + + private Component clickToEdit = CreateLang.translateDirect("gui.schedule.lmb_edit") + .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC); + + public boolean action(@Nullable GuiGraphics graphics, double mouseX, double mouseY, int click) { + if (editingItem != null) + return false; + + int mx = (int) mouseX; + int my = (int) mouseY; + int x = mx - leftPos - 20; + int y = my - topPos - 24; + if (x < 0 || x >= 196) + return false; + if (y < 0 || y >= 143) + return false; + y += scroll.getValue(0); + + List entries = schedule; + for (int i = 0; i < entries.size(); i++) { + ItemStack entry = entries.get(i); + int cardHeight = CARD_HEADER; + + if (y >= cardHeight) { + y -= cardHeight; + if (y < 0) + return false; + continue; + } + + int fieldSize = 140; + if (x > 0 && x <= fieldSize && y > 0 && y <= 16) { + List components = new ArrayList<>(); + components + .add(entry.isEmpty() ? CreateLang.translate("gui.stock_ticker.empty_category_name_placeholder") + .component() : entry.getHoverName()); + components.add(clickToEdit); + renderActionTooltip(graphics, components, mx, my); + if (click == 0) + startEditing(i); + return true; + } + + if (x > fieldSize && x <= fieldSize + 16 && y > 0 && y <= 16) { + renderActionTooltip(graphics, ImmutableList.of(CreateLang.translate("gui.stock_ticker.delete_category") + .component()), mx, my); + if (click == 0) { + if (!entry.isEmpty()) + AllPackets.getChannel() + .sendToServer(new StockKeeperCategoryRefundPacket(menu.contentHolder.getBlockPos(), entry)); + entries.remove(entry); + init(); + } + return true; + } + + if (x > 158 && x < 170) { + if (y > 2 && y <= 10 && i > 0) { + renderActionTooltip(graphics, + ImmutableList.of(CreateLang.translateDirect("gui.schedule.move_up"), + CreateLang.translate("gui.stock_ticker.shift_moves_top") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mx, my); + if (click == 0) { + entries.remove(entry); + entries.add(hasShiftDown() ? 0 : i - 1, entry); + init(); + } + return true; + } + if (y > 10 && y <= 22 && i < entries.size() - 1) { + renderActionTooltip(graphics, + ImmutableList.of(CreateLang.translateDirect("gui.schedule.move_down"), + CreateLang.translate("gui.stock_ticker.shift_moves_bottom") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mx, my); + if (click == 0) { + entries.remove(entry); + entries.add(hasShiftDown() ? entries.size() : i + 1, entry); + init(); + } + return true; + } + } + + x -= 18; + y -= 28; + + if (x < 0 || y < 0 || x > 160) + return false; + } + + if (x > 0 && x <= 16 && y > 0 && y <= 16) { + renderActionTooltip(graphics, ImmutableList.of(CreateLang.translate("gui.stock_ticker.new_category") + .component()), mx, my); + if (click == 0) { + playUiSound(SoundEvents.UI_BUTTON_CLICK.get(), 1f, 1f); + startEditing(-1); + } + } + + return false; + } + + private void renderActionTooltip(@Nullable GuiGraphics graphics, List tooltip, int mx, int my) { + if (graphics != null) + graphics.renderTooltip(font, tooltip, Optional.empty(), mx, my); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + if (editorConfirm != null && editorConfirm.isMouseOver(pMouseX, pMouseY)) { + stopEditing(); + return true; + } + if (action(null, pMouseX, pMouseY, pButton)) { + playUiSound(SoundEvents.UI_BUTTON_CLICK.get(), 1f, 1f); + return true; + } + + boolean wasNotFocused = editorEditBox != null && !editorEditBox.isFocused(); + boolean mouseClicked = super.mouseClicked(pMouseX, pMouseY, pButton); + + if (editorEditBox != null && editorEditBox.isMouseOver(pMouseX, pMouseY) && wasNotFocused) { + editorEditBox.moveCursorToEnd(); + editorEditBox.setHighlightPos(0); + } + + return mouseClicked; + } + + @Override + public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { + if (editingItem == null) + return super.keyPressed(pKeyCode, pScanCode, pModifiers); + + InputConstants.Key mouseKey = InputConstants.getKey(pKeyCode, pScanCode); + boolean hitEscape = pKeyCode == GLFW.GLFW_KEY_ESCAPE; + boolean hitEnter = getFocused() instanceof EditBox && (pKeyCode == 257 || pKeyCode == 335); + boolean hitE = getFocused() == null && minecraft.options.keyInventory.isActiveAndMatches(mouseKey); + if (hitE || hitEnter || hitEscape) { + stopEditing(); + return true; + } + + return super.keyPressed(pKeyCode, pScanCode, pModifiers); + } + + @Override + public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) { + if (editingItem != null) + return super.mouseScrolled(pMouseX, pMouseY, pDelta); + + float chaseTarget = scroll.getChaseTarget(); + float max = 40 - (3 + AllGuiTextures.STOCK_KEEPER_CATEGORY.getHeight() * slices); + max += schedule.size() * CARD_HEADER + 24; + if (max > 0) { + chaseTarget -= pDelta * 12; + chaseTarget = Mth.clamp(chaseTarget, 0, max); + scroll.chase((int) chaseTarget, 0.7f, Chaser.EXP); + } else + scroll.chase(0, 0.7f, Chaser.EXP); + + return super.mouseScrolled(pMouseX, pMouseY, pDelta); + } + + @Override + protected void renderForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + super.renderForeground(graphics, mouseX, mouseY, partialTicks); + + GuiGameElement.of(AllBlocks.STOCK_TICKER.asStack()).at(leftPos + AllGuiTextures.STOCK_KEEPER_CATEGORY.getWidth() + 12, + topPos + imageHeight - 39, -190) + .scale(3) + .render(graphics); + + action(graphics, mouseX, mouseY, -1); + + if (editingItem == null) + return; + + if (hoveredSlot instanceof SlotItemHandler && hoveredSlot.getItem() + .isEmpty()) { + graphics.renderComponentTooltip(font, List.of(CreateLang.translate("gui.stock_ticker.category_filter") + .color(ScrollInput.HEADER_RGB) + .component(), + CreateLang.translate("gui.stock_ticker.category_filter_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.stock_ticker.category_filter_tip_1") + .style(ChatFormatting.GRAY) + .component()), + mouseX, mouseY); + } + + if (editorEditBox != null && editorEditBox.isHovered() && !editorEditBox.isFocused()) { + graphics.renderComponentTooltip(font, List.of(CreateLang.translate("gui.stock_ticker.category_name") + .color(ScrollInput.HEADER_RGB) + .component(), clickToEdit), mouseX, mouseY); + } + + } + + @Override + protected void renderBg(GuiGraphics graphics, float pPartialTick, int pMouseX, int pMouseY) { + int y = topPos; + AllGuiTextures.STOCK_KEEPER_CATEGORY_HEADER.render(graphics, leftPos, y); + y += AllGuiTextures.STOCK_KEEPER_CATEGORY_HEADER.getHeight(); + for (int i = 0; i < slices; i++) { + AllGuiTextures.STOCK_KEEPER_CATEGORY.render(graphics, leftPos, y); + y += AllGuiTextures.STOCK_KEEPER_CATEGORY.getHeight(); + } + AllGuiTextures.STOCK_KEEPER_CATEGORY_FOOTER.render(graphics, leftPos, y); + AllGuiTextures.STOCK_KEEPER_CATEGORY_SAYS.render(graphics, leftPos + imageWidth - 6, y + 7); + + FormattedCharSequence formattedcharsequence = menu.contentHolder.getBlockState() + .getBlock() + .getName() + .getVisualOrderText(); + + int center = leftPos + (AllGuiTextures.STOCK_KEEPER_CATEGORY.getWidth()) / 2; + graphics.drawString(font, formattedcharsequence, (float) (center - font.width(formattedcharsequence) / 2), + (float) topPos + 4, 0x3D3C48, false); + renderCategories(graphics, pMouseX, pMouseY, pPartialTick); + + if (editingItem == null) + return; + + graphics.fillGradient(0, 0, this.width, this.height, -1072689136, -804253680); + + y = topPos - 5; + AllGuiTextures.STOCK_KEEPER_CATEGORY_HEADER.render(graphics, leftPos, y); + y += AllGuiTextures.STOCK_KEEPER_CATEGORY_HEADER.getHeight(); + AllGuiTextures.STOCK_KEEPER_CATEGORY_EDIT.render(graphics, leftPos, y); + y += AllGuiTextures.STOCK_KEEPER_CATEGORY_EDIT.getHeight(); + AllGuiTextures.STOCK_KEEPER_CATEGORY_FOOTER.render(graphics, leftPos, y); + + renderPlayerInventory(graphics, leftPos + 10, topPos + 88); + + formattedcharsequence = CreateLang.translate("gui.stock_ticker.category_editor") + .component() + .getVisualOrderText(); + graphics.drawString(font, formattedcharsequence, (float) (center - font.width(formattedcharsequence) / 2), + (float) topPos - 1, 0x3D3C48, false); + } + + @Override + public void removed() { + super.removed(); + AllPackets.getChannel() + .sendToServer(new StockKeeperCategoryEditPacket(menu.contentHolder.getBlockPos(), schedule)); + } + + @Override + protected List getTooltipFromContainerItem(ItemStack pStack) { + List tooltip = super.getTooltipFromContainerItem(pStack); + if (!(hoveredSlot instanceof SlotItemHandler)) + return tooltip; + if (!tooltip.isEmpty()) + tooltip.set(0, CreateLang.translate("gui.stock_ticker.category_filter") + .color(ScrollInput.HEADER_RGB) + .component()); + return tooltip; + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + + public Font getFont() { + return font; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperLockPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperLockPacket.java new file mode 100644 index 0000000000..7edc6a12d8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperLockPacket.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.packagerLink.LogisticsNetwork; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public class StockKeeperLockPacket extends BlockEntityConfigurationPacket { + + private boolean lock; + + public StockKeeperLockPacket(BlockPos pos, boolean lock) { + super(pos); + this.lock = lock; + } + + public StockKeeperLockPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBoolean(lock); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + lock = buffer.readBoolean(); + } + + @Override + protected void applySettings(StockTickerBlockEntity be) {} + + @Override + protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { + if (!be.behaviour.mayAdministrate(player)) + return; + LogisticsNetwork network = Create.LOGISTICS.logisticsNetworks.get(be.behaviour.freqId); + if (network != null) { + network.locked = lock; + Create.LOGISTICS.markDirty(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperRequestMenu.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperRequestMenu.java new file mode 100644 index 0000000000..dd9901823c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperRequestMenu.java @@ -0,0 +1,66 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.List; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.gui.menu.MenuBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; + +public class StockKeeperRequestMenu extends MenuBase { + + boolean isAdmin; + boolean isLocked; + + public Object screenReference; + + public StockKeeperRequestMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public StockKeeperRequestMenu(MenuType type, int id, Inventory inv, StockTickerBlockEntity contentHolder) { + super(type, id, inv, contentHolder); + } + + public static AbstractContainerMenu create(int pContainerId, Inventory pPlayerInventory, + StockTickerBlockEntity stockTickerBlockEntity) { + return new StockKeeperCategoryMenu(AllMenuTypes.STOCK_KEEPER_REQUEST.get(), pContainerId, pPlayerInventory, + stockTickerBlockEntity); + } + + @Override + protected StockTickerBlockEntity createOnClient(FriendlyByteBuf extraData) { + isAdmin = extraData.readBoolean(); + isLocked = extraData.readBoolean(); + if (Minecraft.getInstance().level + .getBlockEntity(extraData.readBlockPos()) instanceof StockTickerBlockEntity stbe) + return stbe; + return null; + } + + @Override + protected void initAndReadInventory(StockTickerBlockEntity contentHolder) {} + + @Override + public void initializeContents(int pStateId, List pItems, ItemStack pCarried) {} + + @Override + protected void addSlots() { + addPlayerSlots(-1000, 0); + } + + @Override + protected void saveData(StockTickerBlockEntity contentHolder) {} + + @Override + public ItemStack quickMoveStack(Player pPlayer, int pIndex) { + return ItemStack.EMPTY; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperRequestScreen.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperRequestScreen.java new file mode 100644 index 0000000000..cc2c205d1b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperRequestScreen.java @@ -0,0 +1,1587 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.platform.Lighting; +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.equipment.clipboard.ClipboardEntry; +import com.simibubi.create.content.logistics.AddressEditBox; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelScreen; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlockEntity; +import com.simibubi.create.content.processing.burner.BlazeBurnerRenderer; +import com.simibubi.create.content.trains.station.NoShadowFontWrapper; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.ScreenWithStencils; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.utility.CreateLang; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.gui.UIRenderHelper; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.theme.Color; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.screens.inventory.InventoryScreen; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.phys.AABB; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.network.simple.SimpleChannel; +import net.minecraftforge.registries.ForgeRegistries; + +public class StockKeeperRequestScreen extends AbstractSimiContainerScreen + implements ScreenWithStencils { + + public static class CategoryEntry { + boolean hidden; + String name; + int y; + int targetBECategory; + + public CategoryEntry(int targetBECategory, String name, int y) { + this.targetBECategory = targetBECategory; + this.name = name; + hidden = false; + this.y = y; + } + } + + ; + + private static final AllGuiTextures NUMBERS = AllGuiTextures.NUMBERS; + private static final AllGuiTextures HEADER = AllGuiTextures.STOCK_KEEPER_REQUEST_HEADER; + private static final AllGuiTextures BODY = AllGuiTextures.STOCK_KEEPER_REQUEST_BODY; + private static final AllGuiTextures FOOTER = AllGuiTextures.STOCK_KEEPER_REQUEST_FOOTER; + + StockTickerBlockEntity blockEntity; + public LerpedFloat itemScroll; + + final int rows = 9; + final int cols = 9; + final int rowHeight = 20; + final int colWidth = 20; + final Couple noneHovered = Couple.create(-1, -1); + int itemsX; + int itemsY; + int orderY; + int lockX; + int lockY; + int windowWidth; + int windowHeight; + + public EditBox searchBox; + EditBox addressBox; + + int emptyTicks = 0; + int successTicks = 0; + + public List> currentItemSource; + public List> displayedItems; + public List categories; + + public List itemsToOrder; + public List recipesToOrder; + + WeakReference stockKeeper; + WeakReference blaze; + + boolean encodeRequester; // Redstone requesters + ItemStack itemToProgram; + List> clipboardItem; + + private boolean isAdmin; + private boolean isLocked; + private boolean scrollHandleActive; + + public boolean refreshSearchNextTick; + public boolean moveToTopNextTick; + private List extraAreas = Collections.emptyList(); + + private Set hiddenCategories; + private InventorySummary forcedEntries; + private boolean canRequestCraftingPackage; + + public StockKeeperRequestScreen(StockKeeperRequestMenu container, Inventory inv, Component title) { + super(container, inv, title); + displayedItems = new ArrayList<>(); + itemsToOrder = new ArrayList<>(); + recipesToOrder = new ArrayList<>(); + categories = new ArrayList<>(); + isAdmin = menu.isAdmin; + isLocked = menu.isLocked; + blockEntity = container.contentHolder; + blockEntity.lastClientsideStockSnapshot = null; + blockEntity.ticksSinceLastUpdate = 15; + emptyTicks = 0; + successTicks = 0; + itemScroll = LerpedFloat.linear() + .startWithValue(0); + stockKeeper = new WeakReference<>(null); + blaze = new WeakReference<>(null); + refreshSearchNextTick = false; + moveToTopNextTick = false; + menu.screenReference = this; + canRequestCraftingPackage = false; + hiddenCategories = + new HashSet<>(blockEntity.hiddenCategoriesByPlayer.getOrDefault(menu.player.getUUID(), List.of())); + + forcedEntries = new InventorySummary(); + + itemToProgram = menu.player.getMainHandItem(); + encodeRequester = + AllItemTags.TABLE_CLOTHS.matches(itemToProgram) || AllBlocks.REDSTONE_REQUESTER.isIn(itemToProgram); + + if (AllBlocks.CLIPBOARD.isIn(itemToProgram)) { + clipboardItem = ClipboardEntry.readAll(itemToProgram); + boolean anyItems = false; + for (List list : clipboardItem) + for (ClipboardEntry entry : list) + if (!entry.icon.isEmpty()) + anyItems = true; + if (!anyItems) + clipboardItem = null; + } + + // Find the keeper for rendering + for (int yOffset : Iterate.zeroAndOne) { + for (Direction side : Iterate.horizontalDirections) { + BlockPos seatPos = blockEntity.getBlockPos() + .below(yOffset) + .relative(side); + for (SeatEntity seatEntity : blockEntity.getLevel() + .getEntitiesOfClass(SeatEntity.class, new AABB(seatPos))) + if (!seatEntity.getPassengers() + .isEmpty() + && seatEntity.getPassengers() + .get(0) instanceof LivingEntity keeper) + stockKeeper = new WeakReference<>(keeper); + if (yOffset == 0 && blockEntity.getLevel() + .getBlockEntity(seatPos) instanceof BlazeBurnerBlockEntity bbbe) { + blaze = new WeakReference<>(bbbe); + return; + } + } + } + } + + @Override + protected void init() { + int appropriateHeight = Minecraft.getInstance() + .getWindow() + .getGuiScaledHeight() - 10; + appropriateHeight -= + Mth.positiveModulo(appropriateHeight - HEADER.getHeight() - FOOTER.getHeight(), BODY.getHeight()); + appropriateHeight = + Math.min(appropriateHeight, HEADER.getHeight() + FOOTER.getHeight() + BODY.getHeight() * 17); + + setWindowSize(windowWidth = 226, windowHeight = appropriateHeight); + super.init(); + clearWidgets(); + + int x = getGuiLeft(); + int y = getGuiTop(); + + itemsX = x + (windowWidth - cols * colWidth) / 2 + 1; + itemsY = y + 33; + orderY = y + windowHeight - 72; + lockX = x + 186; + lockY = y + 18; + + MutableComponent searchLabel = CreateLang.translateDirect("gui.stock_keeper.search_items"); + searchBox = new EditBox(new NoShadowFontWrapper(font), x + 71, y + 22, 100, 9, searchLabel); + searchBox.setMaxLength(50); + searchBox.setBordered(false); + searchBox.setTextColor(0x4A2D31); + addWidget(searchBox); + + boolean initial = addressBox == null; + String previouslyUsedAddress = initial ? blockEntity.previouslyUsedAddress : addressBox.getValue(); + addressBox = + new AddressEditBox(this, new NoShadowFontWrapper(font), x + 27, y + windowHeight - 36, 92, 10, true); + addressBox.setTextColor(0x714A40); + addressBox.setValue(previouslyUsedAddress); + addRenderableWidget(addressBox); + + extraAreas = new ArrayList<>(); + int leftHeight = 40; + int rightHeight = 50; + + LivingEntity keeper = stockKeeper.get(); + if (keeper != null && keeper.isAlive()) + leftHeight = (int) (Math.max(0, keeper.getBoundingBox() + .getYsize()) * 50); + + extraAreas.add(new Rect2i(0, y + windowHeight - 15 - leftHeight, x, height)); + if (encodeRequester) + extraAreas.add(new Rect2i(x + windowWidth, y + windowHeight - 15 - rightHeight, rightHeight + 10, rightHeight)); + + if (initial) { + playUiSound(SoundEvents.WOOD_HIT, 0.5f, 1.5f); + playUiSound(SoundEvents.BOOK_PAGE_TURN, 1, 1); + } + } + + private void refreshSearchResults(boolean scrollBackUp) { + displayedItems = Collections.emptyList(); + if (scrollBackUp) + itemScroll.startWithValue(0); + + if (currentItemSource == null) { + clampScrollBar(); + return; + } + + if (isSchematicListMode()) { + clampScrollBar(); + requestSchematicList(); + return; + } + + categories = new ArrayList<>(); + for (int i = 0; i < blockEntity.categories.size(); i++) { + ItemStack stack = blockEntity.categories.get(i); + CategoryEntry entry = new CategoryEntry(i, stack.isEmpty() ? "" + : stack.getHoverName() + .getString(), + 0); + entry.hidden = hiddenCategories.contains(i); + categories.add(entry); + } + + CategoryEntry unsorted = new CategoryEntry(-1, CreateLang.translate("gui.stock_keeper.unsorted_category") + .string(), 0); + unsorted.hidden = hiddenCategories.contains(-1); + categories.add(unsorted); + + String valueWithPrefix = searchBox.getValue(); + boolean anyItemsInCategory = false; + + // Nothing is being filtered out + if (valueWithPrefix.isBlank()) { + displayedItems = new ArrayList<>(currentItemSource); + + int categoryY = 0; + for (int categoryIndex = 0; categoryIndex < currentItemSource.size(); categoryIndex++) { + categories.get(categoryIndex).y = categoryY; + List displayedItemsInCategory = displayedItems.get(categoryIndex); + if (displayedItemsInCategory.isEmpty()) + continue; + if (categoryIndex < currentItemSource.size() - 1) + anyItemsInCategory = true; + + categoryY += rowHeight; + if (!categories.get(categoryIndex).hidden) + categoryY += Math.ceil(displayedItemsInCategory.size() / (float) cols) * rowHeight; + } + + if (!anyItemsInCategory) + categories.clear(); + + clampScrollBar(); + updateCraftableAmounts(); + return; + } + + // Filter by search string + boolean modSearch = false; + boolean tagSearch = false; + if ((modSearch = valueWithPrefix.startsWith("@")) || (tagSearch = valueWithPrefix.startsWith("#"))) + valueWithPrefix = valueWithPrefix.substring(1); + final String value = valueWithPrefix.toLowerCase(Locale.ROOT); + + displayedItems = new ArrayList<>(); + currentItemSource.forEach($ -> displayedItems.add(new ArrayList<>())); + + int categoryY = 0; + for (int categoryIndex = 0; categoryIndex < displayedItems.size(); categoryIndex++) { + List category = currentItemSource.get(categoryIndex); + categories.get(categoryIndex).y = categoryY; + + if (displayedItems.size() <= categoryIndex) + break; + + List displayedItemsInCategory = displayedItems.get(categoryIndex); + for (BigItemStack entry : category) { + ItemStack stack = entry.stack; + + if (modSearch) { + if (ForgeRegistries.ITEMS.getKey(stack.getItem()) + .getNamespace() + .contains(value)) { + displayedItemsInCategory.add(entry); + } + continue; + } + + if (tagSearch) { + if (stack.getTags() + .anyMatch(key -> key.location() + .toString() + .contains(value))) + displayedItemsInCategory.add(entry); + continue; + } + + if (stack.getHoverName() + .getString() + .toLowerCase(Locale.ROOT) + .contains(value) + || ForgeRegistries.ITEMS.getKey(stack.getItem()) + .getPath() + .contains(value)) { + displayedItemsInCategory.add(entry); + continue; + } + } + + if (displayedItemsInCategory.isEmpty()) + continue; + if (categoryIndex < currentItemSource.size() - 1) + anyItemsInCategory = true; + + categoryY += rowHeight; + + if (!categories.get(categoryIndex).hidden) + categoryY += Math.ceil(displayedItemsInCategory.size() / (float) cols) * rowHeight; + } + + if (!anyItemsInCategory) + categories.clear(); + + clampScrollBar(); + updateCraftableAmounts(); + } + + @Override + protected void containerTick() { + super.containerTick(); + addressBox.tick(); + + if (!forcedEntries.isEmpty()) { + InventorySummary summary = blockEntity.getLastClientsideStockSnapshotAsSummary(); + for (BigItemStack stack : forcedEntries.getStacks()) { + int limitedAmount = -stack.count - 1; + int actualAmount = summary.getCountOf(stack.stack); + if (actualAmount <= limitedAmount) + forcedEntries.erase(stack.stack); + } + } + + boolean allEmpty = true; + for (List list : displayedItems) + allEmpty &= list.isEmpty(); + if (allEmpty) + emptyTicks++; + else + emptyTicks = 0; + + if (successTicks > 0 && itemsToOrder.isEmpty()) + successTicks++; + else + successTicks = 0; + + List> clientStockSnapshot = blockEntity.getClientStockSnapshot(); + if (clientStockSnapshot != currentItemSource) { + currentItemSource = clientStockSnapshot; + refreshSearchResults(false); + revalidateOrders(); + } + + if (refreshSearchNextTick) { + refreshSearchNextTick = false; + refreshSearchResults(moveToTopNextTick); + } + + itemScroll.tickChaser(); + + if (Math.abs(itemScroll.getValue() - itemScroll.getChaseTarget()) < 1 / 16f) + itemScroll.setValue(itemScroll.getChaseTarget()); + + if (blockEntity.ticksSinceLastUpdate > 15) + blockEntity.refreshClientStockSnapshot(); + + LivingEntity keeper = stockKeeper.get(); + BlazeBurnerBlockEntity blazeKeeper = blaze.get(); + if ((keeper == null || !keeper.isAlive()) && (blazeKeeper == null || blazeKeeper.isRemoved())) + menu.player.closeContainer(); + } + + @Override + public void renderBackground(GuiGraphics graphics) { + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(0, 0, -300); + super.renderBackground(graphics); + ms.popPose(); + } + + @Override + protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { + if (this != minecraft.screen) + return; // stencil buffer does not cooperate with ponders gui fade out + + PoseStack ms = graphics.pose(); + float currentScroll = itemScroll.getValue(partialTicks); + Couple hoveredSlot = getHoveredSlot(mouseX, mouseY); + + int x = getGuiLeft(); + int y = getGuiTop(); + + // BG + HEADER.render(graphics, x - 15, y); + y += HEADER.getHeight(); + for (int i = 0; i < (windowHeight - HEADER.getHeight() - FOOTER.getHeight()) / BODY.getHeight(); i++) { + BODY.render(graphics, x - 15, y); + y += BODY.getHeight(); + } + FOOTER.render(graphics, x - 15, y); + y = getGuiTop(); + + // Render text input hints + if (addressBox.getValue() + .isBlank()) + graphics.drawString(font, addressBox.getMessage(), addressBox.getX(), addressBox.getY(), 0x88dddddd); + + // Render keeper + int entitySizeOffset = 0; + LivingEntity keeper = stockKeeper.get(); + if (keeper != null && keeper.isAlive()) { + ms.pushPose(); + ms.translate(0, 0, -300); + entitySizeOffset = (int) (Math.max(0, keeper.getBoundingBox() + .getXsize() - 1) * 50); + int entityX = x - 35 - entitySizeOffset; + int entityY = y + windowHeight - 17; + InventoryScreen.renderEntityInInventoryFollowsMouse(graphics, entityX, entityY, 50, entityX - mouseX, + Mth.clamp(entityY - mouseY, -50, 10), keeper); + ms.popPose(); + } + + BlazeBurnerBlockEntity keeperBE = blaze.get(); + if (keeperBE != null && !keeperBE.isRemoved()) { + ms.pushPose(); + int entityX = x - 35; + int entityY = y + windowHeight - 23; + ms.translate(entityX, entityY, -100); + ms.mulPose(Axis.XP.rotationDegrees(-22.5f)); + ms.mulPose(Axis.YP.rotationDegrees(-45)); + ms.scale(48, -48, 48); + float animation = keeperBE.headAnimation.getValue(AnimationTickHolder.getPartialTicks()) * .175f; + float horizontalAngle = AngleHelper.rad(270); + HeatLevel heatLevel = keeperBE.getHeatLevelForRender(); + boolean canDrawFlame = heatLevel.isAtLeast(HeatLevel.FADING); + boolean drawGoggles = keeperBE.goggles; + PartialModel drawHat = AllPartialModels.LOGISTICS_HAT; + int hashCode = keeperBE.hashCode(); + Lighting.setupForEntityInInventory(); + + VertexConsumer cutout = graphics.bufferSource().getBuffer(RenderType.cutoutMipped()); + CachedBuffers.partial(AllPartialModels.BLAZE_CAGE, keeperBE.getBlockState()) + .rotateCentered(horizontalAngle + Mth.PI, Direction.UP) + .light(LightTexture.FULL_BRIGHT) + .renderInto(ms, cutout); + + BlazeBurnerRenderer.renderShared(ms, null, graphics.bufferSource(), minecraft.level, + keeperBE.getBlockState(), heatLevel, animation, horizontalAngle, canDrawFlame, drawGoggles, drawHat, + hashCode); + Lighting.setupFor3DItems(); + ms.popPose(); + } + + // Render static item icons + if (encodeRequester) { + ms.pushPose(); + ms.translate(x + windowWidth + 5, y + windowHeight - 70, 0); + ms.scale(3.5f, 3.5f, 3.5f); + GuiGameElement.of(itemToProgram) + .render(graphics); + ms.popPose(); + } + + // Render ordered items + for (int index = 0; index < cols; index++) { + if (itemsToOrder.size() <= index) + break; + + BigItemStack entry = itemsToOrder.get(index); + boolean isStackHovered = index == hoveredSlot.getSecond() && hoveredSlot.getFirst() == -1; + + ms.pushPose(); + ms.translate(itemsX + index * colWidth, orderY, 0); + renderItemEntry(graphics, 1, entry, isStackHovered, true); + ms.popPose(); + } + + if (itemsToOrder.size() > 9) { + graphics.drawString(font, Component.literal("[+" + (itemsToOrder.size() - 9) + "]"), x + windowWidth - 40, + orderY + 21, 0xF8F8EC); + } + + boolean justSent = itemsToOrder.isEmpty() && successTicks > 0; + if (isConfirmHovered(mouseX, mouseY) && !justSent) + AllGuiTextures.STOCK_KEEPER_REQUEST_SEND_HOVER.render(graphics, x + windowWidth - 81, + y + windowHeight - 41); + + MutableComponent headerTitle = CreateLang.translate("gui.stock_keeper.title") + .component(); + graphics.drawString(font, headerTitle, x + windowWidth / 2 - font.width(headerTitle) / 2, y + 4, 0x714A40, + false); + MutableComponent component = + CreateLang.translate(encodeRequester ? "gui.stock_keeper.configure" : "gui.stock_keeper.send") + .component(); + + if (justSent) { + float alpha = Mth.clamp((successTicks + partialTicks - 5f) / 5f, 0f, 1f); + ms.pushPose(); + ms.translate(alpha * alpha * 50, 0, 0); + if (successTicks < 10) + graphics.drawString(font, component, x + windowWidth - 42 - font.width(component) / 2, + y + windowHeight - 35, new Color(0x252525).setAlpha(1 - alpha * alpha) + .getRGB(), + false); + ms.popPose(); + + } else { + graphics.drawString(font, component, x + windowWidth - 42 - font.width(component) / 2, + y + windowHeight - 35, 0x252525, false); + } + + // Request just sent + if (justSent) { + Component msg = CreateLang.translateDirect("gui.stock_keeper.request_sent"); + float alpha = Mth.clamp((successTicks + partialTicks - 10f) / 5f, 0f, 1f); + int msgX = x + windowWidth / 2 - (font.width(msg) + 10) / 2; + int msgY = orderY + 5; + if (alpha > 0) { + int c3 = new Color(0x8C5D4B).setAlpha(alpha) + .getRGB(); + int w = font.width(msg) + 14; + AllGuiTextures.STOCK_KEEPER_REQUEST_BANNER_L.render(graphics, msgX - 8, msgY - 4); + UIRenderHelper.drawStretched(graphics, msgX, msgY - 4, w, 16, 0, + AllGuiTextures.STOCK_KEEPER_REQUEST_BANNER_M); + AllGuiTextures.STOCK_KEEPER_REQUEST_BANNER_R.render(graphics, msgX + font.width(msg) + 10, msgY - 4); + graphics.drawString(font, msg, msgX + 5, msgY, c3, false); + } + } + + int itemWindowX = x + 21; + int itemWindowX2 = itemWindowX + 184; + int itemWindowY = y + 17; + int itemWindowY2 = y + windowHeight - 80; + + UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer); + startStencil(graphics, itemWindowX - 5, itemWindowY, itemWindowX2 - itemWindowX + 10, + itemWindowY2 - itemWindowY); + + ms.pushPose(); + ms.translate(0, -currentScroll * rowHeight, 0); + + // BG + for (int sliceY = -2; sliceY < getMaxScroll() * rowHeight + windowHeight - 72; sliceY += + AllGuiTextures.STOCK_KEEPER_REQUEST_BG.getHeight()) { + if (sliceY - currentScroll * rowHeight < -20) + continue; + if (sliceY - currentScroll * rowHeight > windowHeight - 72) + continue; + AllGuiTextures.STOCK_KEEPER_REQUEST_BG.render(graphics, x + 22, y + sliceY + 18); + } + + // Search bar + AllGuiTextures.STOCK_KEEPER_REQUEST_SEARCH.render(graphics, x + 42, searchBox.getY() - 5); + searchBox.render(graphics, mouseX, mouseY, partialTicks); + if (searchBox.getValue() + .isBlank() && !searchBox.isFocused()) + graphics.drawString(font, searchBox.getMessage(), + x + windowWidth / 2 - font.width(searchBox.getMessage()) / 2, searchBox.getY(), 0xff4A2D31, false); + + // Something isnt right + boolean allEmpty = true; + for (List list : displayedItems) + allEmpty &= list.isEmpty(); + if (allEmpty) { + Component msg = getTroubleshootingMessage(); + float alpha = Mth.clamp((emptyTicks - 10f) / 5f, 0f, 1f); + if (alpha > 0) { + List split = font.split(msg, 160); + for (int i = 0; i < split.size(); i++) { + FormattedCharSequence sequence = split.get(i); + int lineWidth = font.width(sequence); + graphics.drawString(font, sequence, x + windowWidth / 2 - lineWidth / 2 + 1, + itemsY + 20 + 1 + i * (font.lineHeight + 1), new Color(0x4A2D31).setAlpha(alpha) + .getRGB(), + false); + graphics.drawString(font, sequence, x + windowWidth / 2 - lineWidth / 2, + itemsY + 20 + i * (font.lineHeight + 1), new Color(0xF8F8EC).setAlpha(alpha) + .getRGB(), + false); + } + } + } + + // Items + for (int categoryIndex = 0; categoryIndex < displayedItems.size(); categoryIndex++) { + List category = displayedItems.get(categoryIndex); + CategoryEntry categoryEntry = categories.isEmpty() ? null : categories.get(categoryIndex); + int categoryY = categories.isEmpty() ? 0 : categoryEntry.y; + if (category.isEmpty()) + continue; + + if (!categories.isEmpty()) { + (categoryEntry.hidden ? AllGuiTextures.STOCK_KEEPER_CATEGORY_HIDDEN + : AllGuiTextures.STOCK_KEEPER_CATEGORY_SHOWN).render(graphics, itemsX, itemsY + categoryY + 6); + graphics.drawString(font, categoryEntry.name, itemsX + 10, itemsY + categoryY + 8, 0x4A2D31, false); + graphics.drawString(font, categoryEntry.name, itemsX + 9, itemsY + categoryY + 7, 0xF8F8EC, false); + if (categoryEntry.hidden) + continue; + } + + for (int index = 0; index < category.size(); index++) { + int pY = itemsY + categoryY + (categories.isEmpty() ? 4 : rowHeight) + (index / cols) * rowHeight; + float cullY = pY - currentScroll * rowHeight; + + if (cullY < y) + continue; + if (cullY > y + windowHeight - 72) + break; + + boolean isStackHovered = index == hoveredSlot.getSecond() && categoryIndex == hoveredSlot.getFirst(); + BigItemStack entry = category.get(index); + + ms.pushPose(); + ms.translate(itemsX + (index % cols) * colWidth, pY, 0); + renderItemEntry(graphics, 1, entry, isStackHovered, false); + ms.popPose(); + } + } + + // Render lock option + if (isAdmin) + (isLocked ? AllGuiTextures.STOCK_KEEPER_REQUEST_LOCKED : AllGuiTextures.STOCK_KEEPER_REQUEST_UNLOCKED) + .render(graphics, lockX, lockY); + + ms.popPose(); + endStencil(); + + // Scroll bar + int windowH = windowHeight - 92; + int totalH = getMaxScroll() * rowHeight + windowH; + int barSize = Math.max(5, Mth.floor((float) windowH / totalH * (windowH - 2))); + if (barSize < windowH - 2) { + int barX = itemsX + cols * colWidth; + int barY = y + 15; + ms.pushPose(); + ms.translate(0, (currentScroll * rowHeight) / totalH * (windowH - 2), 0); + AllGuiTextures pad = AllGuiTextures.STOCK_KEEPER_REQUEST_SCROLL_PAD; + graphics.blit(pad.location, barX, barY, pad.getWidth(), barSize, pad.getStartX(), pad.getStartY(), + pad.getWidth(), pad.getHeight(), 256, 256); + AllGuiTextures.STOCK_KEEPER_REQUEST_SCROLL_TOP.render(graphics, barX, barY); + if (barSize > 16) + AllGuiTextures.STOCK_KEEPER_REQUEST_SCROLL_MID.render(graphics, barX, barY + barSize / 2 - 4); + AllGuiTextures.STOCK_KEEPER_REQUEST_SCROLL_BOT.render(graphics, barX, barY + barSize - 5); + ms.popPose(); + } + + // Render JEI imported + if (recipesToOrder.size() > 0) { + int jeiX = x + (windowWidth - colWidth * recipesToOrder.size()) / 2 + 1; + int jeiY = orderY - 31; + ms.pushPose(); + ms.translate(jeiX, jeiY, 200); + int xoffset = -3; + AllGuiTextures.STOCK_KEEPER_REQUEST_BLUEPRINT_LEFT.render(graphics, xoffset, -3); + xoffset += 10; + for (int i = 0; i <= (recipesToOrder.size() - 1) * 5; i++) { + AllGuiTextures.STOCK_KEEPER_REQUEST_BLUEPRINT_MIDDLE.render(graphics, xoffset, -3); + xoffset += 4; + } + AllGuiTextures.STOCK_KEEPER_REQUEST_BLUEPRINT_RIGHT.render(graphics, xoffset, -3); + + for (int index = 0; index < recipesToOrder.size(); index++) { + CraftableBigItemStack craftableBigItemStack = recipesToOrder.get(index); + boolean isStackHovered = index == hoveredSlot.getSecond() && -2 == hoveredSlot.getFirst(); + ms.pushPose(); + ms.translate(index * colWidth, 0, 0); + renderItemEntry(graphics, 1, craftableBigItemStack, isStackHovered, true); + ms.popPose(); + } + + ms.popPose(); + } + + UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget()); + } + + @Override + protected void renderForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + super.renderForeground(graphics, mouseX, mouseY, partialTicks); + float currentScroll = itemScroll.getValue(partialTicks); + Couple hoveredSlot = getHoveredSlot(mouseX, mouseY); + + // Render tooltip of hovered item + if (hoveredSlot != noneHovered) { + int slot = hoveredSlot.getSecond(); + boolean recipeHovered = hoveredSlot.getFirst() == -2; + boolean orderHovered = hoveredSlot.getFirst() == -1; + BigItemStack entry = recipeHovered ? recipesToOrder.get(slot) + : orderHovered ? itemsToOrder.get(slot) + : displayedItems.get(hoveredSlot.getFirst()) + .get(slot); + + if (recipeHovered) { + ArrayList lines = + new ArrayList<>(entry.stack.getTooltipLines(minecraft.player, TooltipFlag.NORMAL)); + if (lines.size() > 0) + lines.set(0, CreateLang.translateDirect("gui.stock_keeper.craft", lines.get(0) + .copy())); + graphics.renderComponentTooltip(font, lines, mouseX, mouseY); + } else + graphics.renderTooltip(font, entry.stack, mouseX, mouseY); + } + + // Render tooltip of lock option + if (currentScroll < 1 && isAdmin && mouseX > lockX && mouseX <= lockX + 15 && mouseY > lockY + && mouseY <= lockY + 15) { + graphics.renderComponentTooltip(font, + List.of( + CreateLang.translate(isLocked ? "gui.stock_keeper.network_locked" : "gui.stock_keeper.network_open") + .component(), + CreateLang.translate("gui.stock_keeper.network_lock_tip") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.stock_keeper.network_lock_tip_1") + .style(ChatFormatting.GRAY) + .component(), + CreateLang.translate("gui.stock_keeper.network_lock_tip_2") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component()), + mouseX, mouseY); + } + } + + private void renderItemEntry(GuiGraphics graphics, float scale, BigItemStack entry, boolean isStackHovered, + boolean isRenderingOrders) { + + int customCount = entry.count; + if (!isRenderingOrders) { + BigItemStack order = getOrderForItem(entry.stack); + if (entry.count < BigItemStack.INF) { + int forcedCount = forcedEntries.getCountOf(entry.stack); + if (forcedCount != 0) + customCount = Math.min(customCount, -forcedCount - 1); + if (order != null) + customCount -= order.count; + customCount = Math.max(0, customCount); + } + AllGuiTextures.STOCK_KEEPER_REQUEST_SLOT.render(graphics, 0, 0); + } + + boolean craftable = entry instanceof CraftableBigItemStack; + PoseStack ms = graphics.pose(); + ms.pushPose(); + + float scaleFromHover = 1; + if (isStackHovered) + scaleFromHover += .075f; + + ms.translate((colWidth - 18) / 2.0, (rowHeight - 18) / 2.0, 0); + ms.translate(18 / 2.0, 18 / 2.0, 0); + ms.scale(scale, scale, scale); + ms.scale(scaleFromHover, scaleFromHover, scaleFromHover); + ms.translate(-18 / 2.0, -18 / 2.0, 0); + if (customCount != 0 || craftable) + GuiGameElement.of(entry.stack) + .render(graphics); + ms.popPose(); + + ms.pushPose(); + ms.translate(0, 0, 190); + if (customCount != 0 || craftable) + graphics.renderItemDecorations(font, entry.stack, 1, 1, ""); + ms.translate(0, 0, 10); + if (customCount > 1 || craftable) + drawItemCount(graphics, entry.count, customCount); + ms.popPose(); + } + + private void drawItemCount(GuiGraphics graphics, int count, int customCount) { + count = customCount; + String text = count >= 1000000 ? (count / 1000000) + "m" + : count >= 10000 ? (count / 1000) + "k" + : count >= 1000 ? ((count * 10) / 1000) / 10f + "k" : count >= 100 ? count + "" : " " + count; + + if (count >= BigItemStack.INF) + text = "+"; + + if (text.isBlank()) + return; + + int x = (int) Math.floor(-text.length() * 2.5); + for (char c : text.toCharArray()) { + int index = c - '0'; + int xOffset = index * 6; + int spriteWidth = NUMBERS.getWidth(); + + switch (c) { + case ' ': + x += 4; + continue; + case '.': + spriteWidth = 3; + xOffset = 60; + break; + case 'k': + xOffset = 64; + break; + case 'm': + spriteWidth = 7; + xOffset = 70; + break; + case '+': + spriteWidth = 9; + xOffset = 84; + break; + } + + RenderSystem.enableBlend(); + graphics.blit(NUMBERS.location, 14 + x, 10, 0, NUMBERS.getStartX() + xOffset, NUMBERS.getStartY(), + spriteWidth, NUMBERS.getHeight(), 256, 256); + x += spriteWidth - 1; + } + + } + + @Nullable + private BigItemStack getOrderForItem(ItemStack stack) { + for (BigItemStack entry : itemsToOrder) + if (ItemHandlerHelper.canItemStacksStack(stack, entry.stack)) + return entry; + return null; + } + + private void revalidateOrders() { + Set invalid = new HashSet<>(itemsToOrder); + InventorySummary summary = blockEntity.lastClientsideStockSnapshotAsSummary; + if (currentItemSource == null || summary == null) { + itemsToOrder.removeAll(invalid); + return; + } + for (BigItemStack entry : itemsToOrder) { + entry.count = Math.min(summary.getCountOf(entry.stack), entry.count); + if (entry.count > 0) + invalid.remove(entry); + } + + itemsToOrder.removeAll(invalid); + } + + private Couple getHoveredSlot(int x, int y) { + x += 1; + if (x < itemsX || x >= itemsX + cols * colWidth || isSchematicListMode()) + return noneHovered; + + // Ordered item is hovered + if (y >= orderY && y < orderY + rowHeight) { + int col = (x - itemsX) / colWidth; + if (itemsToOrder.size() <= col || col < 0) + return noneHovered; + return Couple.create(-1, col); + } + + // Ordered recipe is hovered + if (y >= orderY - 31 && y < orderY - 31 + rowHeight) { + int jeiX = getGuiLeft() + (windowWidth - colWidth * recipesToOrder.size()) / 2 + 1; + int col = Mth.floorDiv(x - jeiX, colWidth); + if (recipesToOrder.size() > col && col >= 0) + return Couple.create(-2, col); + } + + if (y < getGuiTop() + 16 || y > getGuiTop() + windowHeight - 80) + return noneHovered; + if (!itemScroll.settled()) + return noneHovered; + + int localY = y - itemsY; + + for (int categoryIndex = 0; categoryIndex < displayedItems.size(); categoryIndex++) { + CategoryEntry entry = categories.isEmpty() ? new CategoryEntry(0, "", 0) : categories.get(categoryIndex); + if (entry.hidden) + continue; + + int row = Mth.floor((localY - (categories.isEmpty() ? 4 : rowHeight) - entry.y) / (float) rowHeight + + itemScroll.getChaseTarget()); + + int col = (x - itemsX) / colWidth; + int slot = row * cols + col; + + if (slot < 0) + return noneHovered; + if (displayedItems.get(categoryIndex) + .size() <= slot) + continue; + + return Couple.create(categoryIndex, slot); + } + + return noneHovered; + } + + private boolean isConfirmHovered(int mouseX, int mouseY) { + int confirmX = getGuiLeft() + 143; + int confirmY = getGuiTop() + windowHeight - 39; + int confirmW = 78; + int confirmH = 18; + + if (mouseX < confirmX || mouseX >= confirmX + confirmW) + return false; + if (mouseY < confirmY || mouseY >= confirmY + confirmH) + return false; + return true; + } + + private Component getTroubleshootingMessage() { + if (currentItemSource == null) + return CreateLang.translate("gui.stock_keeper.checking_stocks") + .component(); + if (blockEntity.activeLinks == 0) + return CreateLang.translate("gui.stock_keeper.no_packagers_linked") + .component(); + if (currentItemSource.isEmpty()) + return CreateLang.translate("gui.stock_keeper.inventories_empty") + .component(); + if (isSchematicListMode()) + return CreateLang + .translate(itemsToOrder.isEmpty() ? "gui.stock_keeper.schematic_list.no_results" + : "gui.stock_keeper.schematic_list.requesting") + .component(); + return CreateLang.translate("gui.stock_keeper.no_search_results") + .component(); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + boolean lmb = pButton == GLFW.GLFW_MOUSE_BUTTON_LEFT; + boolean rmb = pButton == GLFW.GLFW_MOUSE_BUTTON_RIGHT; + + // Search + if (rmb && searchBox.isMouseOver(pMouseX, pMouseY)) { + searchBox.setValue(""); + refreshSearchNextTick = true; + moveToTopNextTick = true; + searchBox.setFocused(true); + return true; + } + + if (addressBox.isFocused()) { + if (addressBox.isHovered()) + return addressBox.mouseClicked(pMouseX, pMouseY, pButton); + addressBox.setFocused(false); + } + if (searchBox.isFocused()) { + if (searchBox.isHovered()) + return searchBox.mouseClicked(pMouseX, pMouseY, pButton); + searchBox.setFocused(false); + } + + // Scroll bar + int barX = itemsX + cols * colWidth - 1; + if (getMaxScroll() > 0 && lmb && pMouseX > barX && pMouseX <= barX + 8 && pMouseY > getGuiTop() + 15 + && pMouseY < getGuiTop() + windowHeight - 82) { + scrollHandleActive = true; + if (minecraft.isWindowActive()) + GLFW.glfwSetInputMode(minecraft.getWindow() + .getWindow(), 208897, GLFW.GLFW_CURSOR_HIDDEN); + return true; + } + + Couple hoveredSlot = getHoveredSlot((int) pMouseX, (int) pMouseY); + + // Lock + if (isAdmin && itemScroll.getChaseTarget() == 0 && lmb && pMouseX > lockX && pMouseX <= lockX + 15 + && pMouseY > lockY && pMouseY <= lockY + 15) { + isLocked = !isLocked; + AllPackets.getChannel() + .sendToServer(new StockKeeperLockPacket(blockEntity.getBlockPos(), isLocked)); + playUiSound(SoundEvents.UI_BUTTON_CLICK.get(), 1, 1); + return true; + } + + // Confirm + if (lmb && isConfirmHovered((int) pMouseX, (int) pMouseY)) { + sendIt(); + playUiSound(SoundEvents.UI_BUTTON_CLICK.get(), 1, 1); + return true; + } + + // Category hiding + int localY = (int) (pMouseY - itemsY); + if (itemScroll.settled() && lmb && !categories.isEmpty() && pMouseX >= itemsX + && pMouseX < itemsX + cols * colWidth && pMouseY >= getGuiTop() + 16 + && pMouseY <= getGuiTop() + windowHeight - 80) { + for (int categoryIndex = 0; categoryIndex < displayedItems.size(); categoryIndex++) { + CategoryEntry entry = categories.get(categoryIndex); + if (Mth.floor((localY - entry.y) / (float) rowHeight + itemScroll.getChaseTarget()) != 0) + continue; + if (displayedItems.get(categoryIndex) + .isEmpty()) + continue; + int indexOf = entry.targetBECategory; + if (indexOf >= blockEntity.categories.size()) + continue; + + if (!entry.hidden) { + hiddenCategories.add(indexOf); + playUiSound(SoundEvents.ITEM_FRAME_ROTATE_ITEM, 0.75f, 1.5f); + } + + else { + hiddenCategories.remove(indexOf); + playUiSound(SoundEvents.ITEM_FRAME_ROTATE_ITEM, 0.75f, 0.675f); + } + + refreshSearchNextTick = true; + moveToTopNextTick = false; + return true; + } + } + + if (hoveredSlot == noneHovered || !lmb && !rmb) + return super.mouseClicked(pMouseX, pMouseY, pButton); + + // Items + boolean orderClicked = hoveredSlot.getFirst() == -1; + boolean recipeClicked = hoveredSlot.getFirst() == -2; + BigItemStack entry = recipeClicked ? recipesToOrder.get(hoveredSlot.getSecond()) + : orderClicked ? itemsToOrder.get(hoveredSlot.getSecond()) + : displayedItems.get(hoveredSlot.getFirst()) + .get(hoveredSlot.getSecond()); + + ItemStack itemStack = entry.stack; + int transfer = hasShiftDown() ? itemStack.getMaxStackSize() : hasControlDown() ? 10 : 1; + + if (recipeClicked && entry instanceof CraftableBigItemStack cbis) { + if (rmb && cbis.count == 0) { + recipesToOrder.remove(cbis); + return true; + } + requestCraftable(cbis, rmb ? -transfer : transfer); + return true; + } + + BigItemStack existingOrder = getOrderForItem(entry.stack); + if (existingOrder == null) { + if (itemsToOrder.size() >= cols || rmb) + return true; + itemsToOrder.add(existingOrder = new BigItemStack(itemStack.copyWithCount(1), 0)); + playUiSound(SoundEvents.WOOL_STEP, 0.5f, 1.2f); + playUiSound(SoundEvents.BAMBOO_WOOD_STEP, 0.5f, 0.8f); + } + + int current = existingOrder.count; + + if (rmb || orderClicked) { + existingOrder.count = current - transfer; + if (existingOrder.count <= 0) { + itemsToOrder.remove(existingOrder); + playUiSound(SoundEvents.WOOL_STEP, 0.5f, 1.8f); + playUiSound(SoundEvents.BAMBOO_WOOD_STEP, 0.5f, 1.8f); + } + return true; + } + + existingOrder.count = current + Math.min(transfer, entry.count - current); + return true; + } + + @Override + public boolean mouseReleased(double pMouseX, double pMouseY, int pButton) { + if (pButton == GLFW.GLFW_MOUSE_BUTTON_LEFT && scrollHandleActive) { + scrollHandleActive = false; + if (minecraft.isWindowActive()) + GLFW.glfwSetInputMode(minecraft.getWindow() + .getWindow(), 208897, GLFW.GLFW_CURSOR_NORMAL); + } + return super.mouseReleased(pMouseX, pMouseY, pButton); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + if (addressBox.mouseScrolled(mouseX, mouseY, delta)) + return true; + + Couple hoveredSlot = getHoveredSlot((int) mouseX, (int) mouseY); + boolean noHover = hoveredSlot == noneHovered; + + if (noHover || hoveredSlot.getFirst() >= 0 && !hasShiftDown() && getMaxScroll() != 0) { + int maxScroll = getMaxScroll(); + int direction = (int) (Math.ceil(Math.abs(delta)) * -Math.signum(delta)); + float newTarget = Mth.clamp(Math.round(itemScroll.getChaseTarget() + direction), 0, maxScroll); + itemScroll.chase(newTarget, 0.5, Chaser.EXP); + return true; + } + + boolean orderClicked = hoveredSlot.getFirst() == -1; + boolean recipeClicked = hoveredSlot.getFirst() == -2; + BigItemStack entry = recipeClicked ? recipesToOrder.get(hoveredSlot.getSecond()) + : orderClicked ? itemsToOrder.get(hoveredSlot.getSecond()) + : displayedItems.get(hoveredSlot.getFirst()) + .get(hoveredSlot.getSecond()); + + boolean remove = delta < 0; + int transfer = Mth.ceil(Math.abs(delta)) * (hasControlDown() ? 10 : 1); + + if (recipeClicked && entry instanceof CraftableBigItemStack cbis) { + requestCraftable(cbis, remove ? -transfer : transfer); + return true; + } + + BigItemStack existingOrder = orderClicked ? entry : getOrderForItem(entry.stack); + if (existingOrder == null) { + if (itemsToOrder.size() >= cols || remove) + return true; + itemsToOrder.add(existingOrder = new BigItemStack(entry.stack.copyWithCount(1), 0)); + playUiSound(SoundEvents.WOOL_STEP, 0.5f, 1.2f); + playUiSound(SoundEvents.BAMBOO_WOOD_STEP, 0.5f, 0.8f); + } + + int current = existingOrder.count; + + if (remove) { + existingOrder.count = current - transfer; + if (existingOrder.count <= 0) { + itemsToOrder.remove(existingOrder); + playUiSound(SoundEvents.WOOL_STEP, 0.5f, 1.8f); + playUiSound(SoundEvents.BAMBOO_WOOD_STEP, 0.5f, 1.8f); + } else if (existingOrder.count != current) + playUiSound(AllSoundEvents.SCROLL_VALUE.getMainEvent(), 0.25f, 1.2f); + return true; + } + + existingOrder.count = current + Math.min(transfer, blockEntity.getLastClientsideStockSnapshotAsSummary() + .getCountOf(entry.stack) - current); + + if (existingOrder.count != current && current != 0) + playUiSound(AllSoundEvents.SCROLL_VALUE.getMainEvent(), 0.25f, 1.2f); + + return true; + } + + private void clampScrollBar() { + int maxScroll = getMaxScroll(); + float prevTarget = itemScroll.getChaseTarget(); + float newTarget = Mth.clamp(prevTarget, 0, maxScroll); + if (prevTarget != newTarget) + itemScroll.startWithValue(newTarget); + } + + private int getMaxScroll() { + int visibleHeight = windowHeight - 84; + int totalRows = 2; + for (int i = 0; i < displayedItems.size(); i++) { + List list = displayedItems.get(i); + if (list.isEmpty()) + continue; + totalRows++; + if (categories.size() > i && categories.get(i).hidden) + continue; + totalRows += Math.ceil(list.size() / (float) cols); + } + int maxScroll = (int) Math.max(0, (totalRows * rowHeight - visibleHeight + 50) / rowHeight); + return maxScroll; + } + + @Override + public boolean mouseDragged(double pMouseX, double pMouseY, int pButton, double pDragX, double pDragY) { + if (pButton != GLFW.GLFW_MOUSE_BUTTON_LEFT || !scrollHandleActive) + return super.mouseDragged(pMouseX, pMouseY, pButton, pDragX, pDragY); + + Window window = minecraft.getWindow(); + double scaleX = window.getGuiScaledWidth() / (double) window.getScreenWidth(); + double scaleY = window.getGuiScaledHeight() / (double) window.getScreenHeight(); + + int windowH = windowHeight - 92; + int totalH = getMaxScroll() * rowHeight + windowH; + int barSize = Math.max(5, Mth.floor((float) windowH / totalH * (windowH - 2))); + + int minY = getGuiTop() + 15 + barSize / 2; + int maxY = getGuiTop() + 15 + windowH - barSize / 2; + + if (barSize >= windowH - 2) + return true; + + int barX = itemsX + cols * colWidth; + double target = (pMouseY - getGuiTop() - 15 - barSize / 2.0) * totalH / (windowH - 2) / rowHeight; + itemScroll.chase(Mth.clamp(target, 0, getMaxScroll()), 0.8, Chaser.EXP); + + if (minecraft.isWindowActive()) { + double forceX = (barX + 2) / scaleX; + double forceY = Mth.clamp(pMouseY, minY, maxY) / scaleY; + GLFW.glfwSetCursorPos(window.getWindow(), forceX, forceY); + } + + return true; + } + + @Override + public boolean charTyped(char pCodePoint, int pModifiers) { + if (addressBox.isFocused() && addressBox.charTyped(pCodePoint, pModifiers)) + return true; + String s = searchBox.getValue(); + if (!searchBox.charTyped(pCodePoint, pModifiers)) + return false; + if (!Objects.equals(s, searchBox.getValue())) { + refreshSearchNextTick = true; + moveToTopNextTick = true; + } + return true; + } + + @Override + public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { + if (pKeyCode == GLFW.GLFW_KEY_ENTER && searchBox.isFocused()) { + searchBox.setFocused(false); + return true; + } + + if (pKeyCode == GLFW.GLFW_KEY_ENTER && hasShiftDown()) { + sendIt(); + return true; + } + + if (addressBox.isFocused() && addressBox.keyPressed(pKeyCode, pScanCode, pModifiers)) + return true; + + String s = searchBox.getValue(); + if (!searchBox.keyPressed(pKeyCode, pScanCode, pModifiers)) + return searchBox.isFocused() && searchBox.isVisible() && pKeyCode != 256 ? true + : super.keyPressed(pKeyCode, pScanCode, pModifiers); + if (!Objects.equals(s, searchBox.getValue())) { + refreshSearchNextTick = true; + moveToTopNextTick = true; + } + return true; + } + + @Override + public void removed() { + SimpleChannel channel = AllPackets.getChannel(); + BlockPos pos = blockEntity.getBlockPos(); + channel.sendToServer(new PackageOrderRequestPacket(pos, new PackageOrder(Collections.emptyList()), + addressBox.getValue(), false, PackageOrder.empty())); + channel.sendToServer(new StockKeeperCategoryHidingPacket(pos, new ArrayList<>(hiddenCategories))); + super.removed(); + } + + private void sendIt() { + revalidateOrders(); + if (itemsToOrder.isEmpty()) + return; + + forcedEntries = new InventorySummary(); + InventorySummary summary = blockEntity.getLastClientsideStockSnapshotAsSummary(); + for (BigItemStack toOrder : itemsToOrder) { + // momentarily cut the displayed stack size until the stock updates come in + int countOf = summary.getCountOf(toOrder.stack); + if (countOf == BigItemStack.INF) + continue; + forcedEntries.add(toOrder.stack.copy(), -1 - Math.max(0, countOf - toOrder.count)); + } + + PackageOrder craftingRequest = PackageOrder.empty(); + if (canRequestCraftingPackage && !itemsToOrder.isEmpty() && !recipesToOrder.isEmpty()) + if (recipesToOrder.get(0).recipe instanceof CraftingRecipe cr) + craftingRequest = new PackageOrder(FactoryPanelScreen.convertRecipeToPackageOrderContext(cr, itemsToOrder)); + + AllPackets.getChannel() + .sendToServer(new PackageOrderRequestPacket(blockEntity.getBlockPos(), new PackageOrder(itemsToOrder), + addressBox.getValue(), encodeRequester, craftingRequest)); + + itemsToOrder = new ArrayList<>(); + recipesToOrder = new ArrayList<>(); + blockEntity.ticksSinceLastUpdate = 10; + successTicks = 1; + + if (isSchematicListMode()) + menu.player.closeContainer(); + } + + @Override + public boolean keyReleased(int pKeyCode, int pScanCode, int pModifiers) { + return super.keyReleased(pKeyCode, pScanCode, pModifiers); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + + public boolean isSchematicListMode() { + return clipboardItem != null; + } + + public void requestSchematicList() { + itemsToOrder.clear(); + InventorySummary availableItems = blockEntity.getLastClientsideStockSnapshotAsSummary(); + for (List list : clipboardItem) { + for (ClipboardEntry entry : list) { + ItemStack stack = entry.icon; + int toOrder = Math.min(entry.itemAmount, availableItems.getCountOf(stack)); + if (toOrder == 0) + continue; + itemsToOrder.add(new BigItemStack(stack, toOrder)); + } + } + } + + public void requestCraftable(CraftableBigItemStack cbis, int requestedDifference) { + boolean takeOrdersAway = requestedDifference < 0; + if (takeOrdersAway) + requestedDifference = Math.max(-cbis.count, requestedDifference); + if (requestedDifference == 0) + return; + + InventorySummary availableItems = blockEntity.getLastClientsideStockSnapshotAsSummary(); + Function countModifier = stack -> { + BigItemStack ordered = getOrderForItem(stack); + return ordered == null ? 0 : -ordered.count; + }; + + if (takeOrdersAway) { + availableItems = new InventorySummary(); + for (BigItemStack ordered : itemsToOrder) + availableItems.add(ordered.stack, ordered.count); + countModifier = stack -> 0; + } + + Pair>> craftingResult = + maxCraftable(cbis, availableItems, countModifier, takeOrdersAway ? -1 : 9 - itemsToOrder.size()); + int outputCount = cbis.getOutputCount(blockEntity.getLevel()); + int adjustToRecipeAmount = Mth.ceil(Math.abs(requestedDifference) / (float) outputCount) * outputCount; + int maxCraftable = Math.min(adjustToRecipeAmount, craftingResult.getFirst()); + + if (maxCraftable == 0) + return; + + cbis.count += takeOrdersAway ? -maxCraftable : maxCraftable; + + List> validEntriesByIngredient = craftingResult.getSecond(); + for (List list : validEntriesByIngredient) { + int remaining = maxCraftable / outputCount; + for (BigItemStack entry : list) { + if (remaining <= 0) + break; + + int toTransfer = Math.min(remaining, entry.count); + BigItemStack order = getOrderForItem(entry.stack); + + if (takeOrdersAway) { + if (order != null) { + order.count -= toTransfer; + if (order.count == 0) + itemsToOrder.remove(order); + } + } else { + if (order == null) + itemsToOrder.add(order = new BigItemStack(entry.stack.copyWithCount(1), 0)); + order.count += toTransfer; + } + + remaining -= entry.count; + } + } + + updateCraftableAmounts(); + } + + private void updateCraftableAmounts() { + InventorySummary usedItems = new InventorySummary(); + InventorySummary availableItems = new InventorySummary(); + + for (BigItemStack ordered : itemsToOrder) + availableItems.add(ordered.stack, ordered.count); + + for (CraftableBigItemStack cbis : recipesToOrder) { + Pair>> craftingResult = + maxCraftable(cbis, availableItems, stack -> -usedItems.getCountOf(stack), -1); + int maxCraftable = craftingResult.getFirst(); + List> validEntriesByIngredient = craftingResult.getSecond(); + int outputCount = cbis.getOutputCount(blockEntity.getLevel()); + + // Only tweak amounts downward + cbis.count = Math.min(cbis.count, maxCraftable); + + // Use ingredients up before checking next recipe + for (List list : validEntriesByIngredient) { + int remaining = cbis.count / outputCount; + for (BigItemStack entry : list) { + if (remaining <= 0) + break; + usedItems.add(entry.stack, Math.min(remaining, entry.count)); + remaining -= entry.count; + } + } + } + + canRequestCraftingPackage = false; + if (recipesToOrder.size() != 1) + return; + for (BigItemStack ordered : itemsToOrder) + if (usedItems.getCountOf(ordered.stack) != ordered.count) + return; + canRequestCraftingPackage = true; + } + + private Pair>> maxCraftable(CraftableBigItemStack cbis, InventorySummary summary, + Function countModifier, int newTypeLimit) { + List ingredients = cbis.getIngredients(); + List> validEntriesByIngredient = new ArrayList<>(); + List visited = new ArrayList<>(); + + for (Ingredient ingredient : ingredients) { + if (ingredient.isEmpty()) + continue; + List valid = new ArrayList<>(); + for (List list : summary.getItemMap() + .values()) + Entries: for (BigItemStack entry : list) { + if (!ingredient.test(entry.stack)) + continue; + BigItemStack asBis = new BigItemStack(entry.stack, + summary.getCountOf(entry.stack) + countModifier.apply(entry.stack)); + if (asBis.count > 0) + valid.add(asBis); + for (ItemStack visitedStack : visited) { + if (!ItemHandlerHelper.canItemStacksStack(visitedStack, entry.stack)) + continue; + visitedStack.grow(1); + continue Entries; + } + visited.add(entry.stack.copyWithCount(1)); + } + + if (valid.isEmpty()) + return Pair.of(0, List.of()); + + Collections.sort(valid, + (bis1, bis2) -> -Integer.compare(summary.getCountOf(bis1.stack), summary.getCountOf(bis2.stack))); + validEntriesByIngredient.add(valid); + } + + // Used new items may have to be trimmed + if (newTypeLimit != -1) { + int toRemove = (int) validEntriesByIngredient.stream() + .flatMap(l -> l.stream()) + .filter(entry -> getOrderForItem(entry.stack) == null) + .distinct() + .count() - newTypeLimit; + + for (int i = 0; i < toRemove; i++) + removeLeastEssentialItemStack(validEntriesByIngredient); + } + + // Ingredients with shared items must divide counts + for (ItemStack visitedItem : visited) { + for (List list : validEntriesByIngredient) { + for (BigItemStack entry : list) { + if (!ItemHandlerHelper.canItemStacksStack(entry.stack, visitedItem)) + continue; + entry.count = entry.count / visitedItem.getCount(); + } + } + } + + // Determine the bottlenecking ingredient + int minCount = Integer.MAX_VALUE; + for (List list : validEntriesByIngredient) { + int sum = 0; + for (BigItemStack entry : list) + sum += entry.count; + minCount = Math.min(sum, minCount); + } + + if (minCount == 0) + return Pair.of(0, List.of()); + + int outputCount = cbis.getOutputCount(blockEntity.getLevel()); + return Pair.of(minCount * outputCount, validEntriesByIngredient); + } + + private void removeLeastEssentialItemStack(List> validIngredients) { + List longest = null; + int most = 0; + for (List list : validIngredients) { + int count = (int) list.stream() + .filter(entry -> getOrderForItem(entry.stack) == null) + .count(); + if (longest != null && count <= most) + continue; + longest = list; + most = count; + } + + if (longest.isEmpty()) + return; + + BigItemStack chosen = null; + for (int i = 0; i < longest.size(); i++) { + BigItemStack entry = longest.get(longest.size() - 1 - i); + if (getOrderForItem(entry.stack) != null) + continue; + chosen = entry; + break; + } + + for (List list : validIngredients) + list.remove(chosen); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerBlock.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerBlock.java new file mode 100644 index 0000000000..4e6c5375bf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerBlock.java @@ -0,0 +1,120 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllShapes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBlockItem; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.utility.CreateLang; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkHooks; + +public class StockTickerBlock extends HorizontalDirectionalBlock implements IBE, IWrenchable { + + public StockTickerBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + Direction facing = pContext.getHorizontalDirection() + .getOpposite(); + boolean reverse = pContext.getPlayer() != null && pContext.getPlayer() + .isShiftKeyDown(); + return super.getStateForPlacement(pContext).setValue(FACING, reverse ? facing.getOpposite() : facing); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(FACING)); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + if (pPlayer != null && pPlayer.getItemInHand(pHand) + .getItem() instanceof LogisticallyLinkedBlockItem) + return InteractionResult.PASS; + + return onBlockEntityUse(pLevel, pPos, stbe -> { + if (!stbe.behaviour.mayInteractMessage(pPlayer)) + return InteractionResult.SUCCESS; + + if (!pLevel.isClientSide() && !stbe.receivedPayments.isEmpty()) { + for (int i = 0; i < stbe.receivedPayments.getSlots(); i++) + pPlayer.getInventory() + .placeItemBackInInventory( + stbe.receivedPayments.extractItem(i, stbe.receivedPayments.getStackInSlot(i) + .getCount(), false)); + AllSoundEvents.playItemPickup(pPlayer); + return InteractionResult.SUCCESS; + } + + if (pPlayer instanceof ServerPlayer sp) { + if (stbe.isKeeperPresent()) + NetworkHooks.openScreen(sp, stbe.new CategoryMenuProvider(), stbe.getBlockPos()); + else + CreateLang.translate("stock_ticker.keeper_missing") + .sendStatus(pPlayer); + } + + return InteractionResult.SUCCESS; + }); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.STOCK_TICKER; + } + + @OnlyIn(Dist.CLIENT) + public PartialModel getHat(LevelAccessor level, BlockPos pos, LivingEntity keeper) { + return AllPartialModels.LOGISTICS_HAT; + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + @Override + public Class getBlockEntityClass() { + return StockTickerBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.STOCK_TICKER.get(); + } + + @Override + public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerBlockEntity.java new file mode 100644 index 0000000000..c106713650 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerBlockEntity.java @@ -0,0 +1,297 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.IntStream; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.equipment.goggles.IHaveHoveringInformation; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.logistics.filter.FilterItemStack; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.packagerLink.WiFiParticle; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.item.SmartInventory; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.Containers; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; + +public class StockTickerBlockEntity extends StockCheckingBlockEntity implements IHaveHoveringInformation { + + // Player-interface Feature + protected List> lastClientsideStockSnapshot; + protected InventorySummary lastClientsideStockSnapshotAsSummary; + protected List newlyReceivedStockSnapshot; + protected String previouslyUsedAddress; + protected int activeLinks; + protected int ticksSinceLastUpdate; + protected List categories; + protected Map> hiddenCategoriesByPlayer; + + // Shop feature + protected SmartInventory receivedPayments; + protected LazyOptional capability; + + public StockTickerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + previouslyUsedAddress = ""; + receivedPayments = new SmartInventory(27, this, 64, false); + capability = LazyOptional.of(() -> receivedPayments); + categories = new ArrayList<>(); + hiddenCategoriesByPlayer = new HashMap<>(); + } + + public void refreshClientStockSnapshot() { + ticksSinceLastUpdate = 0; + AllPackets.getChannel() + .sendToServer(new LogisticalStockRequestPacket(worldPosition)); + } + + public List> getClientStockSnapshot() { + return lastClientsideStockSnapshot; + } + + public InventorySummary getLastClientsideStockSnapshotAsSummary() { + return lastClientsideStockSnapshotAsSummary; + } + + public int getTicksSinceLastUpdate() { + return ticksSinceLastUpdate; + } + + @Override + public boolean broadcastPackageRequest(RequestType type, PackageOrder order, IItemHandler ignoredHandler, + String address, @Nullable PackageOrder orderContext) { + boolean result = super.broadcastPackageRequest(type, order, ignoredHandler, address, orderContext); + previouslyUsedAddress = address; + notifyUpdate(); + return result; + } + + @Override + public InventorySummary getRecentSummary() { + InventorySummary recentSummary = super.getRecentSummary(); + int contributingLinks = recentSummary.contributingLinks; + if (activeLinks != contributingLinks && !isRemoved()) { + activeLinks = contributingLinks; + sendData(); + } + return recentSummary; + } + + @Override + public void tick() { + super.tick(); + if (level.isClientSide()) { + if (ticksSinceLastUpdate < 100) + ticksSinceLastUpdate += 1; + return; + } + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.putString("PreviousAddress", previouslyUsedAddress); + tag.put("ReceivedPayments", receivedPayments.serializeNBT()); + tag.put("Categories", NBTHelper.writeItemList(categories)); + tag.put("HiddenCategories", NBTHelper.writeCompoundList(hiddenCategoriesByPlayer.entrySet(), e -> { + CompoundTag c = new CompoundTag(); + c.putUUID("Id", e.getKey()); + c.putIntArray("Indices", e.getValue()); + return c; + })); + + if (clientPacket) + tag.putInt("ActiveLinks", activeLinks); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + previouslyUsedAddress = tag.getString("PreviousAddress"); + receivedPayments.deserializeNBT(tag.getCompound("ReceivedPayments")); + categories = NBTHelper.readItemList(tag.getList("Categories", Tag.TAG_COMPOUND)); + categories.removeIf(stack -> !stack.isEmpty() && !(stack.getItem() instanceof FilterItem)); + hiddenCategoriesByPlayer.clear(); + + NBTHelper.iterateCompoundList(tag.getList("HiddenCategories", Tag.TAG_COMPOUND), + c -> hiddenCategoriesByPlayer.put(c.getUUID("Id"), IntStream.of(c.getIntArray("Indices")) + .boxed() + .toList())); + + if (clientPacket) + activeLinks = tag.getInt("ActiveLinks"); + } + + public void receiveStockPacket(List stacks, boolean endOfTransmission) { + if (newlyReceivedStockSnapshot == null) + newlyReceivedStockSnapshot = new ArrayList<>(); + newlyReceivedStockSnapshot.addAll(stacks); + + if (!endOfTransmission) + return; + + lastClientsideStockSnapshotAsSummary = new InventorySummary(); + lastClientsideStockSnapshot = new ArrayList<>(); + + for (BigItemStack bigStack : newlyReceivedStockSnapshot) + lastClientsideStockSnapshotAsSummary.add(bigStack); + + for (ItemStack filter : categories) { + List inCategory = new ArrayList<>(); + if (!filter.isEmpty()) { + FilterItemStack filterItemStack = FilterItemStack.of(filter); + for (Iterator iterator = newlyReceivedStockSnapshot.iterator(); iterator.hasNext(); ) { + BigItemStack bigStack = iterator.next(); + if (!filterItemStack.test(level, bigStack.stack)) + continue; + inCategory.add(bigStack); + iterator.remove(); + } + } + lastClientsideStockSnapshot.add(inCategory); + } + + List unsorted = new ArrayList<>(newlyReceivedStockSnapshot); + lastClientsideStockSnapshot.add(unsorted); + newlyReceivedStockSnapshot = null; + } + + public boolean isKeeperPresent() { + for (int yOffset : Iterate.zeroAndOne) { + for (Direction side : Iterate.horizontalDirections) { + BlockPos seatPos = worldPosition.below(yOffset) + .relative(side); + for (SeatEntity seatEntity : level.getEntitiesOfClass(SeatEntity.class, new AABB(seatPos))) + if (seatEntity.isVehicle()) + return true; + if (yOffset == 0 && AllBlockEntityTypes.HEATER.is(level.getBlockEntity(seatPos))) + return true; + } + } + return false; + } + + @Override + @OnlyIn(Dist.CLIENT) + public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + if (receivedPayments.isEmpty()) + return false; + if (!behaviour.mayAdministrate(Minecraft.getInstance().player)) + return false; + + CreateLang.translate("stock_ticker.contains_payments") + .style(ChatFormatting.WHITE) + .forGoggles(tooltip); + + InventorySummary summary = new InventorySummary(); + for (int i = 0; i < receivedPayments.getSlots(); i++) + summary.add(receivedPayments.getStackInSlot(i)); + for (BigItemStack entry : summary.getStacksByCount()) + CreateLang.builder() + .text(Component.translatable(entry.stack.getDescriptionId()) + .getString() + " x" + entry.count) + .style(ChatFormatting.GREEN) + .forGoggles(tooltip); + + CreateLang.translate("stock_ticker.click_to_retrieve") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + return true; + } + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (isItemHandlerCap(cap)) + return capability.cast(); + return super.getCapability(cap, side); + } + + @Override + public void destroy() { + ItemHelper.dropContents(level, worldPosition, receivedPayments); + for (ItemStack filter : categories) + if (!filter.isEmpty() && filter.getItem() instanceof FilterItem) + Containers.dropItemStack(level, worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(), + filter); + super.destroy(); + } + + @Override + public void invalidate() { + capability.invalidate(); + super.invalidate(); + } + + public void playEffect() { + AllSoundEvents.STOCK_LINK.playAt(level, worldPosition, 1.0f, 1.0f, false); + Vec3 vec3 = Vec3.atCenterOf(worldPosition); + level.addParticle(new WiFiParticle.Data(), vec3.x, vec3.y, vec3.z, 1, 1, 1); + } + + public class CategoryMenuProvider implements MenuProvider { + + @Override + public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { + return StockKeeperCategoryMenu.create(pContainerId, pPlayerInventory, StockTickerBlockEntity.this); + } + + @Override + public Component getDisplayName() { + return Component.empty(); + } + + } + + public class RequestMenuProvider implements MenuProvider { + + @Override + public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { + return StockKeeperRequestMenu.create(pContainerId, pPlayerInventory, StockTickerBlockEntity.this); + } + + @Override + public Component getDisplayName() { + return Component.empty(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerInteractionHandler.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerInteractionHandler.java new file mode 100644 index 0000000000..eedcd19054 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockTickerInteractionHandler.java @@ -0,0 +1,222 @@ +package com.simibubi.create.content.logistics.stockTicker; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedBehaviour.RequestType; +import com.simibubi.create.content.logistics.tableCloth.ShoppingListItem; +import com.simibubi.create.content.logistics.tableCloth.ShoppingListItem.ShoppingList; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteractSpecific; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.network.NetworkHooks; + +@EventBusSubscriber +public class StockTickerInteractionHandler { + + @SubscribeEvent + public static void interactWithLogisticsManager(EntityInteractSpecific event) { + Entity entity = event.getTarget(); + Player player = event.getEntity(); + if (player == null || entity == null) + return; + if (player.isSpectator()) + return; + + Level level = event.getLevel(); + BlockPos targetPos = getStockTickerPosition(entity); + if (targetPos == null) + return; + + if (interactWithLogisticsManagerAt(player, level, targetPos)) { + event.setCancellationResult(InteractionResult.SUCCESS); + event.setCanceled(true); + } + } + + public static boolean interactWithLogisticsManagerAt(Player player, Level level, BlockPos targetPos) { + ItemStack mainHandItem = player.getMainHandItem(); + + if (AllItems.SHOPPING_LIST.isIn(mainHandItem)) { + interactWithShop(player, level, targetPos, mainHandItem); + return true; + } + + if (level.isClientSide()) + return true; + if (!(level.getBlockEntity(targetPos) instanceof StockTickerBlockEntity stbe)) + return false; + + if (!stbe.behaviour.mayInteract(player)) { + player.displayClientMessage(CreateLang.translate("stock_keeper.locked") + .style(ChatFormatting.RED) + .component(), true); + return true; + } + + if (player instanceof ServerPlayer sp) { + boolean showLockOption = + stbe.behaviour.mayAdministrate(player) && Create.LOGISTICS.isLockable(stbe.behaviour.freqId); + boolean isCurrentlyLocked = Create.LOGISTICS.isLocked(stbe.behaviour.freqId); + + NetworkHooks.openScreen(sp, stbe.new RequestMenuProvider(), buf -> { + buf.writeBoolean(showLockOption); + buf.writeBoolean(isCurrentlyLocked); + buf.writeBlockPos(targetPos); + }); + stbe.getRecentSummary() + .divideAndSendTo(sp, targetPos); + } + + return true; + } + + private static void interactWithShop(Player player, Level level, BlockPos targetPos, ItemStack mainHandItem) { + if (level.isClientSide()) + return; + if (!(level.getBlockEntity(targetPos) instanceof StockTickerBlockEntity tickerBE)) + return; + + ShoppingList list = ShoppingListItem.getList(mainHandItem); + if (list == null) + return; + + Couple bakeEntries = list.bakeEntries(level, null); + InventorySummary paymentEntries = bakeEntries.getSecond(); + InventorySummary orderEntries = bakeEntries.getFirst(); + PackageOrder order = new PackageOrder(orderEntries.getStacksByCount()); + + // Must be up-to-date + tickerBE.getAccurateSummary(); + + // Check stock levels + InventorySummary recentSummary = tickerBE.getRecentSummary(); + for (BigItemStack entry : order.stacks()) { + if (recentSummary.getCountOf(entry.stack) >= entry.count) + continue; + + AllSoundEvents.DENY.playOnServer(level, player.blockPosition()); + CreateLang.translate("stock_keeper.stock_level_too_low") + .style(ChatFormatting.RED) + .sendStatus(player); + return; + } + + // Check space in stock ticker + int occupiedSlots = 0; + for (BigItemStack entry : paymentEntries.getStacksByCount()) + occupiedSlots += Mth.ceil(entry.count / (float) entry.stack.getMaxStackSize()); + for (int i = 0; i < tickerBE.receivedPayments.getSlots(); i++) + if (tickerBE.receivedPayments.getStackInSlot(i) + .isEmpty()) + occupiedSlots--; + + if (occupiedSlots > 0) { + AllSoundEvents.DENY.playOnServer(level, player.blockPosition()); + CreateLang.translate("stock_keeper.cash_register_full") + .style(ChatFormatting.RED) + .sendStatus(player); + return; + } + + // Transfer payment to stock ticker + for (boolean simulate : Iterate.trueAndFalse) { + InventorySummary tally = paymentEntries.copy(); + List toTransfer = new ArrayList<>(); + + for (int i = 0; i < player.getInventory().items.size(); i++) { + ItemStack item = player.getInventory() + .getItem(i); + if (item.isEmpty()) + continue; + int countOf = tally.getCountOf(item); + if (countOf == 0) + continue; + int toRemove = Math.min(item.getCount(), countOf); + tally.add(item, -toRemove); + + if (simulate) + continue; + + int newStackSize = item.getCount() - toRemove; + player.getInventory() + .setItem(i, newStackSize == 0 ? ItemStack.EMPTY : item.copyWithCount(newStackSize)); + toTransfer.add(item.copyWithCount(toRemove)); + } + + if (simulate && tally.getTotalCount() != 0) { + AllSoundEvents.DENY.playOnServer(level, player.blockPosition()); + CreateLang.translate("stock_keeper.too_broke") + .style(ChatFormatting.RED) + .sendStatus(player); + return; + } + + if (simulate) + continue; + + toTransfer.forEach(s -> ItemHandlerHelper.insertItemStacked(tickerBE.receivedPayments, s, false)); + } + + tickerBE.broadcastPackageRequest(RequestType.PLAYER, order, null, ShoppingListItem.getAddress(mainHandItem)); + player.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY); + if (!order.isEmpty()) + AllSoundEvents.STOCK_TICKER_TRADE.playOnServer(level, tickerBE.getBlockPos()); + } + + public static BlockPos getStockTickerPosition(Entity entity) { + Entity rootVehicle = entity.getRootVehicle(); + if (!(rootVehicle instanceof SeatEntity)) + return null; + if (!(entity instanceof LivingEntity)) + return null; + if (AllEntityTypes.PACKAGE.is(entity)) + return null; + + BlockPos pos = entity.blockPosition(); + int stations = 0; + BlockPos targetPos = null; + + for (Direction d : Iterate.horizontalDirections) { + for (int y : Iterate.zeroAndOne) { + BlockPos workstationPos = pos.relative(d) + .above(y); + if (!(entity.level() + .getBlockState(workstationPos) + .getBlock() instanceof StockTickerBlock)) + continue; + targetPos = workstationPos; + stations++; + } + } + + if (stations != 1) + return null; + return targetPos; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/BlueprintOverlayShopContext.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/BlueprintOverlayShopContext.java new file mode 100644 index 0000000000..3472eb64e2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/BlueprintOverlayShopContext.java @@ -0,0 +1,5 @@ +package com.simibubi.create.content.logistics.tableCloth; + +public record BlueprintOverlayShopContext(boolean checkout, int stockLevel, int purchases) { + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/ShoppingListItem.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/ShoppingListItem.java new file mode 100644 index 0000000000..c62fd3090b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/ShoppingListItem.java @@ -0,0 +1,194 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; + +public class ShoppingListItem extends Item { + + public static record ShoppingList(List> purchases, UUID shopOwner, UUID shopNetwork) { + + public static ShoppingList load(CompoundTag tag) { + return new ShoppingList( + NBTHelper.readCompoundList(tag.getList("Purchases", Tag.TAG_COMPOUND), + c -> IntAttached.read(c, NbtUtils::readBlockPos)), + tag.getUUID("ShopOwner"), tag.getUUID("ShopNetwork")); + } + + public CompoundTag save() { + CompoundTag tag = new CompoundTag(); + tag.put("Purchases", + NBTHelper.writeCompoundList(purchases, ia -> ia.serializeNBT(NbtUtils::writeBlockPos))); + tag.putUUID("ShopOwner", shopOwner); + tag.putUUID("ShopNetwork", shopNetwork); + return tag; + } + + // Y value of clothPos is pixel perfect (x16) + public void addPurchases(BlockPos clothPos, int amount) { + for (IntAttached entry : purchases) { + if (clothPos.equals(entry.getValue())) { + entry.setFirst(entry.getFirst() + amount); + return; + } + } + purchases.add(IntAttached.with(amount, clothPos)); + } + + public int getPurchases(BlockPos clothPos) { + for (IntAttached entry : purchases) + if (clothPos.equals(entry.getValue())) + return entry.getFirst(); + return 0; + } + + public Couple bakeEntries(LevelAccessor level, @Nullable BlockPos clothPosToIgnore) { + InventorySummary input = new InventorySummary(); + InventorySummary output = new InventorySummary(); + + for (IntAttached entry : purchases) { + if (clothPosToIgnore != null && clothPosToIgnore.equals(entry.getValue())) + continue; + if (!(level.getBlockEntity(entry.getValue()) instanceof TableClothBlockEntity dcbe)) + continue; + input.add(dcbe.getPaymentItem(), dcbe.getPaymentAmount() * entry.getFirst()); + for (BigItemStack stackEntry : dcbe.requestData.encodedRequest.stacks()) + output.add(stackEntry.stack, stackEntry.count * entry.getFirst()); + } + + return Couple.create(output, input); + } + } + + public ShoppingListItem(Properties pProperties) { + super(pProperties); + } + + public static ShoppingList getList(ItemStack stack) { + if (!stack.hasTag() || !stack.getTag() + .contains("ShoppingList")) + return null; + return ShoppingList.load(stack.getTag() + .getCompound("ShoppingList")); + } + + public static ItemStack saveList(ItemStack stack, ShoppingList list, String address) { + CompoundTag tag = stack.getOrCreateTag(); + tag.put("ShoppingList", list.save()); + tag.putString("Address", address); + return stack; + } + + public static String getAddress(ItemStack stack) { + if (!stack.hasTag()) + return ""; + return stack.getTag() + .getString("Address"); + } + + @Override + public void appendHoverText(ItemStack pStack, Level pLevel, List pTooltipComponents, + TooltipFlag pIsAdvanced) { + ShoppingList list = getList(pStack); + + if (list != null) { + Couple lists = list.bakeEntries(pLevel, null); + + if (lists != null) { + for (InventorySummary items : lists) { + List entries = items.getStacksByCount(); + boolean cost = items == lists.getSecond(); + + if (cost) + pTooltipComponents.add(Component.empty()); + + if (entries.size() == 1) { + BigItemStack entry = entries.get(0); + (cost ? CreateLang.translate("table_cloth.total_cost") : CreateLang.text("")) + .style(ChatFormatting.GOLD) + .add(CreateLang.builder() + .add(entry.stack.getHoverName()) + .text(" x") + .text(String.valueOf(entry.count)) + .style(cost ? ChatFormatting.YELLOW : ChatFormatting.GRAY)) + .addTo(pTooltipComponents); + + } else { + if (cost) + CreateLang.translate("table_cloth.total_cost") + .style(ChatFormatting.GOLD) + .addTo(pTooltipComponents); + for (BigItemStack entry : entries) { + CreateLang.builder() + .add(entry.stack.getHoverName()) + .text(" x") + .text(String.valueOf(entry.count)) + .style(cost ? ChatFormatting.YELLOW : ChatFormatting.GRAY) + .addTo(pTooltipComponents); + } + } + } + } + } + + CreateLang.translate("table_cloth.hand_to_shop_keeper") + .style(ChatFormatting.GRAY) + .addTo(pTooltipComponents); + + CreateLang.translate("table_cloth.sneak_click_discard") + .style(ChatFormatting.DARK_GRAY) + .addTo(pTooltipComponents); + } + + @Override + public InteractionResultHolder use(Level pLevel, Player pPlayer, InteractionHand pUsedHand) { + if (pUsedHand == InteractionHand.OFF_HAND || pPlayer == null || !pPlayer.isShiftKeyDown()) + return new InteractionResultHolder<>(InteractionResult.PASS, pPlayer.getItemInHand(pUsedHand)); + + CreateLang.translate("table_cloth.shopping_list_discarded") + .sendStatus(pPlayer); + pPlayer.playSound(SoundEvents.BOOK_PAGE_TURN); + return new InteractionResultHolder<>(InteractionResult.SUCCESS, ItemStack.EMPTY); + } + + @Override + public InteractionResult useOn(UseOnContext pContext) { + InteractionHand pUsedHand = pContext.getHand(); + Player pPlayer = pContext.getPlayer(); + if (pUsedHand == InteractionHand.OFF_HAND || pPlayer == null || !pPlayer.isShiftKeyDown()) + return InteractionResult.PASS; + pPlayer.setItemInHand(pUsedHand, ItemStack.EMPTY); + + CreateLang.translate("table_cloth.shopping_list_discarded") + .sendStatus(pPlayer); + pPlayer.playSound(SoundEvents.BOOK_PAGE_TURN); + return InteractionResult.SUCCESS; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlock.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlock.java new file mode 100644 index 0000000000..95a8023138 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlock.java @@ -0,0 +1,222 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import java.util.List; +import java.util.function.Predicate; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.redstoneRequester.AutoRequestData; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.IHaveBigOutline; + +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class TableClothBlock extends Block implements IHaveBigOutline, IWrenchable, IBE { + + public static final BooleanProperty HAS_BE = BooleanProperty.create("entity"); + + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + + private DyeColor colour; + + public TableClothBlock(Properties pProperties, DyeColor colour) { + super(pProperties); + this.colour = colour; + registerDefaultState(defaultBlockState().setValue(HAS_BE, false)); + } + + public TableClothBlock(Properties pProperties, String type) { + super(pProperties); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(HAS_BE)); + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + if (!(pPlacer instanceof Player player)) + return; + + AutoRequestData requestData = AutoRequestData.readFromItem(pLevel, player, pPos, pStack); + if (requestData == null) + return; + + pLevel.setBlockAndUpdate(pPos, pState.setValue(HAS_BE, true)); + withBlockEntityDo(pLevel, pPos, dcbe -> { + dcbe.requestData = requestData; + dcbe.owner = player.getUUID(); + dcbe.facing = player.getDirection() + .getOpposite(); + AllAdvancements.TABLE_CLOTH_SHOP.awardTo(player); + }); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult ray) { + if (ray.getDirection() == Direction.DOWN) + return InteractionResult.PASS; + if (world.isClientSide) + return InteractionResult.SUCCESS; + + ItemStack heldItem = player.getItemInHand(hand); + boolean shiftKeyDown = player.isShiftKeyDown(); + if (!player.mayBuild()) + return InteractionResult.PASS; + + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (placementHelper.matchesItem(heldItem)) { + if (shiftKeyDown) + return InteractionResult.PASS; + placementHelper.getOffset(player, world, state, pos, ray) + .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + return InteractionResult.SUCCESS; + } + + if ((shiftKeyDown || heldItem.isEmpty()) && !state.getValue(HAS_BE)) + return InteractionResult.PASS; + + if (!world.isClientSide() && !state.getValue(HAS_BE)) + world.setBlockAndUpdate(pos, state.cycle(HAS_BE)); + + return onBlockEntityUse(world, pos, dcbe -> dcbe.use(player, ray)); + } + + @SuppressWarnings("deprecation") + @Override + public List getDrops(BlockState pState, + net.minecraft.world.level.storage.loot.LootParams.Builder pParams) { + List drops = super.getDrops(pState, pParams); + + if (!(pParams.getOptionalParameter(LootContextParams.BLOCK_ENTITY) instanceof TableClothBlockEntity dcbe)) + return drops; + if (!dcbe.isShop()) + return drops; + + for (ItemStack stack : drops) { + if (AllItemTags.TABLE_CLOTHS.matches(stack)) { + ItemStack drop = new ItemStack(this); + dcbe.requestData.writeToItem(dcbe.getBlockPos(), drop); + return List.of(drop); + } + } + + return drops; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.TABLE_CLOTH; + } + + @Override + public VoxelShape getInteractionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { + return AllShapes.TABLE_CLOTH; + } + + @Override + public VoxelShape getOcclusionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { + return AllShapes.TABLE_CLOTH_OCCLUSION; + } + + @Override + public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, + CollisionContext pContext) { + return AllShapes.TABLE_CLOTH_OCCLUSION; + } + + @Override + public boolean canSurvive(BlockState p_152922_, LevelReader p_152923_, BlockPos p_152924_) { + return true; + } + + @Nullable + public DyeColor getColor() { + return colour; + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return state.getValue(HAS_BE) ? IBE.super.newBlockEntity(pos, state) : null; + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + if (!pNewState.getOptionalValue(HAS_BE) + .orElse(false)) + pNewState = Blocks.AIR.defaultBlockState(); + + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + @Override + public Class getBlockEntityClass() { + return TableClothBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.TABLE_CLOTH.get(); + } + + private static class PlacementHelper implements IPlacementHelper { + + @Override + public Predicate getItemPredicate() { + return i -> AllItemTags.TABLE_CLOTHS.matches(i.getItem()); + } + + @Override + public Predicate getStatePredicate() { + return s -> s.getBlock() instanceof TableClothBlock; + } + + @Override + public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, + BlockHitResult ray) { + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), Axis.Y, + dir -> world.getBlockState(pos.relative(dir)) + .canBeReplaced()); + + if (directions.isEmpty()) + return PlacementOffset.fail(); + else + return PlacementOffset.success(pos.relative(directions.get(0)), s -> s); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlockEntity.java new file mode 100644 index 0000000000..30bc0c4904 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlockEntity.java @@ -0,0 +1,324 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.content.logistics.BigItemStack; +import com.simibubi.create.content.logistics.packager.InventorySummary; +import com.simibubi.create.content.logistics.redstoneRequester.AutoRequestData; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; +import com.simibubi.create.content.logistics.tableCloth.ShoppingListItem.ShoppingList; +import com.simibubi.create.foundation.blockEntity.RemoveBlockEntityPacket; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.Containers; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; + +public class TableClothBlockEntity extends SmartBlockEntity { + + public AutoRequestData requestData; + public List manuallyAddedItems; + public UUID owner; + + public Direction facing; + public boolean sideOccluded; + public FilteringBehaviour priceTag; + + private List renderedItemsForShop; + + public TableClothBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + manuallyAddedItems = new ArrayList<>(); + requestData = new AutoRequestData(); + owner = null; + facing = Direction.SOUTH; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(priceTag = new TableClothFilteringBehaviour(this)); + } + + public List getItemsForRender() { + if (isShop()) { + if (renderedItemsForShop == null) + renderedItemsForShop = requestData.encodedRequest.stacks() + .stream() + .map(b -> b.stack) + .limit(4) + .toList(); + return renderedItemsForShop; + } + + return manuallyAddedItems; + } + + @Override + public void lazyTick() { + super.lazyTick(); + BlockPos relativePos = worldPosition.relative(facing); + sideOccluded = AllBlockTags.TABLE_CLOTHS.matches(level.getBlockState(relativePos)) + || Block.isFaceFull(level.getBlockState(relativePos.below()) + .getOcclusionShape(level, relativePos.below()), facing.getOpposite()); + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(1); + } + + public boolean isShop() { + return !requestData.encodedRequest.isEmpty(); + } + + public InteractionResult use(Player player, BlockHitResult ray) { + if (isShop()) + return useShop(player); + + ItemStack heldItem = player.getItemInHand(InteractionHand.MAIN_HAND); + + if (heldItem.isEmpty()) { + if (manuallyAddedItems.isEmpty()) + return InteractionResult.SUCCESS; + player.setItemInHand(InteractionHand.MAIN_HAND, manuallyAddedItems.remove(manuallyAddedItems.size() - 1)); + level.playSound(null, worldPosition, SoundEvents.ITEM_FRAME_REMOVE_ITEM, SoundSource.BLOCKS, 0.5f, 1f); + + if (manuallyAddedItems.isEmpty()) { + level.setBlock(worldPosition, getBlockState().setValue(TableClothBlock.HAS_BE, false), 3); + AllPackets.getChannel() + .send(packetTarget(), new RemoveBlockEntityPacket(worldPosition)); + } else + notifyUpdate(); + + return InteractionResult.SUCCESS; + } + + if (manuallyAddedItems.size() >= 4) + return InteractionResult.SUCCESS; + + level.playSound(null, worldPosition, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.5f, 1f); + manuallyAddedItems.add(heldItem.copyWithCount(1)); + facing = player.getDirection() + .getOpposite(); + heldItem.shrink(1); + if (heldItem.isEmpty()) + player.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY); + notifyUpdate(); + return InteractionResult.SUCCESS; + } + + public boolean targetsPriceTag(Player player, BlockHitResult ray) { + return priceTag != null && priceTag.mayInteract(player) && priceTag.getSlotPositioning() + .testHit(level, worldPosition, getBlockState(), ray.getLocation() + .subtract(Vec3.atLowerCornerOf(worldPosition))); + } + + public InteractionResult useShop(Player player) { + ItemStack itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND); + ItemStack prevListItem = ItemStack.EMPTY; + boolean addOntoList = false; + + // Remove other lists from inventory + for (int i = 0; i < 9; i++) { + ItemStack item = player.getInventory() + .getItem(i); + if (!AllItems.SHOPPING_LIST.isIn(item)) + continue; + prevListItem = item; + addOntoList = true; + player.getInventory() + .setItem(i, ItemStack.EMPTY); + } + + // add onto existing list if in hand + if (AllItems.SHOPPING_LIST.isIn(itemInHand)) { + prevListItem = itemInHand; + addOntoList = true; + } + + if (!itemInHand.isEmpty() && !addOntoList) { + CreateLang.translate("stock_keeper.shopping_list_empty_hand") + .sendStatus(player); + AllSoundEvents.DENY.playOnServer(level, worldPosition, 0.5f, 1); + return InteractionResult.SUCCESS; + } + + if (getPaymentItem().isEmpty()) { + CreateLang.translate("stock_keeper.no_price_set") + .sendStatus(player); + AllSoundEvents.DENY.playOnServer(level, worldPosition, 0.5f, 1); + return InteractionResult.SUCCESS; + } + + UUID tickerID = null; + BlockPos tickerPos = requestData.targetOffset.offset(worldPosition); + if (level.getBlockEntity(tickerPos) instanceof StockTickerBlockEntity stbe && stbe.isKeeperPresent()) + tickerID = stbe.behaviour.freqId; + + int stockLevel = getStockLevelForTrade(ShoppingListItem.getList(prevListItem)); + + if (tickerID == null) { + CreateLang.translate("stock_keeper.keeper_missing") + .style(ChatFormatting.RED) + .sendStatus(player); + AllSoundEvents.DENY.playOnServer(level, worldPosition, 0.5f, 1); + return InteractionResult.SUCCESS; + } + + if (stockLevel == 0) { + CreateLang.translate("stock_keeper.out_of_stock") + .style(ChatFormatting.RED) + .sendStatus(player); + AllSoundEvents.DENY.playOnServer(level, worldPosition, 0.5f, 1); + if (!prevListItem.isEmpty()) { + if (player.getItemInHand(InteractionHand.MAIN_HAND) + .isEmpty()) + player.setItemInHand(InteractionHand.MAIN_HAND, prevListItem); + else + player.getInventory() + .placeItemBackInInventory(prevListItem); + } + + return InteractionResult.SUCCESS; + } + + ShoppingList list = new ShoppingList(new ArrayList<>(), owner, tickerID); + + if (addOntoList) { + ShoppingList prevList = ShoppingListItem.getList(prevListItem); + if (owner.equals(prevList.shopOwner()) && tickerID.equals(prevList.shopNetwork())) + list = prevList; + else + addOntoList = false; + } + + if (list.getPurchases(worldPosition) >= stockLevel) { + for (IntAttached entry : list.purchases()) + if (worldPosition.equals(entry.getValue())) + entry.setFirst(Math.min(stockLevel, entry.getFirst())); + + CreateLang.translate("stock_keeper.limited_stock") + .style(ChatFormatting.RED) + .sendStatus(player); + + } else { + AllSoundEvents.CONFIRM_2.playOnServer(level, worldPosition, 0.5f, 1.0f); + list.addPurchases(worldPosition, 1); + if (!addOntoList) + CreateLang.translate("stock_keeper.use_list_to_add_purchases") + .color(0xeeeeee) + .sendStatus(player); + if (!addOntoList) + level.playSound(null, worldPosition, SoundEvents.BOOK_PAGE_TURN, SoundSource.BLOCKS, 1, 1.5f); + } + + ItemStack newListItem = + ShoppingListItem.saveList(AllItems.SHOPPING_LIST.asStack(), list, requestData.encodedTargetAdress); + + if (player.getItemInHand(InteractionHand.MAIN_HAND) + .isEmpty()) + player.setItemInHand(InteractionHand.MAIN_HAND, newListItem); + else + player.getInventory() + .placeItemBackInInventory(newListItem); + + return InteractionResult.SUCCESS; + } + + public int getStockLevelForTrade(@Nullable ShoppingList otherPurchases) { + BlockPos tickerPos = requestData.targetOffset.offset(worldPosition); + if (!(level.getBlockEntity(tickerPos) instanceof StockTickerBlockEntity stbe)) + return 0; + + InventorySummary recentSummary = null; + + if (level.isClientSide()) { + if (stbe.getTicksSinceLastUpdate() > 15) + stbe.refreshClientStockSnapshot(); + recentSummary = stbe.getLastClientsideStockSnapshotAsSummary(); + } else + recentSummary = stbe.getRecentSummary(); + + if (recentSummary == null) + return 0; + + InventorySummary modifierSummary = new InventorySummary(); + if (otherPurchases != null) + modifierSummary = otherPurchases.bakeEntries(level, worldPosition) + .getFirst(); + + int smallestQuotient = Integer.MAX_VALUE; + for (BigItemStack entry : requestData.encodedRequest.stacks()) + if (entry.count > 0) + smallestQuotient = Math.min(smallestQuotient, + (recentSummary.getCountOf(entry.stack) - modifierSummary.getCountOf(entry.stack)) / entry.count); + + return smallestQuotient; + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.put("Items", NBTHelper.writeItemList(manuallyAddedItems)); + tag.putInt("Facing", facing.get2DDataValue()); + requestData.write(tag); + if (owner != null) + tag.putUUID("OwnerUUID", owner); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + manuallyAddedItems = NBTHelper.readItemList(tag.getList("Items", Tag.TAG_COMPOUND)); + requestData = AutoRequestData.read(tag); + owner = tag.contains("OwnerUUID") ? tag.getUUID("OwnerUUID") : null; + facing = Direction.from2DDataValue(Mth.positiveModulo(tag.getInt("Facing"), 4)); + } + + @Override + public void destroy() { + super.destroy(); + manuallyAddedItems.forEach(stack -> Containers.dropItemStack(level, worldPosition.getX(), worldPosition.getY(), + worldPosition.getZ(), stack)); + manuallyAddedItems.clear(); + } + + public ItemStack getPaymentItem() { + return priceTag.getFilter(); + } + + public int getPaymentAmount() { + return priceTag.getFilter() + .isEmpty() ? 1 : priceTag.count; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlockItem.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlockItem.java new file mode 100644 index 0000000000..4577f254a4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothBlockItem.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import java.util.List; + +import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterBlock; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; + +public class TableClothBlockItem extends BlockItem { + + public TableClothBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public boolean isFoil(ItemStack pStack) { + CompoundTag tag = pStack.getTag(); + return tag != null && tag.contains("TargetOffset"); + } + + @Override + public void appendHoverText(ItemStack pStack, Level pLevel, List pTooltip, TooltipFlag pFlag) { + super.appendHoverText(pStack, pLevel, pTooltip, pFlag); + if (!isFoil(pStack)) + return; + + CreateLang.translate("table_cloth.shop_configured") + .style(ChatFormatting.GOLD) + .addTo(pTooltip); + + RedstoneRequesterBlock.appendRequesterTooltip(pStack, pTooltip); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothFilterSlot.java new file mode 100644 index 0000000000..ffb76be2b2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothFilterSlot.java @@ -0,0 +1,35 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; + +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +class TableClothFilterSlot extends ValueBoxTransform { + + private TableClothBlockEntity be; + + public TableClothFilterSlot(TableClothBlockEntity be) { + this.be = be; + } + + @Override + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { + Vec3 v = be.sideOccluded ? VecHelper.voxelSpace(8, 0.75, 15.25) : VecHelper.voxelSpace(12, -2.75, 16.75); + return VecHelper.rotateCentered(v, -be.facing.toYRot(), Axis.Y); + } + + @Override + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { + TransformStack.of(ms) + .rotateYDegrees(180 - be.facing.toYRot()) + .rotateXDegrees(be.sideOccluded ? 90 : 0); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothFilteringBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothFilteringBehaviour.java new file mode 100644 index 0000000000..ab87c6732c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothFilteringBehaviour.java @@ -0,0 +1,97 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.BlockHitResult; + +public class TableClothFilteringBehaviour extends FilteringBehaviour { + + public TableClothFilteringBehaviour(TableClothBlockEntity be) { + super(be, new TableClothFilterSlot(be)); + withPredicate(is -> !(is.getItem() instanceof FilterItem) && !(is.getItem() instanceof ShoppingListItem)); + count = 1; + } + + @Override + public void onShortInteract(Player player, InteractionHand hand, Direction side, BlockHitResult hitResult) { + super.onShortInteract(player, hand, side, hitResult); + } + + @Override + public float getRenderDistance() { + return 32; + } + + private TableClothBlockEntity dbe() { + return (TableClothBlockEntity) blockEntity; + } + + @Override + public boolean mayInteract(Player player) { + return dbe().owner == null || player.getUUID() + .equals(dbe().owner); + } + + @Override + public boolean isSafeNBT() { + return false; + } + + @Override + public MutableComponent getLabel() { + return CreateLang.translateDirect("table_cloth.price_per_order"); + } + + public boolean isCountVisible() { + return !filter.isEmpty(); + } + + @Override + public boolean setFilter(ItemStack stack) { + int before = count; + boolean result = super.setFilter(stack); + count = before; + return result; + } + + @Override + public void setValueSettings(Player player, ValueSettings settings, boolean ctrlDown) { + if (getValueSettings().equals(settings)) + return; + count = Math.max(1, settings.value()); + blockEntity.setChanged(); + blockEntity.sendData(); + playFeedbackSound(this); + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + return new ValueSettingsBoard(getLabel(), 100, 10, CreateLang.translatedOptions("table_cloth", "amount"), + new ValueSettingsFormatter(this::formatValue)); + } + + public MutableComponent formatValue(ValueSettings value) { + return Component.literal(String.valueOf(Math.max(1, value.value()))); + } + + @Override + public MutableComponent getCountLabelForValueBox() { + return Component.literal(isCountVisible() ? String.valueOf(count) : ""); + } + + @Override + public boolean isActive() { + return dbe().isShop(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothModel.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothModel.java new file mode 100644 index 0000000000..ece6473f68 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothModel.java @@ -0,0 +1,126 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.model.BakedModelWrapperWithData; +import com.simibubi.create.foundation.model.BakedQuadHelper; + +import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.data.Iterate; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.client.model.data.ModelData.Builder; +import net.minecraftforge.client.model.data.ModelProperty; + +public class TableClothModel extends BakedModelWrapperWithData { + + private static final ModelProperty CULL_PROPERTY = new ModelProperty<>(); + + private static final Map>> CORNERS = new HashMap<>(); + + public TableClothModel(BakedModel originalModel) { + super(originalModel); + } + + public static void reload() { + CORNERS.clear(); + } + + @Override + public boolean useAmbientOcclusion() { + return false; + } + + private List getCorner(TableClothBlock block, int corner, @NotNull RandomSource rand, + @Nullable RenderType renderType) { + if (!CORNERS.containsKey(block)) { + TextureAtlasSprite targetSprite = getParticleIcon(ModelData.EMPTY); + List> list = new ArrayList<>(); + + for (PartialModel pm : List.of(AllPartialModels.TABLE_CLOTH_SW, AllPartialModels.TABLE_CLOTH_NW, + AllPartialModels.TABLE_CLOTH_NE, AllPartialModels.TABLE_CLOTH_SE)) + list.add(getCornerQuads(rand, renderType, targetSprite, pm)); + + CORNERS.put(block, list); + } + + return CORNERS.get(block) + .get(corner); + } + + private List getCornerQuads(RandomSource rand, RenderType renderType, TextureAtlasSprite targetSprite, + PartialModel pm) { + List quads = new ArrayList<>(); + + for (BakedQuad quad : pm.get() + .getQuads(null, null, rand, ModelData.EMPTY, renderType)) { + TextureAtlasSprite original = quad.getSprite(); + BakedQuad newQuad = BakedQuadHelper.clone(quad); + int[] vertexData = newQuad.getVertices(); + for (int vertex = 0; vertex < 4; vertex++) { + BakedQuadHelper.setU(vertexData, vertex, targetSprite + .getU(SpriteShiftEntry.getUnInterpolatedU(original, BakedQuadHelper.getU(vertexData, vertex)))); + BakedQuadHelper.setV(vertexData, vertex, targetSprite + .getV(SpriteShiftEntry.getUnInterpolatedV(original, BakedQuadHelper.getV(vertexData, vertex)))); + } + quads.add(newQuad); + } + + return quads; + } + + @Override + protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, + ModelData blockEntityData) { + List culledSides = new ArrayList<>(); + for (Direction side : Iterate.horizontalDirections) + if (!Block.shouldRenderFace(state, world, pos, side, pos.relative(side))) + culledSides.add(side); + if (culledSides.isEmpty()) + return builder; + return builder.with(CULL_PROPERTY, new CullData(EnumSet.copyOf(culledSides))); + } + + @Override + public @NotNull List getQuads(@Nullable BlockState state, @Nullable Direction side, + @NotNull RandomSource rand, @NotNull ModelData extraData, @Nullable RenderType renderType) { + @NotNull + List mainQuads = super.getQuads(state, side, rand, extraData, renderType); + if (side == null || side.getAxis() == Axis.Y) + return mainQuads; + + CullData cullData = extraData.get(CULL_PROPERTY); + if (cullData != null && cullData.culled() + .contains(side.getClockWise())) + return mainQuads; + if (state == null || !(state.getBlock() instanceof TableClothBlock dcb)) + return mainQuads; + + List copyOf = new ArrayList<>(mainQuads); + copyOf.addAll(getCorner(dcb, side.get2DDataValue(), rand, renderType)); + return copyOf; + } + + private static record CullData(EnumSet culled) { + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothOverlayRenderer.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothOverlayRenderer.java new file mode 100644 index 0000000000..1256ce6c0a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothOverlayRenderer.java @@ -0,0 +1,71 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; +import com.simibubi.create.content.logistics.stockTicker.StockTickerInteractionHandler; +import com.simibubi.create.content.logistics.tableCloth.ShoppingListItem.ShoppingList; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.HitResult.Type; + +public class TableClothOverlayRenderer { + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + if (mc.gameMode.getPlayerMode() == GameType.SPECTATOR) + return; + HitResult mouseOver = mc.hitResult; + if (mouseOver == null) + return; + + ItemStack heldItem = mc.player.getMainHandItem(); + + if (mouseOver.getType() != Type.ENTITY) { + if (!(mouseOver instanceof BlockHitResult bhr)) + return; + if (!(mc.level.getBlockEntity(bhr.getBlockPos()) instanceof TableClothBlockEntity dcbe)) + return; + if (!dcbe.isShop()) + return; + if (AllBlocks.CLIPBOARD.isIn(heldItem)) + return; + if (dcbe.targetsPriceTag(mc.player, bhr)) + return; + + int alreadyPurchased = 0; + ShoppingList list = ShoppingListItem.getList(heldItem); + if (list != null) + alreadyPurchased = list.getPurchases(dcbe.getBlockPos()); + + BlueprintOverlayRenderer.displayClothShop(dcbe, alreadyPurchased, list); + return; + } + + EntityHitResult entityRay = (EntityHitResult) mouseOver; + if (!AllItems.SHOPPING_LIST.isIn(heldItem)) + return; + + ShoppingList list = ShoppingListItem.getList(heldItem); + BlockPos stockTickerPosition = StockTickerInteractionHandler.getStockTickerPosition(entityRay.getEntity()); + + if (list == null || stockTickerPosition == null) + return; + if (!(mc.level.getBlockEntity(stockTickerPosition) instanceof StockTickerBlockEntity tickerBE)) + return; + if (!tickerBE.behaviour.freqId.equals(list.shopNetwork())) + return; + + BlueprintOverlayRenderer.displayShoppingList(list.bakeEntries(mc.level, null)); + return; + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothRenderer.java b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothRenderer.java new file mode 100644 index 0000000000..8bde680a94 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tableCloth/TableClothRenderer.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.logistics.tableCloth; + +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.depot.DepotRenderer; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; + +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +public class TableClothRenderer extends SmartBlockEntityRenderer { + + public TableClothRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(TableClothBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + super.renderSafe(blockEntity, partialTicks, ms, buffer, light, overlay); + List stacks = blockEntity.getItemsForRender(); + float rotationInRadians = Mth.DEG_TO_RAD * (180 - blockEntity.facing.toYRot()); + + if (blockEntity.isShop()) { + CachedBuffers + .partial(blockEntity.sideOccluded ? AllPartialModels.TABLE_CLOTH_PRICE_TOP + : AllPartialModels.TABLE_CLOTH_PRICE_SIDE, blockEntity.getBlockState()) + .rotateCentered(rotationInRadians, Direction.UP) + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutout())); + } + + ms.pushPose(); + TransformStack.of(ms) + .rotateCentered(rotationInRadians, Direction.UP); + for (int i = 0; i < stacks.size(); i++) { + ItemStack entry = stacks.get(i); + ms.pushPose(); + ms.translate(0.5f, 3 / 16f, 0.5f); + + if (stacks.size() > 1) { + ms.mulPose(Axis.YP.rotationDegrees(i * (360f / stacks.size()) + 45f)); + ms.translate(0, i % 2 == 0 ? -0.005 : 0, 5 / 16f); + ms.mulPose(Axis.YP.rotationDegrees(-i * (360f / stacks.size()) - 45f)); + } + + BakedModel bakedModel = Minecraft.getInstance() + .getItemRenderer() + .getModel(entry, null, null, 0); + boolean blockItem = bakedModel.isGui3d(); + if (!blockItem) + TransformStack.of(ms) + .rotate(-rotationInRadians + Mth.PI, Direction.UP); + + DepotRenderer.renderItem(blockEntity.getLevel(), ms, buffer, light, OverlayTexture.NO_OVERLAY, entry, 0, + null, Vec3.atCenterOf(blockEntity.getBlockPos()), true); + ms.popPose(); + } + + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlock.java index 4c572e8486..c8bb55eae6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlock.java @@ -9,9 +9,9 @@ import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehavi import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.levelWrappers.WrappedLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -99,7 +99,7 @@ public class BeltTunnelBlock extends Block implements IBE @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState p_220082_4_, boolean p_220082_5_) { - if (!(world instanceof WrappedWorld) && !world.isClientSide()) + if (!(world instanceof WrappedLevel) && !world.isClientSide()) withBlockEntityDo(world, pos, BeltTunnelBlockEntity::updateTunnelConnections); } @@ -109,7 +109,7 @@ public class BeltTunnelBlock extends Block implements IBE if (facing.getAxis() .isVertical()) return state; - if (!(worldIn instanceof WrappedWorld) && !worldIn.isClientSide()) + if (!(worldIn instanceof WrappedLevel) && !worldIn.isClientSide()) withBlockEntityDo(worldIn, currentPos, BeltTunnelBlockEntity::updateTunnelConnections); BlockState tunnelState = getTunnelState(worldIn, currentPos); if (tunnelState.getValue(HORIZONTAL_AXIS) == state.getValue(HORIZONTAL_AXIS)) { diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlockEntity.java index 9a932ce55b..106e035712 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlockEntity.java @@ -15,11 +15,11 @@ import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock.Shape; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -155,7 +155,7 @@ public class BeltTunnelBlockEntity extends SmartBlockEntity { if (level.isClientSide) { if (flaps.containsKey(side)) flaps.get(side) - .setValue(inward ^ side.getAxis() == Axis.Z ? -1 : 1); + .setValue(inward ? -1 : 1); return; } diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelRenderer.java index 6cfa1c5c49..c2edb61511 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelRenderer.java @@ -3,22 +3,17 @@ package com.simibubi.create.content.logistics.tunnel; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.FlapStuffs; import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; -import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.Vec3; public class BeltTunnelRenderer extends SmartBlockEntityRenderer { @@ -34,45 +29,17 @@ public class BeltTunnelRenderer extends SmartBlockEntityRenderer 0) - flapAngle *= .5f; - - msr.translate(pivot) - .rotateXDegrees(flapAngle) - .translateBack(pivot); - flapBuffer.light(light) - .renderInto(ms, vb); - - ms.popPose(); - ms.translate(-3.05f / 16f, 0, 0); - } - ms.popPose(); + FlapStuffs.renderFlaps(ms, vb, flapBuffer, FlapStuffs.TUNNEL_PIVOT, direction, f, 0, light); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelShapes.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelShapes.java index b1dc2f5d89..b505d33520 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelShapes.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelShapes.java @@ -2,8 +2,7 @@ package com.simibubi.create.content.logistics.tunnel; import static net.minecraft.world.level.block.Block.box; -import com.simibubi.create.foundation.utility.VoxelShaper; - +import net.createmod.catnip.math.VoxelShaper; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.world.level.block.state.BlockState; diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelVisual.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelVisual.java index f4171b9c96..526a5a9c89 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelVisual.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelVisual.java @@ -1,74 +1,41 @@ package com.simibubi.create.content.logistics.tunnel; -import java.util.ArrayList; -import java.util.Collection; import java.util.EnumMap; import java.util.Map; import java.util.function.Consumer; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.logistics.flwdata.FlapInstance; -import com.simibubi.create.foundation.render.AllInstanceTypes; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.content.logistics.FlapStuffs; import dev.engine_room.flywheel.api.instance.Instance; -import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.lib.instance.AbstractInstance; -import dev.engine_room.flywheel.lib.instance.FlatLit; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; +import net.createmod.catnip.animation.LerpedFloat; import net.minecraft.core.Direction; -import net.minecraft.world.level.LightLayer; public class BeltTunnelVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { - private final Map> tunnelFlaps = new EnumMap<>(Direction.class); + private final Map tunnelFlaps = new EnumMap<>(Direction.class); + private int light; - public BeltTunnelVisual(VisualizationContext context, BeltTunnelBlockEntity blockEntity, float partialTick) { + public BeltTunnelVisual(VisualizationContext context, BeltTunnelBlockEntity blockEntity, float partialTick) { super(context, blockEntity, partialTick); - setupFlaps(partialTick); + createFlaps(); + updateFlaps(partialTick); } - private void setupFlaps(float partialTick) { - Instancer model = instancerProvider().instancer(AllInstanceTypes.FLAP, Models.partial(AllPartialModels.BELT_TUNNEL_FLAP)); - - int blockLight = level.getBrightness(LightLayer.BLOCK, pos); - int skyLight = level.getBrightness(LightLayer.SKY, pos); - + private void createFlaps() { blockEntity.flaps.forEach((direction, flapValue) -> { + var commonTransform = FlapStuffs.commonTransform(visualPos, direction, 0); + var flapSide = new FlapStuffs.Visual(instancerProvider(), commonTransform, FlapStuffs.TUNNEL_PIVOT, Models.partial(AllPartialModels.BELT_TUNNEL_FLAP)); - float flapness = flapValue.getValue(partialTick); + flapSide.updateLight(light); - float horizontalAngle = direction.getOpposite().toYRot(); - - float flapScale = direction.getAxis() == Direction.Axis.X ? 1 : -1; - - ArrayList flaps = new ArrayList<>(4); - - for (int segment = 0; segment <= 3; segment++) { - float intensity = segment == 3 ? 1.5f : segment + 1; - float segmentOffset = -3.05f / 16f * segment + 0.075f / 16f; - - FlapInstance key = model.createInstance(); - - key.setPosition(getVisualPosition()) - .setSegmentOffset(segmentOffset, 0, 0) - .light(blockLight, skyLight) - .setHorizontalAngle(horizontalAngle) - .setFlapness(flapness) - .setFlapScale(flapScale) - .setPivotVoxelSpace(0, 10, 1) - .setIntensity(intensity) - .setChanged(); - - flaps.add(key); - } - - tunnelFlaps.put(direction, flaps); + tunnelFlaps.put(direction, flapSide); }); } @@ -77,42 +44,47 @@ public class BeltTunnelVisual extends AbstractBlockEntityVisual { - LerpedFloat lerpedFloat = blockEntity.flaps.get(direction); - if (lerpedFloat == null) - return; + updateFlaps(ctx.partialTick()); + } - float flapness = lerpedFloat.getValue(ctx.partialTick()); - for (FlapInstance flap : keys) { - flap.setFlapness(flapness) - .setChanged(); - } + private void updateFlaps(float partialTicks) { + tunnelFlaps.forEach((direction, keys) -> { + LerpedFloat lerpedFloat = blockEntity.flaps.get(direction); + if (lerpedFloat == null) { + return; + } + + keys.update(lerpedFloat.getValue(partialTicks)); }); - } + } - @Override + @Override public void updateLight(float partialTick) { - relight(tunnelFlaps.values().stream().flatMap(Collection::stream).toArray(FlatLit[]::new)); + // Need to save the packed light in case we need to recreate the instances. + light = computePackedLight(); + for (FlapStuffs.Visual value : tunnelFlaps.values()) { + value.updateLight(light); + } } @Override protected void _delete() { tunnelFlaps.values() - .stream() - .flatMap(Collection::stream) - .forEach(AbstractInstance::delete); + .forEach(FlapStuffs.Visual::delete); + + tunnelFlaps.clear(); } @Override public void collectCrumblingInstances(Consumer consumer) { - tunnelFlaps.values() - .stream() - .flatMap(Collection::stream) - .forEach(consumer); + for (FlapStuffs.Visual value : tunnelFlaps.values()) { + value.collectCrumblingInstances(consumer); + } } } diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlock.java index 5812add243..6147caa956 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlock.java @@ -28,17 +28,16 @@ public class BrassTunnelBlock extends BeltTunnelBlock { @Override public InteractionResult use(BlockState p_225533_1_, Level world, BlockPos pos, Player player, - InteractionHand p_225533_5_, BlockHitResult p_225533_6_) { + InteractionHand p_225533_5_, BlockHitResult p_225533_6_) { return onBlockEntityUse(world, pos, be -> { - if (!(be instanceof BrassTunnelBlockEntity)) + if (!(be instanceof BrassTunnelBlockEntity bte)) return InteractionResult.PASS; - BrassTunnelBlockEntity bte = (BrassTunnelBlockEntity) be; List stacksOfGroup = bte.grabAllStacksOfGroup(world.isClientSide); if (stacksOfGroup.isEmpty()) return InteractionResult.PASS; if (world.isClientSide) return InteractionResult.SUCCESS; - for (ItemStack itemStack : stacksOfGroup) + for (ItemStack itemStack : stacksOfGroup) player.getInventory().placeItemBackInInventory(itemStack.copy()); world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f, 1f + world.random.nextFloat()); @@ -53,7 +52,7 @@ public class BrassTunnelBlock extends BeltTunnelBlock { @Override public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor worldIn, - BlockPos currentPos, BlockPos facingPos) { + BlockPos currentPos, BlockPos facingPos) { return super.updateShape(state, facing, facingState, worldIn, currentPos, facingPos); } diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlockEntity.java index 2a4506f89a..4522c3aa2c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlockEntity.java @@ -14,7 +14,7 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; import com.simibubi.create.content.kinetics.belt.BeltHelper; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; @@ -28,13 +28,13 @@ import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIc import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -51,6 +51,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; @@ -75,6 +76,7 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa // Couple>> distributionTargets; + private boolean newItemArrived; private boolean syncedOutputActive; private Set syncSet; @@ -98,7 +100,7 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); behaviours.add(selectionMode = new ScrollOptionBehaviour<>(SelectionMode.class, - Lang.translateDirect("logistics.when_multiple_outputs_available"), this, new BrassTunnelModeSlot())); + CreateLang.translateDirect("logistics.when_multiple_outputs_available"), this, new BrassTunnelModeSlot())); selectionMode.onlyActiveWhen(this::hasDistributionBehaviour); @@ -171,14 +173,19 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa if (distributionTargets.getFirst() .isEmpty() && distributionTargets.getSecond() - .isEmpty()) + .isEmpty()) return; - if (selectionMode.get() != SelectionMode.SYNCHRONIZE || syncedOutputActive) { - distributionProgress = AllConfigs.server().logistics.brassTunnelTimer.get(); - sendData(); + if (newItemArrived) { + newItemArrived = false; + distributionProgress = 2; + } else { + if (selectionMode.get() != SelectionMode.SYNCHRONIZE || syncedOutputActive) { + distributionProgress = AllConfigs.server().logistics.brassTunnelTimer.get(); + sendData(); + } + return; } - return; } if (distributionProgress != 0) @@ -327,6 +334,8 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa stackToDistribute = stack; stackEnteredFrom = enteredFrom; distributionProgress = -1; + if (!stack.isEmpty()) + newItemArrived = true; sendData(); setChanged(); } @@ -367,7 +376,7 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa @Nullable protected ItemStack insertIntoTunnel(BrassTunnelBlockEntity tunnel, Direction side, ItemStack stack, - boolean simulate) { + boolean simulate) { if (stack.isEmpty()) return stack; if (!tunnel.testFlapFilter(side, stack)) @@ -505,7 +514,7 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa } private void addValidOutputsOf(BrassTunnelBlockEntity tunnelBE, - List> validOutputs) { + List> validOutputs) { syncSet.add(tunnelBE); BeltBlockEntity below = BeltHelper.getSegmentBE(level, tunnelBE.worldPosition.below()); if (below == null) @@ -784,13 +793,13 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa if (allStacks.isEmpty()) return false; - Lang.translate("tooltip.brass_tunnel.contains").style(ChatFormatting.WHITE).forGoggles(tooltip); + CreateLang.translate("tooltip.brass_tunnel.contains").style(ChatFormatting.WHITE).forGoggles(tooltip); for (ItemStack item : allStacks) { - Lang.translate("tooltip.brass_tunnel.contains_entry", - Components.translatable(item.getDescriptionId()).getString(), item.getCount()) - .style(ChatFormatting.GRAY).forGoggles(tooltip); + CreateLang.translate("tooltip.brass_tunnel.contains_entry", + Component.translatable(item.getDescriptionId()).getString(), item.getCount()) + .style(ChatFormatting.GRAY).forGoggles(tooltip); } - Lang.translate("tooltip.brass_tunnel.retrieve").style(ChatFormatting.DARK_GRAY).forGoggles(tooltip); + CreateLang.translate("tooltip.brass_tunnel.retrieve").style(ChatFormatting.DARK_GRAY).forGoggles(tooltip); return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelFilterSlot.java index 1c32b74d85..a51b307344 100644 --- a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelFilterSlot.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.logistics.tunnel; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.world.phys.Vec3; public class BrassTunnelFilterSlot extends ValueBoxTransform.Sided { diff --git a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlock.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlock.java index d874732a1a..9f84f30b9a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlock.java @@ -31,7 +31,7 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.Property; -import net.minecraftforge.common.capabilities.ForgeCapabilities; + import net.minecraftforge.common.util.ForgeSoundType; public class ItemVaultBlock extends Block implements IWrenchable, IBE { @@ -84,8 +84,7 @@ public class ItemVaultBlock extends Block implements IWrenchable, IBE { + public static final Codec CODEC = CreateCodecs.ITEM_STACK_HANDLER.xmap( + ItemVaultMountedStorage::new, storage -> storage.wrapped + ); + + protected ItemVaultMountedStorage(MountedItemStorageType type, ItemStackHandler handler) { + super(type, handler); + } + + protected ItemVaultMountedStorage(ItemStackHandler handler) { + this(AllMountedStorageTypes.VAULT.get(), handler); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof ItemVaultBlockEntity vault) { + vault.applyInventoryToBlock(this.wrapped); + } + } + + @Override + public boolean handleInteraction(ServerPlayer player, Contraption contraption, StructureBlockInfo info) { + // vaults should never be opened. + return false; + } + + public static ItemVaultMountedStorage fromVault(ItemVaultBlockEntity vault) { + // Vault inventories have a world-affecting onContentsChanged, copy to a safe one + return new ItemVaultMountedStorage(copyToItemStackHandler(vault.getInventoryOfBlock())); + } + + public static ItemVaultMountedStorage fromLegacy(CompoundTag nbt) { + ItemStackHandler handler = new ItemStackHandler(); + handler.deserializeNBT(nbt); + return new ItemVaultMountedStorage(handler); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorageType.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorageType.java new file mode 100644 index 0000000000..51b065850e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorageType.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.logistics.vault; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class ItemVaultMountedStorageType extends MountedItemStorageType { + public ItemVaultMountedStorageType() { + super(ItemVaultMountedStorage.CODEC); + } + + @Override + @Nullable + public ItemVaultMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + return be instanceof ItemVaultBlockEntity vault ? ItemVaultMountedStorage.fromVault(vault) : null; + } +} diff --git a/src/main/java/com/simibubi/create/content/materials/ExperienceBlock.java b/src/main/java/com/simibubi/create/content/materials/ExperienceBlock.java index 442deccce6..857cc1e098 100644 --- a/src/main/java/com/simibubi/create/content/materials/ExperienceBlock.java +++ b/src/main/java/com/simibubi/create/content/materials/ExperienceBlock.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.materials; -import com.simibubi.create.foundation.utility.VecHelper; - +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.util.RandomSource; diff --git a/src/main/java/com/simibubi/create/content/materials/ExperienceNuggetItem.java b/src/main/java/com/simibubi/create/content/materials/ExperienceNuggetItem.java index 52308dde60..7deb022ed5 100644 --- a/src/main/java/com/simibubi/create/content/materials/ExperienceNuggetItem.java +++ b/src/main/java/com/simibubi/create/content/materials/ExperienceNuggetItem.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.materials; -import com.simibubi.create.foundation.utility.VecHelper; - +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.Direction.Axis; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -61,11 +60,11 @@ public class ExperienceNuggetItem extends Item { xp.setDeltaMovement(motion); pLevel.addFreshEntity(xp); } - + itemInHand.shrink(amountUsed); if (!itemInHand.isEmpty()) return InteractionResultHolder.success(itemInHand); - + pPlayer.setItemInHand(pUsedHand, ItemStack.EMPTY); return InteractionResultHolder.consume(itemInHand); } diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinBlock.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlock.java index 26cafec475..d665206853 100644 --- a/src/main/java/com/simibubi/create/content/processing/basin/BasinBlock.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlock.java @@ -41,6 +41,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -61,7 +62,7 @@ public class BasinBlock extends Block implements IBE, IWrencha protected void createBlockStateDefinition(Builder p_206840_1_) { super.createBlockStateDefinition(p_206840_1_.add(FACING)); } - + public static boolean isBasin(LevelReader world, BlockPos pos) { return world.getBlockEntity(pos) instanceof BasinBlockEntity; } @@ -84,7 +85,7 @@ public class BasinBlock extends Block implements IBE, IWrencha @Override public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { + BlockHitResult hit) { ItemStack heldItem = player.getItemInHand(handIn); return onBlockEntityUse(worldIn, pos, be -> { @@ -100,9 +101,9 @@ public class BasinBlock extends Block implements IBE, IWrencha if (heldItem.getItem() .equals(Items.SPONGE) && !be.getCapability(ForgeCapabilities.FLUID_HANDLER) - .map(iFluidHandler -> iFluidHandler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.EXECUTE)) - .orElse(FluidStack.EMPTY) - .isEmpty()) { + .map(iFluidHandler -> iFluidHandler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.EXECUTE)) + .orElse(FluidStack.EMPTY) + .isEmpty()) { return InteractionResult.SUCCESS; } return InteractionResult.PASS; @@ -133,24 +134,17 @@ public class BasinBlock extends Block implements IBE, IWrencha if (!worldIn.getBlockState(entityIn.blockPosition()) .is(this)) return; - if (!(entityIn instanceof ItemEntity)) + if (!(entityIn instanceof ItemEntity itemEntity)) return; if (!entityIn.isAlive()) return; - ItemEntity itemEntity = (ItemEntity) entityIn; withBlockEntityDo(worldIn, entityIn.blockPosition(), be -> { - - // Tossed items bypass the quarter-stack limit - be.inputInventory.withMaxStackSize(64); ItemStack insertItem = ItemHandlerHelper.insertItem(be.inputInventory, itemEntity.getItem() .copy(), false); - be.inputInventory.withMaxStackSize(16); - if (insertItem.isEmpty()) { itemEntity.discard(); return; } - itemEntity.setItem(insertItem); }); } @@ -212,8 +206,7 @@ public class BasinBlock extends Block implements IBE, IWrencha return false; } else { BlockEntity blockEntity = world.getBlockEntity(output); - if (blockEntity instanceof BeltBlockEntity) { - BeltBlockEntity belt = (BeltBlockEntity) blockEntity; + if (blockEntity instanceof BeltBlockEntity belt) { return belt.getSpeed() == 0 || belt.getMovementFacing() != direction.getOpposite(); } } diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinBlockEntity.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlockEntity.java index 0f78978363..b57e9ea75b 100644 --- a/src/main/java/com/simibubi/create/content/processing/basin/BasinBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlockEntity.java @@ -11,7 +11,7 @@ import javax.annotation.Nonnull; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllParticleTypes; import com.simibubi.create.AllTags; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.content.fluids.FluidFX; import com.simibubi.create.content.fluids.particle.FluidParticleData; import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; @@ -28,19 +28,18 @@ import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipul import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.LangBuilder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -59,6 +58,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; @@ -256,12 +256,11 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf } BlockEntity blockEntity = level.getBlockEntity(worldPosition.above(2)); - if (!(blockEntity instanceof MechanicalMixerBlockEntity)) { + if (!(blockEntity instanceof MechanicalMixerBlockEntity mixer)) { setAreFluidsMoving(false); return; } - MechanicalMixerBlockEntity mixer = (MechanicalMixerBlockEntity) blockEntity; setAreFluidsMoving(mixer.running && mixer.runningTicks <= 20); } @@ -384,15 +383,15 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf IItemHandler targetInv = be == null ? null : be.getCapability(ForgeCapabilities.ITEM_HANDLER, direction.getOpposite()) - .orElse(inserter == null ? null : inserter.getInventory()); + .orElse(inserter == null ? null : inserter.getInventory()); IFluidHandler targetTank = be == null ? null : be.getCapability(ForgeCapabilities.FLUID_HANDLER, direction.getOpposite()) - .orElse(null); + .orElse(null); boolean update = false; - for (Iterator iterator = spoutputBuffer.iterator(); iterator.hasNext();) { + for (Iterator iterator = spoutputBuffer.iterator(); iterator.hasNext(); ) { ItemStack itemStack = iterator.next(); if (direction == Direction.DOWN) { @@ -422,7 +421,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf itemStack.setCount(remainder.getCount()); } - for (Iterator iterator = spoutputFluidBuffer.iterator(); iterator.hasNext();) { + for (Iterator iterator = spoutputFluidBuffer.iterator(); iterator.hasNext(); ) { FluidStack fluidStack = iterator.next(); if (direction == Direction.DOWN) { @@ -536,10 +535,10 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf be == null ? null : BlockEntityBehaviour.get(level, be.getBlockPos(), InvManipulationBehaviour.TYPE); IItemHandler targetInv = be == null ? null : be.getCapability(ForgeCapabilities.ITEM_HANDLER, direction.getOpposite()) - .orElse(inserter == null ? null : inserter.getInventory()); + .orElse(inserter == null ? null : inserter.getInventory()); IFluidHandler targetTank = be == null ? null : be.getCapability(ForgeCapabilities.FLUID_HANDLER, direction.getOpposite()) - .orElse(null); + .orElse(null); boolean externalTankNotPresent = targetTank == null; if (!outputItems.isEmpty() && targetInv == null) @@ -584,7 +583,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf } private boolean acceptFluidOutputsIntoBasin(List outputFluids, boolean simulate, - IFluidHandler targetTank) { + IFluidHandler targetTank) { for (FluidStack fluidStack : outputFluids) { FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE; int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler @@ -742,7 +741,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - Lang.translate("gui.goggles.basin_contents") + CreateLang.translate("gui.goggles.basin_contents") .forGoggles(tooltip); IItemHandlerModifiable items = itemCapability.orElse(new ItemStackHandler()); @@ -753,25 +752,25 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf ItemStack stackInSlot = items.getStackInSlot(i); if (stackInSlot.isEmpty()) continue; - Lang.text("") - .add(Components.translatable(stackInSlot.getDescriptionId()) + CreateLang.text("") + .add(Component.translatable(stackInSlot.getDescriptionId()) .withStyle(ChatFormatting.GRAY)) - .add(Lang.text(" x" + stackInSlot.getCount()) + .add(CreateLang.text(" x" + stackInSlot.getCount()) .style(ChatFormatting.GREEN)) .forGoggles(tooltip, 1); isEmpty = false; } - LangBuilder mb = Lang.translate("generic.unit.millibuckets"); + LangBuilder mb = CreateLang.translate("generic.unit.millibuckets"); for (int i = 0; i < fluids.getTanks(); i++) { FluidStack fluidStack = fluids.getFluidInTank(i); if (fluidStack.isEmpty()) continue; - Lang.text("") - .add(Lang.fluidName(fluidStack) - .add(Lang.text(" ")) + CreateLang.text("") + .add(CreateLang.fluidName(fluidStack) + .add(CreateLang.text(" ")) .style(ChatFormatting.GRAY) - .add(Lang.number(fluidStack.getAmount()) + .add(CreateLang.number(fluidStack.getAmount()) .add(mb) .style(ChatFormatting.BLUE))) .forGoggles(tooltip, 1); diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinInventory.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinInventory.java index 63121355dc..8cb674203a 100644 --- a/src/main/java/com/simibubi/create/content/processing/basin/BasinInventory.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinInventory.java @@ -8,14 +8,19 @@ import net.minecraftforge.items.ItemHandlerHelper; public class BasinInventory extends SmartInventory { private BasinBlockEntity blockEntity; + + public boolean packagerMode; public BasinInventory(int slots, BasinBlockEntity be) { - super(slots, be, 16, true); + super(slots, be, 64, true); this.blockEntity = be; } @Override public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (packagerMode) // Unique stack insertion only matters for belt setups + return inv.insertItem(slot, stack, simulate); + int firstFreeSlot = -1; for (int i = 0; i < getSlots(); i++) { diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinMovementBehaviour.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinMovementBehaviour.java index 85f183bac8..5f21a3fd6e 100644 --- a/src/main/java/com/simibubi/create/content/processing/basin/BasinMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinMovementBehaviour.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.processing.basin; import java.util.HashMap; import java.util.Map; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import net.minecraft.core.Direction; @@ -11,6 +11,7 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.items.ItemStackHandler; public class BasinMovementBehaviour implements MovementBehaviour { diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinRecipe.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinRecipe.java index 3bb7827151..81effe6c25 100644 --- a/src/main/java/com/simibubi/create/content/processing/basin/BasinRecipe.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinRecipe.java @@ -16,23 +16,25 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; import com.simibubi.create.foundation.fluid.FluidIngredient; -import com.simibubi.create.foundation.item.SmartInventory; import com.simibubi.create.foundation.recipe.DummyCraftingContainer; import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.Minecraft; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.level.Level; + import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; -public class BasinRecipe extends ProcessingRecipe { +public class BasinRecipe extends ProcessingRecipe { public static boolean match(BasinBlockEntity basin, Recipe recipe) { FilteringBehaviour filter = basin.getFilter(); @@ -41,12 +43,11 @@ public class BasinRecipe extends ProcessingRecipe { boolean filterTest = filter.test(recipe.getResultItem(basin.getLevel() .registryAccess())); - if (recipe instanceof BasinRecipe) { - BasinRecipe basinRecipe = (BasinRecipe) recipe; + if (recipe instanceof BasinRecipe basinRecipe) { if (basinRecipe.getRollableResults() .isEmpty() && !basinRecipe.getFluidResults() - .isEmpty()) + .isEmpty()) filterTest = filter.test(basinRecipe.getFluidResults() .get(0)); } @@ -93,9 +94,8 @@ public class BasinRecipe extends ProcessingRecipe { int[] extractedItemsFromSlot = new int[availableItems.getSlots()]; int[] extractedFluidsFromTank = new int[availableFluids.getTanks()]; - Ingredients: for (int i = 0; i < ingredients.size(); i++) { - Ingredient ingredient = ingredients.get(i); - + Ingredients: + for (Ingredient ingredient : ingredients) { for (int slot = 0; slot < availableItems.getSlots(); slot++) { if (simulate && availableItems.getStackInSlot(slot) .getCount() <= extractedItemsFromSlot[slot]) @@ -114,8 +114,8 @@ public class BasinRecipe extends ProcessingRecipe { } boolean fluidsAffected = false; - FluidIngredients: for (int i = 0; i < fluidIngredients.size(); i++) { - FluidIngredient fluidIngredient = fluidIngredients.get(i); + FluidIngredients: + for (FluidIngredient fluidIngredient : fluidIngredients) { int amountRequired = fluidIngredient.getRequiredAmount(); for (int tank = 0; tank < availableFluids.getTanks(); tank++) { @@ -148,23 +148,24 @@ public class BasinRecipe extends ProcessingRecipe { } if (simulate) { + CraftingContainer remainderContainer = new DummyCraftingContainer(availableItems, extractedItemsFromSlot); + if (recipe instanceof BasinRecipe basinRecipe) { recipeOutputItems.addAll(basinRecipe.rollResults()); - + for (FluidStack fluidStack : basinRecipe.getFluidResults()) if (!fluidStack.isEmpty()) recipeOutputFluids.add(fluidStack); - for (ItemStack stack : basinRecipe.getRemainingItems(basin.getInputInventory())) + for (ItemStack stack : basinRecipe.getRemainingItems(remainderContainer)) if (!stack.isEmpty()) recipeOutputItems.add(stack); - + } else { recipeOutputItems.add(recipe.getResultItem(basin.getLevel() .registryAccess())); if (recipe instanceof CraftingRecipe craftingRecipe) { - for (ItemStack stack : craftingRecipe - .getRemainingItems(new DummyCraftingContainer(availableItems, extractedItemsFromSlot))) + for (ItemStack stack : craftingRecipe.getRemainingItems(remainderContainer)) if (!stack.isEmpty()) recipeOutputItems.add(stack); } @@ -225,7 +226,7 @@ public class BasinRecipe extends ProcessingRecipe { } @Override - public boolean matches(SmartInventory inv, @Nonnull Level worldIn) { + public boolean matches(Container inv, @Nonnull Level worldIn) { return false; } diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinRenderer.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinRenderer.java index 9d4dec2043..97a5475241 100644 --- a/src/main/java/com/simibubi/create/content/processing/basin/BasinRenderer.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinRenderer.java @@ -5,12 +5,12 @@ import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTank import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -72,7 +72,7 @@ public class BasinRenderer extends SmartBlockEntityRenderer { if (fluidLevel > 0) { ms.translate(0, (Mth.sin( - AnimationTickHolder.getRenderTime(basin.getLevel()) / 12f + anglePartition * itemCount) + 1.5f) + AnimationTickHolder.getRenderTime(basin.getLevel()) / 12f + anglePartition * itemCount) + 1.5f) * 1 / 32f, 0); } @@ -171,8 +171,8 @@ public class BasinRenderer extends SmartBlockEntityRenderer { float partial = Mth.clamp(units / totalUnits, 0, 1); xMax += partial * 12 / 16f; - FluidRenderer.renderFluidBox(renderedFluid, xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light, - false); + FluidRenderer.renderFluidBox(renderedFluid.getFluid(), renderedFluid.getAmount(), xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light, + false, false, renderedFluid.getTag()); xMin = xMax; } diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlock.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlock.java index 94383c534d..f04f03d9bb 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlock.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlock.java @@ -10,10 +10,12 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; +import com.simibubi.create.content.logistics.stockTicker.StockTickerInteractionHandler; import com.simibubi.create.content.processing.basin.BasinBlockEntity; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.advancements.critereon.StatePropertiesPredicate; import net.minecraft.core.BlockPos; @@ -49,6 +51,7 @@ import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.FakePlayer; @@ -75,9 +78,8 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE< if (world.isClientSide) return; BlockEntity blockEntity = world.getBlockEntity(pos.above()); - if (!(blockEntity instanceof BasinBlockEntity)) + if (!(blockEntity instanceof BasinBlockEntity basin)) return; - BasinBlockEntity basin = (BasinBlockEntity) blockEntity; basin.notifyChangeOfContents(); } @@ -101,7 +103,7 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE< @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult blockRayTraceResult) { + BlockHitResult blockRayTraceResult) { ItemStack heldItem = player.getItemInHand(hand); HeatLevel heat = state.getValue(HEAT_LEVEL); @@ -114,6 +116,14 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE< return InteractionResult.SUCCESS; }); + BlazeBurnerBlockEntity be = getBlockEntity(world, pos); + if (be != null && be.stockKeeper) { + StockTickerBlockEntity stockTicker = BlazeBurnerBlockEntity.getStockTicker(world, pos); + if (stockTicker != null) + StockTickerInteractionHandler.interactWithLogisticsManagerAt(player, world, stockTicker.getBlockPos()); + return InteractionResult.SUCCESS; + } + if (heldItem.isEmpty() && heat != HeatLevel.NONE) return onBlockEntityUse(world, pos, bbte -> { if (!bbte.goggles) @@ -155,14 +165,13 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE< } public static InteractionResultHolder tryInsert(BlockState state, Level world, BlockPos pos, - ItemStack stack, boolean doNotConsume, boolean forceOverflow, boolean simulate) { + ItemStack stack, boolean doNotConsume, boolean forceOverflow, boolean simulate) { if (!state.hasBlockEntity()) return InteractionResultHolder.fail(ItemStack.EMPTY); BlockEntity be = world.getBlockEntity(pos); - if (!(be instanceof BlazeBurnerBlockEntity)) + if (!(be instanceof BlazeBurnerBlockEntity burnerBE)) return InteractionResultHolder.fail(ItemStack.EMPTY); - BlazeBurnerBlockEntity burnerBE = (BlazeBurnerBlockEntity) be; if (burnerBE.isCreativeFuel(stack)) { if (!simulate) @@ -203,7 +212,7 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE< @Override public VoxelShape getCollisionShape(BlockState p_220071_1_, BlockGetter p_220071_2_, BlockPos p_220071_3_, - CollisionContext p_220071_4_) { + CollisionContext p_220071_4_) { if (p_220071_4_ == CollisionContext.empty()) return AllShapes.HEATER_BLOCK_SPECIAL_COLLISION_SHAPE; return getShape(p_220071_1_, p_220071_2_, p_220071_3_, p_220071_4_); @@ -245,9 +254,9 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE< public static int getLight(BlockState state) { HeatLevel level = state.getValue(HEAT_LEVEL); return switch (level) { - case NONE -> 0; - case SMOULDERING -> 8; - default -> 15; + case NONE -> 0; + case SMOULDERING -> 8; + default -> 15; }; } @@ -269,7 +278,8 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE< } public enum HeatLevel implements StringRepresentable { - NONE, SMOULDERING, FADING, KINDLED, SEETHING,; + NONE, SMOULDERING, FADING, KINDLED, SEETHING, + ; public static HeatLevel byIndex(int index) { return values()[index]; diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockEntity.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockEntity.java index e5352a8dff..e0119575a7 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockEntity.java @@ -2,19 +2,24 @@ package com.simibubi.create.content.processing.burner; import java.util.List; +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.content.fluids.tank.FluidTankBlock; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; import com.simibubi.create.content.processing.basin.BasinBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; -import dev.engine_room.flywheel.api.backend.BackendManager; +import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -26,6 +31,8 @@ import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -38,13 +45,16 @@ public class BlazeBurnerBlockEntity extends SmartBlockEntity { public static final int MAX_HEAT_CAPACITY = 10000; public static final int INSERTION_THRESHOLD = 500; + public LerpedFloat headAnimation; + public boolean stockKeeper; + public boolean isCreative; + public boolean goggles; + public boolean hat; + protected FuelType activeFuel; protected int remainingBurnTime; - protected LerpedFloat headAnimation; protected LerpedFloat headAngle; - protected boolean isCreative; - protected boolean goggles; - protected boolean hat; + public BlazeBurnerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -54,6 +64,7 @@ public class BlazeBurnerBlockEntity extends SmartBlockEntity { headAngle = LerpedFloat.angular(); isCreative = false; goggles = false; + stockKeeper = false; headAngle.startWithValue((AngleHelper.horizontalAngle(state.getOptionalValue(BlazeBurnerBlock.FACING) .orElse(Direction.SOUTH)) + 180) % 360); @@ -103,10 +114,30 @@ public class BlazeBurnerBlockEntity extends SmartBlockEntity { updateBlockState(); } + @Override + public void lazyTick() { + super.lazyTick(); + stockKeeper = getStockTicker(level, worldPosition) != null; + } + + @Nullable + public static StockTickerBlockEntity getStockTicker(LevelAccessor level, BlockPos pos) { + for (Direction direction : Iterate.horizontalDirections) { + if (level instanceof Level l && !l.isLoaded(pos)) + return null; + BlockState blockState = level.getBlockState(pos.relative(direction)); + if (!AllBlocks.STOCK_TICKER.has(blockState)) + continue; + if (level.getBlockEntity(pos.relative(direction)) instanceof StockTickerBlockEntity stbe) + return stbe; + } + return null; + } + @OnlyIn(Dist.CLIENT) private boolean shouldTickAnimation() { // Offload the animation tick to the visual when flywheel in enabled - return !BackendManager.isBackendOn(); + return !VisualizationManager.supportsVisualization(level); } @OnlyIn(Dist.CLIENT) @@ -174,6 +205,13 @@ public class BlazeBurnerBlockEntity extends SmartBlockEntity { return BlazeBurnerBlock.getHeatLevelOf(getBlockState()); } + public BlazeBurnerBlock.HeatLevel getHeatLevelForRender() { + HeatLevel heatLevel = getHeatLevelFromBlock(); + if (!heatLevel.isAtLeast(HeatLevel.FADING) && stockKeeper) + return HeatLevel.FADING; + return heatLevel; + } + public void updateBlockState() { setBlockHeat(getHeatLevel()); } diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockItem.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockItem.java index ce0202417b..7d7989ea86 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockItem.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockItem.java @@ -9,9 +9,9 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllEntityTags; -import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.math.VecHelper; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; @@ -63,7 +63,7 @@ public class BlazeBurnerBlockItem extends BlockItem { @Override public String getDescriptionId() { - return hasCapturedBlaze() ? super.getDescriptionId() : "item.create." + RegisteredObjects.getKeyOrThrow(this).getPath(); + return hasCapturedBlaze() ? super.getDescriptionId() : "item.create." + CatnipServices.REGISTRIES.getKeyOrThrow(this).getPath(); } @Override diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerHandler.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerHandler.java index d491f20483..ad57746932 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerHandler.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerHandler.java @@ -22,6 +22,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.event.entity.ProjectileImpactEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -47,7 +48,7 @@ public class BlazeBurnerHandler { BlockEntity blockEntity = projectile.level() .getBlockEntity(BlockPos.containing(event.getRayTraceResult() .getLocation())); - if (!(blockEntity instanceof BlazeBurnerBlockEntity)) { + if (!(blockEntity instanceof BlazeBurnerBlockEntity heater)) { return; } @@ -59,7 +60,6 @@ public class BlazeBurnerHandler { if (world.isClientSide) return; - BlazeBurnerBlockEntity heater = (BlazeBurnerBlockEntity) blockEntity; if (!heater.isCreative()) { if (heater.activeFuel != FuelType.SPECIAL) { heater.activeFuel = FuelType.NORMAL; @@ -77,9 +77,8 @@ public class BlazeBurnerHandler { Projectile projectile = event.getProjectile(); if (projectile.level().isClientSide) return; - if (!(projectile instanceof ThrownPotion)) + if (!(projectile instanceof ThrownPotion entity)) return; - ThrownPotion entity = (ThrownPotion) projectile; if (event.getRayTraceResult() .getType() != HitResult.Type.BLOCK) diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerMovementBehaviour.java index 3074fc8afc..4f9477f4a8 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerMovementBehaviour.java @@ -1,19 +1,19 @@ package com.simibubi.create.content.processing.burner; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.trains.entity.CarriageContraption; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.Direction; @@ -25,6 +25,7 @@ import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerRenderer.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerRenderer.java index 002b4c9366..4cc509ded1 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerRenderer.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerRenderer.java @@ -9,16 +9,16 @@ import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.virtualWorld.VirtualRenderWorld; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SpriteShiftEntry; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -35,7 +35,7 @@ public class BlazeBurnerRenderer extends SafeBlockEntityRenderer 0.125f; float time = AnimationTickHolder.getRenderTime(level); @@ -117,7 +116,7 @@ public class BlazeBurnerRenderer extends SafeBlockEntityRenderer implements SimpleDynamicVisual, SimpleTickableVisual { - private final BlazeBurnerBlock.HeatLevel heatLevel; + private BlazeBurnerBlock.HeatLevel heatLevel; private final TransformedInstance head; - private final TransformedInstance smallRods; - private final TransformedInstance largeRods; private final boolean isInert; + @Nullable + private TransformedInstance smallRods; + @Nullable + private TransformedInstance largeRods; @Nullable private ScrollInstance flame; @Nullable @@ -49,7 +52,7 @@ public class BlazeBurnerVisual extends AbstractBlockEntityVisual 0.125f; + HeatLevel heatLevel = blockEntity.getHeatLevelForRender(); - if (validBlockAbove != this.validBlockAbove) { + if (validBlockAbove != this.validBlockAbove || heatLevel != this.heatLevel) { this.validBlockAbove = validBlockAbove; PartialModel blazeModel = BlazeBurnerRenderer.getBlazeModel(heatLevel, validBlockAbove); instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(blazeModel)) .stealInstance(head); + + boolean needsRods = heatLevel.isAtLeast(BlazeBurnerBlock.HeatLevel.FADING); + boolean hasRods = this.heatLevel.isAtLeast(HeatLevel.FADING); + + if (needsRods && !hasRods) { + PartialModel rodsModel = heatLevel == BlazeBurnerBlock.HeatLevel.SEETHING ? AllPartialModels.BLAZE_BURNER_SUPER_RODS + : AllPartialModels.BLAZE_BURNER_RODS; + PartialModel rodsModel2 = heatLevel == BlazeBurnerBlock.HeatLevel.SEETHING ? AllPartialModels.BLAZE_BURNER_SUPER_RODS_2 + : AllPartialModels.BLAZE_BURNER_RODS_2; + + smallRods = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(rodsModel)) + .createInstance(); + largeRods = instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(rodsModel2)) + .createInstance(); + + smallRods.light(LightTexture.FULL_BRIGHT); + largeRods.light(LightTexture.FULL_BRIGHT); + + } else if (!needsRods && hasRods) { + if (smallRods != null) + smallRods.delete(); + if (largeRods != null) + largeRods.delete(); + smallRods = null; + largeRods = null; + } + + this.heatLevel = heatLevel; } // Switch between showing/hiding the flame @@ -125,11 +139,15 @@ public class BlazeBurnerVisual extends AbstractBlockEntityVisual isValidConductor; - private final TrainConductorHandler.UpdateScheduleCallback callback; - - public BlockBasedTrainConductorInteractionBehaviour(Predicate isValidConductor, TrainConductorHandler.UpdateScheduleCallback callback) { - this.isValidConductor = isValidConductor; - this.callback = callback; - } - - @Override - public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, - AbstractContraptionEntity contraptionEntity) { - ItemStack itemInHand = player.getItemInHand(activeHand); - - if (!(contraptionEntity instanceof CarriageContraptionEntity carriageEntity)) - return false; - if (activeHand == InteractionHand.OFF_HAND) - return false; - Contraption contraption = carriageEntity.getContraption(); - if (!(contraption instanceof CarriageContraption carriageContraption)) - return false; - - StructureBlockInfo info = carriageContraption.getBlocks() - .get(localPos); - if (info == null || !isValidConductor.test(info.state())) - return false; - - Direction assemblyDirection = carriageContraption.getAssemblyDirection(); - for (Direction direction : Iterate.directionsInAxis(assemblyDirection.getAxis())) { - if (!carriageContraption.inControl(localPos, direction)) - continue; - - Train train = carriageEntity.getCarriage().train; - if (train == null) - return false; - if (player.level().isClientSide) - return true; - - if (train.runtime.getSchedule() != null) { - if (train.runtime.paused && !train.runtime.completed) { - train.runtime.paused = false; - AllSoundEvents.CONFIRM.playOnServer(player.level(), player.blockPosition(), 1, 1); - player.displayClientMessage(Lang.translateDirect("schedule.continued"), true); - return true; - } - - if (!itemInHand.isEmpty()) { - AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); - player.displayClientMessage(Lang.translateDirect("schedule.remove_with_empty_hand"), true); - return true; - } - - AllSoundEvents.playItemPickup(player); - player.displayClientMessage(Lang.translateDirect( - train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"), - true); - player.setItemInHand(activeHand, train.runtime.returnSchedule()); - callback.update(false, info.state(), newBlockState -> setBlockState(localPos, contraptionEntity, newBlockState)); - return true; - } - - if (!AllItems.SCHEDULE.isIn(itemInHand)) - return true; - - Schedule schedule = ScheduleItem.getSchedule(itemInHand); - if (schedule == null) - return false; - - if (schedule.entries.isEmpty()) { - AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); - player.displayClientMessage(Lang.translateDirect("schedule.no_stops"), true); - return true; - } - callback.update(true, info.state(), newBlockState -> setBlockState(localPos, contraptionEntity, newBlockState)); - train.runtime.setSchedule(schedule, false); - AllAdvancements.CONDUCTOR.awardTo(player); - AllSoundEvents.CONFIRM.playOnServer(player.level(), player.blockPosition(), 1, 1); - player.displayClientMessage(Lang.translateDirect("schedule.applied_to_train") - .withStyle(ChatFormatting.GREEN), true); - itemInHand.shrink(1); - player.setItemInHand(activeHand, itemInHand.isEmpty() ? ItemStack.EMPTY : itemInHand); - return true; - } - - player.displayClientMessage(Lang.translateDirect("schedule.non_controlling_seat"), true); - AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); - return true; - } - - private void setBlockState(BlockPos localPos, AbstractContraptionEntity contraption, BlockState newState) { - StructureTemplate.StructureBlockInfo info = contraption.getContraption().getBlocks().get(localPos); - if (info != null) { - setContraptionBlockData(contraption, localPos, new StructureTemplate.StructureBlockInfo(info.pos(), newState, info.nbt())); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/processing/burner/LitBlazeBurnerBlock.java b/src/main/java/com/simibubi/create/content/processing/burner/LitBlazeBurnerBlock.java index c989a5ea4f..1382f79b77 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/LitBlazeBurnerBlock.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/LitBlazeBurnerBlock.java @@ -6,8 +6,8 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.Create; import com.simibubi.create.content.equipment.wrench.IWrenchable; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.sounds.SoundEvents; diff --git a/src/main/java/com/simibubi/create/content/processing/burner/ScrollInstance.java b/src/main/java/com/simibubi/create/content/processing/burner/ScrollInstance.java index 12bcc25e1a..bcf394450f 100644 --- a/src/main/java/com/simibubi/create/content/processing/burner/ScrollInstance.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/ScrollInstance.java @@ -1,13 +1,15 @@ package com.simibubi.create.content.processing.burner; import org.joml.Quaternionf; +import org.joml.Quaternionfc; import dev.engine_room.flywheel.api.instance.InstanceHandle; import dev.engine_room.flywheel.api.instance.InstanceType; -import dev.engine_room.flywheel.lib.instance.ColoredLitInstance; +import dev.engine_room.flywheel.lib.instance.ColoredLitOverlayInstance; +import net.createmod.catnip.render.SpriteShiftEntry; import net.minecraft.core.Vec3i; -public class ScrollInstance extends ColoredLitInstance { +public class ScrollInstance extends ColoredLitOverlayInstance { public float x; public float y; public float z; @@ -16,13 +18,16 @@ public class ScrollInstance extends ColoredLitInstance { public float speedU; public float speedV; + public float offsetU; + public float offsetV; + public float diffU; public float diffV; public float scaleU; public float scaleV; - public ScrollInstance(InstanceType type, InstanceHandle handle) { + public ScrollInstance(InstanceType type, InstanceHandle handle) { super(type, handle); } @@ -32,4 +37,58 @@ public class ScrollInstance extends ColoredLitInstance { this.z = position.getZ(); return this; } + + public ScrollInstance position(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } + + public ScrollInstance shift(float x, float y, float z) { + this.x += x; + this.y += y; + this.z += z; + return this; + } + + public ScrollInstance rotation(Quaternionfc rotation) { + this.rotation.set(rotation); + return this; + } + + public ScrollInstance setSpriteShift(SpriteShiftEntry spriteShift) { + return setSpriteShift(spriteShift, 0.5f, 0.5f); + } + public ScrollInstance setSpriteShift(SpriteShiftEntry spriteShift, float factorU, float factorV) { + float spriteWidth = spriteShift.getTarget() + .getU1() + - spriteShift.getTarget() + .getU0(); + + float spriteHeight = spriteShift.getTarget() + .getV1() + - spriteShift.getTarget() + .getV0(); + + scaleU = spriteWidth * factorU; + scaleV = spriteHeight * factorV; + + diffU = spriteShift.getTarget().getU0() - spriteShift.getOriginal().getU0(); + diffV = spriteShift.getTarget().getV0() - spriteShift.getOriginal().getV0(); + + return this; + } + + public ScrollInstance speed(float speedU, float speedV) { + this.speedU = speedU; + this.speedV = speedV; + return this; + } + + public ScrollInstance offset(float offsetU, float offsetV) { + this.offsetU = offsetU; + this.offsetV = offsetV; + return this; + } } diff --git a/src/main/java/com/simibubi/create/content/processing/burner/ScrollTransformedInstance.java b/src/main/java/com/simibubi/create/content/processing/burner/ScrollTransformedInstance.java new file mode 100644 index 0000000000..920435cc50 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/processing/burner/ScrollTransformedInstance.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.processing.burner; + +import dev.engine_room.flywheel.api.instance.InstanceHandle; +import dev.engine_room.flywheel.api.instance.InstanceType; +import dev.engine_room.flywheel.lib.instance.TransformedInstance; +import net.createmod.catnip.render.SpriteShiftEntry; + +public class ScrollTransformedInstance extends TransformedInstance { + public float speedU; + public float speedV; + + public float offsetU; + public float offsetV; + + public float diffU; + public float diffV; + + public float scaleU; + public float scaleV; + + public ScrollTransformedInstance(InstanceType type, InstanceHandle handle) { + super(type, handle); + } + + public ScrollTransformedInstance setSpriteShift(SpriteShiftEntry spriteShift) { + return setSpriteShift(spriteShift, 0.5f, 0.5f); + } + + public ScrollTransformedInstance setSpriteShift(SpriteShiftEntry spriteShift, float factorU, float factorV) { + float spriteWidth = spriteShift.getTarget() + .getU1() + - spriteShift.getTarget() + .getU0(); + + float spriteHeight = spriteShift.getTarget() + .getV1() + - spriteShift.getTarget() + .getV0(); + + scaleU = spriteWidth * factorU; + scaleV = spriteHeight * factorV; + + diffU = spriteShift.getTarget().getU0() - spriteShift.getOriginal().getU0(); + diffV = spriteShift.getTarget().getV0() - spriteShift.getOriginal().getV0(); + + return this; + } + + public ScrollTransformedInstance speed(float speedU, float speedV) { + this.speedU = speedU; + this.speedV = speedV; + return this; + } + + public ScrollTransformedInstance offset(float offsetU, float offsetV) { + this.offsetU = offsetU; + this.offsetV = offsetV; + return this; + } +} diff --git a/src/main/java/com/simibubi/create/content/processing/recipe/HeatCondition.java b/src/main/java/com/simibubi/create/content/processing/recipe/HeatCondition.java index da0a350fd2..9c26f0bb52 100644 --- a/src/main/java/com/simibubi/create/content/processing/recipe/HeatCondition.java +++ b/src/main/java/com/simibubi/create/content/processing/recipe/HeatCondition.java @@ -3,7 +3,8 @@ package com.simibubi.create.content.processing.recipe; import com.simibubi.create.Create; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.utility.Lang; + +import net.createmod.catnip.lang.Lang; public enum HeatCondition { diff --git a/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingOutput.java b/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingOutput.java index 10fb8f942e..9c7e654694 100644 --- a/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingOutput.java +++ b/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingOutput.java @@ -8,9 +8,9 @@ import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.TagParser; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -61,7 +61,7 @@ public class ProcessingOutput { public JsonElement serialize() { JsonObject json = new JsonObject(); - ResourceLocation resourceLocation = compatDatagenOutput == null ? RegisteredObjects.getKeyOrThrow(stack + ResourceLocation resourceLocation = compatDatagenOutput == null ? CatnipServices.REGISTRIES.getKeyOrThrow(stack .getItem()) : compatDatagenOutput.getFirst(); json.addProperty("item", resourceLocation.toString()); int count = compatDatagenOutput == null ? stack.getCount() : compatDatagenOutput.getSecond(); diff --git a/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingRecipeBuilder.java b/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingRecipeBuilder.java index 7004a95d0c..d9cc5cdd98 100644 --- a/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingRecipeBuilder.java +++ b/src/main/java/com/simibubi/create/content/processing/recipe/ProcessingRecipeBuilder.java @@ -11,9 +11,9 @@ import com.simibubi.create.foundation.data.recipe.Mods; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; -import com.simibubi.create.foundation.utility.Pair; import com.tterrag.registrate.util.DataIngredient; +import net.createmod.catnip.data.Pair; import net.minecraft.core.NonNullList; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.resources.ResourceLocation; @@ -31,12 +31,13 @@ import net.minecraftforge.common.crafting.conditions.NotCondition; import net.minecraftforge.fluids.FluidStack; public class ProcessingRecipeBuilder> { - + protected ResourceLocation recipeId; protected ProcessingRecipeFactory factory; protected ProcessingRecipeParams params; protected List recipeConditions; public ProcessingRecipeBuilder(ProcessingRecipeFactory factory, ResourceLocation recipeId) { + this.recipeId = recipeId; params = new ProcessingRecipeParams(recipeId); recipeConditions = new ArrayList<>(); this.factory = factory; @@ -170,6 +171,10 @@ public class ProcessingRecipeBuilder> { return output(new ProcessingOutput(Pair.of(mod.asResource(id), amount), chance)); } + public ProcessingRecipeBuilder output(ResourceLocation id) { + return output(1, id, 1); + } + public ProcessingRecipeBuilder output(Mods mod, String id) { return output(1, mod.asResource(id), 1); } diff --git a/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyItem.java b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyItem.java index 9d0eb16730..760620fae9 100644 --- a/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyItem.java +++ b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyItem.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.processing.sequenced; -import com.simibubi.create.foundation.utility.Color; - +import net.createmod.catnip.theme.Color; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipe.java b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipe.java index e13da99f6c..dc1a5a6eeb 100644 --- a/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipe.java +++ b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipe.java @@ -13,14 +13,14 @@ import com.simibubi.create.Create; import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.core.RegistryAccess; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Container; @@ -31,6 +31,7 @@ import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.event.entity.player.ItemTooltipEvent; @@ -58,18 +59,18 @@ public class SequencedAssemblyRecipe implements Recipe { } public static > Optional getRecipe(Level world, C inv, - RecipeType type, Class recipeClass) { + RecipeType type, Class recipeClass) { return getRecipe(world, inv, type, recipeClass, r -> r.matches(inv, world)); } public static > Optional getRecipe(Level world, C inv, - RecipeType type, Class recipeClass, Predicate recipeFilter) { + RecipeType type, Class recipeClass, Predicate recipeFilter) { return getRecipes(world, inv.getItem(0), type, recipeClass).filter(recipeFilter) .findFirst(); } public static > Optional getRecipe(Level world, ItemStack item, - RecipeType type, Class recipeClass) { + RecipeType type, Class recipeClass) { List all = world.getRecipeManager() .getAllRecipesFor(AllRecipeTypes.SEQUENCED_ASSEMBLY.getType()); for (SequencedAssemblyRecipe sequencedAssemblyRecipe : all) { @@ -86,21 +87,21 @@ public class SequencedAssemblyRecipe implements Recipe { } public static > Stream getRecipes(Level world, ItemStack item, - RecipeType type, Class recipeClass) { + RecipeType type, Class recipeClass) { List all = world.getRecipeManager() .getAllRecipesFor(AllRecipeTypes.SEQUENCED_ASSEMBLY.getType()); return all.stream() - .filter(it -> it.appliesTo(item)) - .map(it -> Pair.of(it, it.getNextRecipe(item).getRecipe())) - .filter(it -> it.getSecond() - .getType() == type && recipeClass.isInstance(it.getSecond())) - .map(it -> { - it.getSecond() - .enforceNextResult(() -> it.getFirst().advance(item)); - return it.getSecond(); - }) - .map(recipeClass::cast); + .filter(it -> it.appliesTo(item)) + .map(it -> Pair.of(it, it.getNextRecipe(item).getRecipe())) + .filter(it -> it.getSecond() + .getType() == type && recipeClass.isInstance(it.getSecond())) + .map(it -> { + it.getSecond() + .enforceNextResult(() -> it.getFirst().advance(item)); + return it.getSecond(); + }) + .map(recipeClass::cast); } private ItemStack advance(ItemStack input) { @@ -158,9 +159,9 @@ public class SequencedAssemblyRecipe implements Recipe { return true; return input.hasTag() && getTransitionalItem().getItem() == input.getItem() && input.getTag() .contains("SequencedAssembly") && input.getTag() - .getCompound("SequencedAssembly") - .getString("id") - .equals(id.toString()); + .getCompound("SequencedAssembly") + .getString("id") + .equals(id.toString()); } private SequencedRecipe getNextRecipe(ItemStack input) { @@ -241,18 +242,17 @@ public class SequencedAssemblyRecipe implements Recipe { if (!optionalRecipe.isPresent()) return; Recipe recipe = optionalRecipe.get(); - if (!(recipe instanceof SequencedAssemblyRecipe)) + if (!(recipe instanceof SequencedAssemblyRecipe sequencedAssemblyRecipe)) return; - SequencedAssemblyRecipe sequencedAssemblyRecipe = (SequencedAssemblyRecipe) recipe; int length = sequencedAssemblyRecipe.sequence.size(); int step = sequencedAssemblyRecipe.getStep(stack); int total = length * sequencedAssemblyRecipe.loops; List tooltip = event.getToolTip(); - tooltip.add(Components.immutableEmpty()); - tooltip.add(Lang.translateDirect("recipe.sequenced_assembly") + tooltip.add(CommonComponents.EMPTY); + tooltip.add(CreateLang.translateDirect("recipe.sequenced_assembly") .withStyle(ChatFormatting.GRAY)); - tooltip.add(Lang.translateDirect("recipe.assembly.progress", step, total) + tooltip.add(CreateLang.translateDirect("recipe.assembly.progress", step, total) .withStyle(ChatFormatting.DARK_GRAY)); int remaining = total - step; @@ -263,11 +263,12 @@ public class SequencedAssemblyRecipe implements Recipe { Component textComponent = sequencedRecipe.getAsAssemblyRecipe() .getDescriptionForAssembly(); if (i == 0) - tooltip.add(Lang.translateDirect("recipe.assembly.next", textComponent) + tooltip.add(CreateLang.translateDirect("recipe.assembly.next", textComponent) .withStyle(ChatFormatting.AQUA)); - else - tooltip.add(Components.literal("-> ").append(textComponent) + else { + tooltip.add(Component.literal("-> ").append(textComponent) .withStyle(ChatFormatting.DARK_AQUA)); + } } } diff --git a/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedRecipe.java b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedRecipe.java index 76c5f34262..a9bf8ebde7 100644 --- a/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedRecipe.java +++ b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedRecipe.java @@ -5,14 +5,15 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeSerializer; + import net.minecraftforge.common.crafting.conditions.ICondition.IContext; import net.minecraftforge.registries.ForgeRegistries; @@ -36,7 +37,7 @@ public class SequencedRecipe> { @SuppressWarnings("unchecked") ProcessingRecipeSerializer serializer = (ProcessingRecipeSerializer) wrapped.getSerializer(); JsonObject json = new JsonObject(); - json.addProperty("type", RegisteredObjects.getKeyOrThrow(serializer) + json.addProperty("type", CatnipServices.REGISTRIES.getKeyOrThrow(serializer) .toString()); serializer.write(json, wrapped); return json; @@ -46,9 +47,7 @@ public class SequencedRecipe> { ResourceLocation parentId = parent.getId(); Recipe recipe = RecipeManager.fromJson( new ResourceLocation(parentId.getNamespace(), parentId.getPath() + "_step_" + index), json, IContext.EMPTY); - if (recipe instanceof ProcessingRecipe && recipe instanceof IAssemblyRecipe) { - ProcessingRecipe processingRecipe = (ProcessingRecipe) recipe; - IAssemblyRecipe assemblyRecipe = (IAssemblyRecipe) recipe; + if (recipe instanceof ProcessingRecipe processingRecipe && recipe instanceof IAssemblyRecipe assemblyRecipe) { if (assemblyRecipe.supportsAssembly()) { Ingredient transit = Ingredient.of(parent.getTransitionalItem()); processingRecipe.getIngredients() @@ -63,7 +62,7 @@ public class SequencedRecipe> { public void writeToBuffer(FriendlyByteBuf buffer) { @SuppressWarnings("unchecked") ProcessingRecipeSerializer serializer = (ProcessingRecipeSerializer) wrapped.getSerializer(); - buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow(serializer)); + buffer.writeResourceLocation(CatnipServices.REGISTRIES.getKeyOrThrow(serializer)); buffer.writeResourceLocation(wrapped.getId()); serializer.toNetwork(buffer, wrapped); } diff --git a/src/main/java/com/simibubi/create/content/redstone/DirectedDirectionalBlock.java b/src/main/java/com/simibubi/create/content/redstone/DirectedDirectionalBlock.java index 50c77a6981..ceb784aea7 100644 --- a/src/main/java/com/simibubi/create/content/redstone/DirectedDirectionalBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/DirectedDirectionalBlock.java @@ -2,7 +2,7 @@ package com.simibubi.create.content.redstone; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.api.contraption.transformable.TransformableBlock; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.equipment.wrench.IWrenchable; @@ -17,7 +17,7 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.properties.AttachFace; import net.minecraft.world.level.block.state.properties.EnumProperty; -public class DirectedDirectionalBlock extends HorizontalDirectionalBlock implements IWrenchable, ITransformableBlock { +public class DirectedDirectionalBlock extends HorizontalDirectionalBlock implements IWrenchable, TransformableBlock { public static final EnumProperty TARGET = EnumProperty.create("target", AttachFace.class); diff --git a/src/main/java/com/simibubi/create/content/redstone/FilteredDetectorFilterSlot.java b/src/main/java/com/simibubi/create/content/redstone/FilteredDetectorFilterSlot.java index 616e256d53..3ff1cdb6ed 100644 --- a/src/main/java/com/simibubi/create/content/redstone/FilteredDetectorFilterSlot.java +++ b/src/main/java/com/simibubi/create/content/redstone/FilteredDetectorFilterSlot.java @@ -2,12 +2,14 @@ package com.simibubi.create.content.redstone; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -40,8 +42,8 @@ public class FilteredDetectorFilterSlot extends ValueBoxTransform.Sided { } @Override - public void rotate(BlockState state, PoseStack ms) { - super.rotate(state, ms); + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { + super.rotate(level, pos, state, ms); Direction facing = state.getValue(DirectedDirectionalBlock.FACING); if (facing.getAxis() == Axis.Y) return; diff --git a/src/main/java/com/simibubi/create/content/redstone/RoseQuartzLampBlock.java b/src/main/java/com/simibubi/create/content/redstone/RoseQuartzLampBlock.java index 7fb27315b5..100acdb5ab 100644 --- a/src/main/java/com/simibubi/create/content/redstone/RoseQuartzLampBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/RoseQuartzLampBlock.java @@ -8,8 +8,8 @@ import java.util.function.BiConsumer; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.redstone.diodes.BrassDiodeBlock; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlockEntity.java index 53b0c6b837..e1196c177f 100644 --- a/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlockEntity.java @@ -2,13 +2,13 @@ package com.simibubi.create.content.redstone.analogLever; import java.util.List; -import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -79,7 +79,7 @@ public class AnalogLeverBlockEntity extends SmartBlockEntity implements IHaveGog @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - Lang.translate("tooltip.analogStrength", this.state).forGoggles(tooltip); + CreateLang.translate("tooltip.analogStrength", this.state).forGoggles(tooltip); return true; } diff --git a/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverRenderer.java b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverRenderer.java index e544e026a2..f5a2e8055c 100644 --- a/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverRenderer.java +++ b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverRenderer.java @@ -4,12 +4,12 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Color; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -34,7 +34,7 @@ public class AnalogLeverRenderer extends SafeBlockEntityRenderer { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public DeskBellBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(FACING, Direction.UP) + .setValue(POWERED, false) + .setValue(WATERLOGGED, false)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return withWater(defaultBlockState().setValue(FACING, context.getClickedFace()), context); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pPos); + return pState; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.DESK_BELL.get(pState.getValue(FACING)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED, WATERLOGGED)); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + playSound(pPlayer, pLevel, pPos); + if (pLevel.isClientSide) + return InteractionResult.SUCCESS; + pLevel.setBlock(pPos, pState.setValue(POWERED, true), 3); + updateNeighbours(pState, pLevel, pPos); + withBlockEntityDo(pLevel, pPos, DeskBellBlockEntity::ding); + return InteractionResult.SUCCESS; + } + + public void playSound(@Nullable Player pPlayer, LevelAccessor pLevel, BlockPos pPos) { + if (pLevel instanceof Level level) + AllSoundEvents.DESK_BELL_USE.play(level, pPlayer, pPos); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + if (!pIsMoving && !pState.is(pNewState.getBlock())) + if (pState.getValue(POWERED)) + updateNeighbours(pState, pLevel, pPos); + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + @Override + public int getSignal(BlockState pBlockState, BlockGetter pBlockAccess, BlockPos pPos, Direction pSide) { + return pBlockState.getValue(POWERED) ? 15 : 0; + } + + @Override + public int getDirectSignal(BlockState pBlockState, BlockGetter pBlockAccess, BlockPos pPos, Direction pSide) { + return pBlockState.getValue(POWERED) && getConnectedDirection(pBlockState) == pSide ? 15 : 0; + } + + @Override + public boolean isSignalSource(BlockState pState) { + return true; + } + + public void unPress(BlockState pState, Level pLevel, BlockPos pPos) { + pLevel.setBlock(pPos, pState.setValue(POWERED, false), 3); + updateNeighbours(pState, pLevel, pPos); + } + + protected void updateNeighbours(BlockState pState, Level pLevel, BlockPos pPos) { + pLevel.updateNeighborsAt(pPos, this); + pLevel.updateNeighborsAt(pPos.relative(getConnectedDirection(pState).getOpposite()), this); + } + + private Direction getConnectedDirection(BlockState pState) { + return pState.getOptionalValue(FACING) + .orElse(Direction.UP); + } + + @Override + public Class getBlockEntityClass() { + return DeskBellBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.DESK_BELL.get(); + } + + @Override + public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/deskBell/DeskBellBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/deskBell/DeskBellBlockEntity.java new file mode 100644 index 0000000000..22a49a14d4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/deskBell/DeskBellBlockEntity.java @@ -0,0 +1,84 @@ +package com.simibubi.create.content.redstone.deskBell; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class DeskBellBlockEntity extends SmartBlockEntity { + + public LerpedFloat animation = LerpedFloat.linear() + .startWithValue(0); + + public boolean ding; + + int blockStateTimer; + float animationOffset; + + public DeskBellBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + blockStateTimer = 0; + } + + @Override + public void tick() { + super.tick(); + animation.tickChaser(); + + if (level.isClientSide) + return; + if (blockStateTimer == 0) + return; + + blockStateTimer--; + + if (blockStateTimer > 0) + return; + BlockState blockState = getBlockState(); + if (blockState.getValue(DeskBellBlock.POWERED)) + AllBlocks.DESK_BELL.get() + .unPress(blockState, level, worldPosition); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + if (clientPacket && ding) + NBTHelper.putMarker(tag, "Ding"); + ding = false; + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + if (clientPacket && tag.contains("Ding")) + ding(); + } + + public void ding() { + if (!level.isClientSide) { + blockStateTimer = 20; + ding = true; + sendData(); + return; + } + + animationOffset = level.random.nextFloat() * 2 * Mth.PI; + animation.startWithValue(1) + .chase(0, 0.05, Chaser.LINEAR); + } + + @Override + public void addBehaviours(List behaviours) {} + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/deskBell/DeskBellRenderer.java b/src/main/java/com/simibubi/create/content/redstone/deskBell/DeskBellRenderer.java new file mode 100644 index 0000000000..ba92910306 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/deskBell/DeskBellRenderer.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.redstone.deskBell; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; + +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class DeskBellRenderer extends SmartBlockEntityRenderer { + + public DeskBellRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(DeskBellBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + BlockState blockState = blockEntity.getBlockState(); + float p = blockEntity.animation.getValue(partialTicks); + if (p < 0.004 && !blockState.getOptionalValue(DeskBellBlock.POWERED) + .orElse(false)) + return; + + float f = (float) (1 - 4 * Math.pow((Math.max(p - 0.5, 0)) - 0.5, 2)); + float f2 = (float) (Math.pow(p, 1.25f)); + + Direction facing = blockState.getValue(DeskBellBlock.FACING); + + CachedBuffers.partial(AllPartialModels.DESK_BELL_PLUNGER, blockState) + .center() + .rotateYDegrees(AngleHelper.horizontalAngle(facing)) + .rotateXDegrees(AngleHelper.verticalAngle(facing) + 90) + .uncenter() + .translate(0, f * -.75f / 16f, 0) + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + + CachedBuffers.partial(AllPartialModels.DESK_BELL_BELL, blockState) + .center() + .rotateYDegrees(AngleHelper.horizontalAngle(facing)) + .rotateXDegrees(AngleHelper.verticalAngle(facing) + 90) + .translate(0, -1 / 16, 0) + .rotateXDegrees(f2 * 8 * Mth.sin(p * Mth.PI * 4 + blockEntity.animationOffset)) + .rotateZDegrees(f2 * 8 * Mth.cos(p * Mth.PI * 4 + blockEntity.animationOffset)) + .translate(0, 1 / 16, 0) + .scale(0.995f) + .uncenter() + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlock.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlock.java index c80c6a4a97..74510831a3 100644 --- a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlock.java @@ -91,8 +91,9 @@ public class BrassDiodeBlock extends AbstractDiodeBlock implements IBE getBlockEntityType() { - return AllBlocks.PULSE_EXTENDER.is(this) ? AllBlockEntityTypes.PULSE_EXTENDER.get() - : AllBlockEntityTypes.PULSE_REPEATER.get(); + return AllBlocks.PULSE_TIMER.is(this) ? AllBlockEntityTypes.PULSE_TIMER.get() + : AllBlocks.PULSE_EXTENDER.is(this) ? AllBlockEntityTypes.PULSE_EXTENDER.get() + : AllBlockEntityTypes.PULSE_REPEATER.get(); } } diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlockEntity.java index 9de08f8d5b..971ea3a50b 100644 --- a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlockEntity.java @@ -8,7 +8,7 @@ import com.simibubi.create.content.equipment.clipboard.ClipboardCloneable; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -30,14 +30,18 @@ public abstract class BrassDiodeBlockEntity extends SmartBlockEntity implements @Override public void addBehaviours(List behaviours) { - maxState = new BrassDiodeScrollValueBehaviour(Lang.translateDirect("logistics.redstone_interval"), this, + maxState = new BrassDiodeScrollValueBehaviour(CreateLang.translateDirect("logistics.redstone_interval"), this, new BrassDiodeScrollSlot()).between(2, 60 * 20 * 60); maxState.withFormatter(this::format); maxState.withCallback(this::onMaxDelayChanged); - maxState.setValue(2); + maxState.setValue(defaultValue()); behaviours.add(maxState); } + protected int defaultValue() { + return 2; + } + public float getProgress() { int max = Math.max(2, maxState.getValue()); return Mth.clamp(state, 0, max) / (float) max; @@ -88,7 +92,7 @@ public abstract class BrassDiodeBlockEntity extends SmartBlockEntity implements public String getClipboardKey() { return "Block"; } - + @Override public boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate) { if (!tag.contains("Inverted")) @@ -100,12 +104,12 @@ public abstract class BrassDiodeBlockEntity extends SmartBlockEntity implements level.setBlockAndUpdate(worldPosition, blockState.cycle(BrassDiodeBlock.INVERTED)); return true; } - + @Override public boolean writeToClipboard(CompoundTag tag, Direction side) { tag.putBoolean("Inverted", getBlockState().getOptionalValue(BrassDiodeBlock.INVERTED) .orElse(false)); return true; } - + } diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeRenderer.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeRenderer.java index 3cf4a8d0fc..d4912448ca 100644 --- a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeRenderer.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeRenderer.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.redstone.diodes; import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.blockEntity.renderer.ColoredOverlayBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.Color; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.theme.Color; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; public class BrassDiodeRenderer extends ColoredOverlayBlockEntityRenderer { @@ -21,7 +21,7 @@ public class BrassDiodeRenderer extends ColoredOverlayBlockEntityRenderer Math.max(2, value) + "t"; case 1 -> "0:" + (value < 10 ? "0" : "") + value; default -> value + ":00"; }); } - + @Override public String getClipboardKey() { return "Timings"; diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeVisual.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeVisual.java index 76693e75f2..bbcfa8a1dc 100644 --- a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeVisual.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeVisual.java @@ -3,7 +3,6 @@ package com.simibubi.create.content.redstone.diodes; import java.util.function.Consumer; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.utility.Color; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.visual.TickableVisual; @@ -13,6 +12,7 @@ import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual; +import net.createmod.catnip.theme.Color; public class BrassDiodeVisual extends AbstractBlockEntityVisual implements SimpleTickableVisual { diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/PulseTimerBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/diodes/PulseTimerBlockEntity.java new file mode 100644 index 0000000000..4b6ad09289 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/PulseTimerBlockEntity.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.redstone.diodes; + +import static com.simibubi.create.content.redstone.diodes.BrassDiodeBlock.POWERING; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class PulseTimerBlockEntity extends BrassDiodeBlockEntity { + + public PulseTimerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected int defaultValue() { + return 20; + } + + @Override + protected void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin) { + if (powered || state >= maxState.getValue() - 1) + state = 0; + else + state++; + + if (level.isClientSide) + return; + + boolean shouldPower = !powered && (maxState.getValue() == 2 ? state == 0 : state <= 1); + BlockState blockState = getBlockState(); + if (blockState.getValue(POWERING) != shouldPower) + level.setBlockAndUpdate(worldPosition, blockState.setValue(POWERING, shouldPower)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java deleted file mode 100644 index ea79b70bd9..0000000000 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java +++ /dev/null @@ -1,246 +0,0 @@ -package com.simibubi.create.content.redstone.displayLink; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.annotation.Nullable; - -import com.simibubi.create.Create; -import com.simibubi.create.compat.Mods; -import com.simibubi.create.content.redstone.displayLink.source.ComputerDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.DeathCounterDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.EnchantPowerDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.RedstonePowerDisplaySource; -import com.simibubi.create.content.redstone.displayLink.source.ScoreboardDisplaySource; -import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; -import com.simibubi.create.content.redstone.displayLink.target.LecternDisplayTarget; -import com.simibubi.create.content.redstone.displayLink.target.SignDisplayTarget; -import com.simibubi.create.foundation.utility.AttachedRegistry; -import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.tterrag.registrate.util.nullness.NonNullConsumer; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.entity.SignBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; - -public class AllDisplayBehaviours { - public static final Map GATHERER_BEHAVIOURS = new HashMap<>(); - - private static final AttachedRegistry> SOURCES_BY_BLOCK = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final AttachedRegistry, List> SOURCES_BY_BLOCK_ENTITY = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); - - private static final AttachedRegistry TARGETS_BY_BLOCK = new AttachedRegistry<>(ForgeRegistries.BLOCKS); - private static final AttachedRegistry, DisplayTarget> TARGETS_BY_BLOCK_ENTITY = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); - - public static DisplayBehaviour register(ResourceLocation id, DisplayBehaviour behaviour) { - behaviour.id = id; - GATHERER_BEHAVIOURS.put(id, behaviour); - return behaviour; - } - - public static void assignBlock(DisplayBehaviour behaviour, ResourceLocation block) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK.get(block); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK.register(block, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK.register(block, target); - } - } - - public static void assignBlockEntity(DisplayBehaviour behaviour, ResourceLocation beType) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK_ENTITY.get(beType); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK_ENTITY.register(beType, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK_ENTITY.register(beType, target); - } - } - - public static void assignBlock(DisplayBehaviour behaviour, Block block) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK.get(block); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK.register(block, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK.register(block, target); - } - } - - public static void assignBlockEntity(DisplayBehaviour behaviour, BlockEntityType beType) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK_ENTITY.get(beType); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK_ENTITY.register(beType, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK_ENTITY.register(beType, target); - } - } - - public static NonNullConsumer assignDataBehaviour(DisplayBehaviour behaviour, - String... suffix) { - return b -> { - ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(b); - String idSuffix = behaviour instanceof DisplaySource ? "_source" : "_target"; - if (suffix.length > 0) - idSuffix += "_" + suffix[0]; - assignBlock(register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), - behaviour), registryName); - }; - } - - public static > NonNullConsumer assignDataBehaviourBE( - DisplayBehaviour behaviour, String... suffix) { - return b -> { - ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(b); - String idSuffix = behaviour instanceof DisplaySource ? "_source" : "_target"; - if (suffix.length > 0) - idSuffix += "_" + suffix[0]; - assignBlockEntity( - register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), - behaviour), - registryName); - }; - } - - // - - @Nullable - public static DisplaySource getSource(ResourceLocation resourceLocation) { - DisplayBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null); - if (available instanceof DisplaySource source) - return source; - return null; - } - - @Nullable - public static DisplayTarget getTarget(ResourceLocation resourceLocation) { - DisplayBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null); - if (available instanceof DisplayTarget target) - return target; - return null; - } - - // - - public static List sourcesOf(Block block) { - List sources = SOURCES_BY_BLOCK.get(block); - if (sources == null) { - return Collections.emptyList(); - } - return sources; - } - - public static List sourcesOf(BlockState state) { - return sourcesOf(state.getBlock()); - } - - public static List sourcesOf(BlockEntityType blockEntityType) { - List sources = SOURCES_BY_BLOCK_ENTITY.get(blockEntityType); - if (sources == null) { - return Collections.emptyList(); - } - return sources; - } - - public static List sourcesOf(BlockEntity blockEntity) { - return sourcesOf(blockEntity.getType()); - } - - @Nullable - public static DisplayTarget targetOf(Block block) { - return TARGETS_BY_BLOCK.get(block); - } - - @Nullable - public static DisplayTarget targetOf(BlockState state) { - return targetOf(state.getBlock()); - } - - @Nullable - public static DisplayTarget targetOf(BlockEntityType blockEntityType) { - return TARGETS_BY_BLOCK_ENTITY.get(blockEntityType); - } - - @Nullable - public static DisplayTarget targetOf(BlockEntity blockEntity) { - return targetOf(blockEntity.getType()); - } - - public static List sourcesOf(LevelAccessor level, BlockPos pos) { - BlockState blockState = level.getBlockState(pos); - BlockEntity blockEntity = level.getBlockEntity(pos); - - List sourcesOfBlock = sourcesOf(blockState); - List sourcesOfBlockEntity = blockEntity == null ? Collections.emptyList() : sourcesOf(blockEntity); - - if (sourcesOfBlockEntity.isEmpty()) - return sourcesOfBlock; - return sourcesOfBlockEntity; - } - - @Nullable - public static DisplayTarget targetOf(LevelAccessor level, BlockPos pos) { - BlockState blockState = level.getBlockState(pos); - BlockEntity blockEntity = level.getBlockEntity(pos); - - DisplayTarget targetOfBlock = targetOf(blockState); - DisplayTarget targetOfBlockEntity = blockEntity == null ? null : targetOf(blockEntity); - - // Commonly added by mods, but with a non-vanilla blockentitytype - if (targetOfBlockEntity == null && blockEntity instanceof SignBlockEntity) - targetOfBlockEntity = targetOf(BlockEntityType.SIGN); - - if (targetOfBlockEntity == null) - return targetOfBlock; - return targetOfBlockEntity; - } - - // - - public static void registerDefaults() { - assignBlockEntity(register(Create.asResource("sign_display_target"), new SignDisplayTarget()), BlockEntityType.SIGN); - assignBlockEntity(register(Create.asResource("lectern_display_target"), new LecternDisplayTarget()), BlockEntityType.LECTERN); - assignBlock(register(Create.asResource("death_count_display_source"), new DeathCounterDisplaySource()), Blocks.RESPAWN_ANCHOR); - assignBlockEntity(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK); - assignBlockEntity(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE); - assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET); - - Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { - DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource()); - - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("wired_modem_full")); - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_normal")); - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_advanced")); - assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_command")); - }); - } -} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/ClickToLinkBlockItem.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/ClickToLinkBlockItem.java new file mode 100644 index 0000000000..19108c7dba --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/ClickToLinkBlockItem.java @@ -0,0 +1,185 @@ +package com.simibubi.create.content.redstone.displayLink; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.outliner.Outliner; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.Event.Result; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public abstract class ClickToLinkBlockItem extends BlockItem { + + public ClickToLinkBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @SubscribeEvent + public static void linkableItemAlwaysPlacesWhenUsed(PlayerInteractEvent.RightClickBlock event) { + ItemStack usedItem = event.getItemStack(); + if (!(usedItem.getItem() instanceof ClickToLinkBlockItem blockItem)) + return; + if (event.getLevel() + .getBlockState(event.getPos()) + .is(blockItem.getBlock())) + return; + event.setUseBlock(Result.DENY); + } + + @Override + public InteractionResult useOn(UseOnContext pContext) { + ItemStack stack = pContext.getItemInHand(); + BlockPos pos = pContext.getClickedPos(); + Level level = pContext.getLevel(); + BlockState state = level.getBlockState(pos); + Player player = pContext.getPlayer(); + String msgKey = getMessageTranslationKey(); + int maxDistance = getMaxDistanceFromSelection(); + + if (player == null) + return InteractionResult.FAIL; + + if (player.isShiftKeyDown() && stack.hasTag()) { + if (level.isClientSide) + return InteractionResult.SUCCESS; + player.displayClientMessage(CreateLang.translateDirect(msgKey + ".clear"), true); + stack.setTag(null); + return InteractionResult.SUCCESS; + } + + String placedDim = level.dimension() + .location() + .toString(); + + if (!stack.hasTag()) { + if (!isValidTarget(level, pos)) { + if (placeWhenInvalid()) { + InteractionResult useOn = super.useOn(pContext); + if (level.isClientSide || useOn == InteractionResult.FAIL) + return useOn; + + ItemStack itemInHand = player.getItemInHand(pContext.getHand()); + if (!itemInHand.isEmpty()) + itemInHand.setTag(null); + return useOn; + } + + if (level.isClientSide) + AllSoundEvents.DENY.playFrom(player); + player.displayClientMessage(CreateLang.translateDirect(msgKey + ".invalid"), true); + return InteractionResult.FAIL; + } + + if (level.isClientSide) + return InteractionResult.SUCCESS; + CompoundTag stackTag = stack.getOrCreateTag(); + stackTag.put("SelectedPos", NbtUtils.writeBlockPos(pos)); + stackTag.putString("SelectedDimension", placedDim); + + player.displayClientMessage(CreateLang.translateDirect(msgKey + ".set"), true); + stack.setTag(stackTag); + return InteractionResult.SUCCESS; + } + + CompoundTag tag = stack.getTag(); + CompoundTag teTag = new CompoundTag(); + + BlockPos selectedPos = NbtUtils.readBlockPos(tag.getCompound("SelectedPos")); + String selectedDim = tag.getString("SelectedDimension"); + BlockPos placedPos = pos.relative(pContext.getClickedFace(), state.canBeReplaced() ? 0 : 1); + + if (maxDistance != -1 && (!selectedPos.closerThan(placedPos, maxDistance) || !selectedDim.equals(placedDim))) { + player.displayClientMessage(CreateLang.translateDirect(msgKey + ".too_far") + .withStyle(ChatFormatting.RED), true); + return InteractionResult.FAIL; + } + + teTag.put("TargetOffset", NbtUtils.writeBlockPos(selectedPos.subtract(placedPos))); + teTag.putString("TargetDimension", selectedDim); + tag.put("BlockEntityTag", teTag); + + InteractionResult useOn = super.useOn(pContext); + if (level.isClientSide || useOn == InteractionResult.FAIL) + return useOn; + + ItemStack itemInHand = player.getItemInHand(pContext.getHand()); + if (!itemInHand.isEmpty()) + itemInHand.setTag(null); + player.displayClientMessage(CreateLang.translateDirect(msgKey + ".success") + .withStyle(ChatFormatting.GREEN), true); + return useOn; + } + + private static BlockPos lastShownPos = null; + private static AABB lastShownAABB = null; + + @OnlyIn(Dist.CLIENT) + public static void clientTick() { + Player player = Minecraft.getInstance().player; + if (player == null) + return; + ItemStack heldItemMainhand = player.getMainHandItem(); + if (!(heldItemMainhand.getItem() instanceof ClickToLinkBlockItem blockItem)) + return; + if (!heldItemMainhand.hasTag()) + return; + CompoundTag stackTag = heldItemMainhand.getOrCreateTag(); + if (!stackTag.contains("SelectedPos")) + return; + + BlockPos selectedPos = NbtUtils.readBlockPos(stackTag.getCompound("SelectedPos")); + + if (!selectedPos.equals(lastShownPos)) { + lastShownAABB = blockItem.getSelectionBounds(selectedPos); + lastShownPos = selectedPos; + } + + Outliner.getInstance().showAABB("target", lastShownAABB) + .colored(0xffcb74) + .lineWidth(1 / 16f); + } + + public abstract int getMaxDistanceFromSelection(); + + public abstract String getMessageTranslationKey(); + + public boolean placeWhenInvalid() { + return false; + } + + public boolean isValidTarget(LevelAccessor level, BlockPos pos) { + return true; + } + + @OnlyIn(Dist.CLIENT) + public AABB getSelectionBounds(BlockPos pos) { + Level world = Minecraft.getInstance().level; + BlockState state = world.getBlockState(pos); + VoxelShape shape = state.getShape(world, pos); + return shape.isEmpty() ? new AABB(BlockPos.ZERO) + : shape.bounds() + .move(pos); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayBehaviour.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayBehaviour.java deleted file mode 100644 index 7c067394d2..0000000000 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayBehaviour.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.simibubi.create.content.redstone.displayLink; - -import net.minecraft.resources.ResourceLocation; - -public abstract class DisplayBehaviour { - - public ResourceLocation id; - -} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlock.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlock.java index f5ed8a9799..04abdd055c 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlock.java @@ -6,15 +6,15 @@ import java.util.function.Consumer; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplaySource; import com.simibubi.create.content.redstone.displayLink.source.RedstonePowerDisplaySource; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -38,6 +38,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -64,6 +65,11 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements IBE< AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); } + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + public static void notifyGatherers(LevelAccessor level, BlockPos pos) { forEachAttachedGatherer(level, pos, DisplayLinkBlockEntity::tickSource); } @@ -151,7 +157,7 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements IBE< if (!(player instanceof LocalPlayer)) return; if (be.targetOffset.equals(BlockPos.ZERO)) { - player.displayClientMessage(Lang.translateDirect("display_link.invalid"), true); + player.displayClientMessage(CreateLang.translateDirect("display_link.invalid"), true); return; } ScreenOpener.open(new DisplayLinkScreen(be)); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockEntity.java index 26771c9424..614fceba4d 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockEntity.java @@ -5,17 +5,17 @@ import java.util.List; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplayTarget; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; import com.simibubi.create.compat.computercraft.ComputerCraftProxy; -import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; -import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelPosition; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSupportBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -23,10 +23,12 @@ import net.minecraft.nbt.NbtUtils; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; -public class DisplayLinkBlockEntity extends SmartBlockEntity { +public class DisplayLinkBlockEntity extends LinkWithBulbBlockEntity { protected BlockPos targetOffset; @@ -36,25 +38,23 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { public DisplayTarget activeTarget; public int targetLine; - public LerpedFloat glow; - private boolean sendPulse; - public int refreshTicks; public AbstractComputerBehaviour computerBehaviour; + public FactoryPanelSupportBehaviour factoryPanelSupport; public DisplayLinkBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); targetOffset = BlockPos.ZERO; sourceConfig = new CompoundTag(); targetLine = 0; - glow = LerpedFloat.linear() - .startWithValue(0); - glow.chase(0, 0.5f, Chaser.EXP); } @Override public void addBehaviours(List behaviours) { behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + behaviours.add(factoryPanelSupport = new FactoryPanelSupportBehaviour(this, () -> false, () -> false, () -> { + updateGatheredData(); + })); registerAwardables(behaviours, AllAdvancements.DISPLAY_LINK, AllAdvancements.DISPLAY_BOARD); } @@ -62,17 +62,12 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { public void tick() { super.tick(); - if (isVirtual()) { - glow.tickChaser(); + if (isVirtual()) return; - } - if (activeSource == null) return; - if (level.isClientSide) { - glow.tickChaser(); + if (level.isClientSide) return; - } refreshTicks++; if (refreshTicks < activeSource.getPassiveRefreshTicks() || !activeSource.shouldPassiveReset()) @@ -104,8 +99,8 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { if (!level.isLoaded(targetPosition) || !level.isLoaded(sourcePosition)) return; - DisplayTarget target = AllDisplayBehaviours.targetOf(level, targetPosition); - List sources = AllDisplayBehaviours.sourcesOf(level, sourcePosition); + DisplayTarget target = DisplayTarget.get(level, targetPosition); + List sources = DisplaySource.getAll(level, sourcePosition); boolean notify = false; if (activeTarget != target) { @@ -126,7 +121,7 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { DisplayLinkContext context = new DisplayLinkContext(level, this); activeSource.transferData(context, activeTarget, targetLine); - sendPulse = true; + sendPulseNextSync(); sendData(); award(AllAdvancements.DISPLAY_LINK); @@ -142,11 +137,11 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { protected void write(CompoundTag tag, boolean clientPacket) { super.write(tag, clientPacket); writeGatheredData(tag); - if (clientPacket && activeTarget != null) - tag.putString("TargetType", activeTarget.id.toString()); - if (clientPacket && sendPulse) { - sendPulse = false; - NBTHelper.putMarker(tag, "Pulse"); + if (clientPacket && activeTarget != null) { + ResourceLocation id = CreateBuiltInRegistries.DISPLAY_TARGET.getKey(this.activeTarget); + if (id != null) { + tag.putString("TargetType", id.toString()); + } } } @@ -156,7 +151,10 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { if (activeSource != null) { CompoundTag data = sourceConfig.copy(); - data.putString("Id", activeSource.id.toString()); + ResourceLocation id = CreateBuiltInRegistries.DISPLAY_SOURCE.getKey(this.activeSource); + if (id != null) { + data.putString("Id", id.toString()); + } tag.put("Source", data); } } @@ -168,15 +166,12 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { targetLine = tag.getInt("TargetLine"); if (clientPacket && tag.contains("TargetType")) - activeTarget = AllDisplayBehaviours.getTarget(new ResourceLocation(tag.getString("TargetType"))); - if (clientPacket && tag.contains("Pulse")) - glow.setValue(2); - + activeTarget = DisplayTarget.get(ResourceLocation.tryParse(tag.getString("TargetType"))); if (!tag.contains("Source")) return; CompoundTag data = tag.getCompound("Source"); - activeSource = AllDisplayBehaviours.getSource(new ResourceLocation(data.getString("Id"))); + activeSource = DisplaySource.get(ResourceLocation.tryParse(data.getString("Id"))); sourceConfig = new CompoundTag(); if (activeSource != null) sourceConfig = data.copy(); @@ -202,6 +197,8 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { } public BlockPos getSourcePosition() { + for (FactoryPanelPosition position : factoryPanelSupport.getLinkedPanels()) + return position.pos(); return worldPosition.relative(getDirection()); } @@ -223,4 +220,14 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity { return worldPosition.offset(targetOffset); } + private static final Vec3 bulbOffset = VecHelper.voxelSpace(11, 7, 5); + private static final Vec3 bulbOffsetVertical = VecHelper.voxelSpace(5, 7, 11); + + @Override + public Vec3 getBulbOffset(BlockState state) { + if (state.getOptionalValue(DisplayLinkBlock.FACING).orElse(Direction.UP).getAxis().isVertical()) + return bulbOffsetVertical; + return bulbOffset; + } + } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockItem.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockItem.java index 50d24a8ff7..23549cdfcb 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockItem.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockItem.java @@ -1,149 +1,42 @@ package com.simibubi.create.content.redstone.displayLink; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.CreateClient; -import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.api.behaviour.display.DisplayTarget; import com.simibubi.create.infrastructure.config.AllConfigs; -import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.eventbus.api.Event.Result; -import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber -public class DisplayLinkBlockItem extends BlockItem { +public class DisplayLinkBlockItem extends ClickToLinkBlockItem { public DisplayLinkBlockItem(Block pBlock, Properties pProperties) { super(pBlock, pProperties); } - @SubscribeEvent - public static void gathererItemAlwaysPlacesWhenUsed(PlayerInteractEvent.RightClickBlock event) { - ItemStack usedItem = event.getItemStack(); - if (usedItem.getItem() instanceof DisplayLinkBlockItem) { - if (AllBlocks.DISPLAY_LINK.has(event.getLevel() - .getBlockState(event.getPos()))) - return; - event.setUseBlock(Result.DENY); - } + @OnlyIn(Dist.CLIENT) + public AABB getSelectionBounds(BlockPos pos) { + Level world = Minecraft.getInstance().level; + DisplayTarget target = DisplayTarget.get(world, pos); + if (target != null) + return target.getMultiblockBounds(world, pos); + return super.getSelectionBounds(pos); } @Override - public InteractionResult useOn(UseOnContext pContext) { - ItemStack stack = pContext.getItemInHand(); - BlockPos pos = pContext.getClickedPos(); - Level level = pContext.getLevel(); - BlockState state = level.getBlockState(pos); - Player player = pContext.getPlayer(); - - if (player == null) - return InteractionResult.FAIL; - - if (player.isShiftKeyDown() && stack.hasTag()) { - if (level.isClientSide) - return InteractionResult.SUCCESS; - player.displayClientMessage(Lang.translateDirect("display_link.clear"), true); - stack.setTag(null); - return InteractionResult.SUCCESS; - } - - if (!stack.hasTag()) { - if (level.isClientSide) - return InteractionResult.SUCCESS; - CompoundTag stackTag = stack.getOrCreateTag(); - stackTag.put("SelectedPos", NbtUtils.writeBlockPos(pos)); - player.displayClientMessage(Lang.translateDirect("display_link.set"), true); - stack.setTag(stackTag); - return InteractionResult.SUCCESS; - } - - CompoundTag tag = stack.getTag(); - CompoundTag teTag = new CompoundTag(); - - BlockPos selectedPos = NbtUtils.readBlockPos(tag.getCompound("SelectedPos")); - BlockPos placedPos = pos.relative(pContext.getClickedFace(), state.canBeReplaced() ? 0 : 1); - - if (!selectedPos.closerThan(placedPos, AllConfigs.server().logistics.displayLinkRange.get())) { - player.displayClientMessage(Lang.translateDirect("display_link.too_far") - .withStyle(ChatFormatting.RED), true); - return InteractionResult.FAIL; - } - - teTag.put("TargetOffset", NbtUtils.writeBlockPos(selectedPos.subtract(placedPos))); - tag.put("BlockEntityTag", teTag); - - InteractionResult useOn = super.useOn(pContext); - if (level.isClientSide || useOn == InteractionResult.FAIL) - return useOn; - - ItemStack itemInHand = player.getItemInHand(pContext.getHand()); - if (!itemInHand.isEmpty()) - itemInHand.setTag(null); - player.displayClientMessage(Lang.translateDirect("display_link.success") - .withStyle(ChatFormatting.GREEN), true); - return useOn; + public int getMaxDistanceFromSelection() { + return AllConfigs.server().logistics.displayLinkRange.get(); } - private static BlockPos lastShownPos = null; - private static AABB lastShownAABB = null; - - @OnlyIn(Dist.CLIENT) - public static void clientTick() { - Player player = Minecraft.getInstance().player; - if (player == null) - return; - ItemStack heldItemMainhand = player.getMainHandItem(); - if (!(heldItemMainhand.getItem() instanceof DisplayLinkBlockItem)) - return; - if (!heldItemMainhand.hasTag()) - return; - CompoundTag stackTag = heldItemMainhand.getOrCreateTag(); - if (!stackTag.contains("SelectedPos")) - return; - - BlockPos selectedPos = NbtUtils.readBlockPos(stackTag.getCompound("SelectedPos")); - - if (!selectedPos.equals(lastShownPos)) { - lastShownAABB = getBounds(selectedPos); - lastShownPos = selectedPos; - } - - CreateClient.OUTLINER.showAABB("target", lastShownAABB) - .colored(0xffcb74) - .lineWidth(1 / 16f); - } - - @OnlyIn(Dist.CLIENT) - private static AABB getBounds(BlockPos pos) { - Level world = Minecraft.getInstance().level; - DisplayTarget target = AllDisplayBehaviours.targetOf(world, pos); - - if (target != null) - return target.getMultiblockBounds(world, pos); - - BlockState state = world.getBlockState(pos); - VoxelShape shape = state.getShape(world, pos); - return shape.isEmpty() ? new AABB(BlockPos.ZERO) - : shape.bounds() - .move(pos); + @Override + public String getMessageTranslationKey() { + return "display_link"; } } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkConfigurationPacket.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkConfigurationPacket.java index 70fbba6a63..960e3819d4 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkConfigurationPacket.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkConfigurationPacket.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.redstone.displayLink; -import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplaySource; import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; import net.minecraft.core.BlockPos; @@ -44,8 +44,8 @@ public class DisplayLinkConfigurationPacket extends BlockEntityConfigurationPack return; } - ResourceLocation id = new ResourceLocation(configData.getString("Id")); - DisplaySource source = AllDisplayBehaviours.getSource(id); + ResourceLocation id = ResourceLocation.tryParse(configData.getString("Id")); + DisplaySource source = DisplaySource.get(id); if (source == null) { be.notifyUpdate(); return; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkRenderer.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkRenderer.java deleted file mode 100644 index 9ca03ea537..0000000000 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkRenderer.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.redstone.displayLink; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllPartialModels; -import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.RenderTypes; -import com.simibubi.create.foundation.utility.AngleHelper; - -import dev.engine_room.flywheel.lib.transform.TransformStack; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; - -public class DisplayLinkRenderer extends SafeBlockEntityRenderer { - - public DisplayLinkRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(DisplayLinkBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - float glow = be.glow.getValue(partialTicks); - if (glow < .125f) - return; - - glow = (float) (1 - (2 * Math.pow(glow - .75f, 2))); - glow = Mth.clamp(glow, -1, 1); - - int color = (int) (200 * glow); - - BlockState blockState = be.getBlockState(); - var msr = TransformStack.of(ms); - - Direction face = blockState.getOptionalValue(DisplayLinkBlock.FACING) - .orElse(Direction.UP); - - if (face.getAxis() - .isHorizontal()) - face = face.getOpposite(); - - ms.pushPose(); - - msr.center() - .rotateYDegrees(AngleHelper.horizontalAngle(face)) - .rotateXDegrees(-AngleHelper.verticalAngle(face) - 90) - .uncenter(); - - CachedBufferer.partial(AllPartialModels.DISPLAY_LINK_TUBE, blockState) - .light(LightTexture.FULL_BRIGHT) - .renderInto(ms, buffer.getBuffer(RenderType.translucent())); - - CachedBufferer.partial(AllPartialModels.DISPLAY_LINK_GLOW, blockState) - .light(LightTexture.FULL_BRIGHT) - .color(color, color, color, 255) - .disableDiffuse() - .renderInto(ms, buffer.getBuffer(RenderTypes.additive())); - - ms.popPose(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkScreen.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkScreen.java index d2eb0b13d3..3765a0b48a 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkScreen.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkScreen.java @@ -5,38 +5,40 @@ import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPackets; -import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplayTarget; +import com.simibubi.create.api.registry.CreateBuiltInRegistries; import com.simibubi.create.content.redstone.displayLink.source.SingleLineDisplaySource; -import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.ModularGuiLine; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; -import com.simibubi.create.foundation.gui.widget.ElementWidget; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.ponder.ui.PonderTagScreen; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.infrastructure.ponder.AllPonderTags; +import com.simibubi.create.foundation.utility.CreateLang; +import com.simibubi.create.infrastructure.ponder.AllCreatePonderTags; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.ScreenOpener; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; +import net.createmod.catnip.gui.widget.ElementWidget; +import net.createmod.ponder.foundation.ui.PonderTagScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Block; @@ -75,7 +77,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { @Override protected void init() { - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); super.init(); clearWidgets(); @@ -85,7 +87,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { initGathererOptions(); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(this::onClose); addRenderableWidget(confirmButton); } @@ -94,9 +96,9 @@ public class DisplayLinkScreen extends AbstractSimiScreen { public void tick() { super.tick(); if (sourceState != null && sourceState.getBlock() != minecraft.level.getBlockState(blockEntity.getSourcePosition()) - .getBlock() - || targetState != null && targetState.getBlock() != minecraft.level.getBlockState(blockEntity.getTargetPosition()) - .getBlock()) + .getBlock() + || targetState != null && targetState.getBlock() != minecraft.level.getBlockState(blockEntity.getTargetPosition()) + .getBlock()) initGathererOptions(); } @@ -118,8 +120,8 @@ public class DisplayLinkScreen extends AbstractSimiScreen { asItem = targetBlock.getCloneItemStack(level, blockEntity.getTargetPosition(), targetState); ItemStack targetIcon = asItem == null || asItem.isEmpty() ? FALLBACK : asItem; - sources = AllDisplayBehaviours.sourcesOf(level, blockEntity.getSourcePosition()); - target = AllDisplayBehaviours.targetOf(level, blockEntity.getTargetPosition()); + sources = DisplaySource.getAll(level, blockEntity.getSourcePosition()); + target = DisplayTarget.get(level, blockEntity.getTargetPosition()); removeWidget(targetLineSelector); removeWidget(targetLineLabel); @@ -138,15 +140,15 @@ public class DisplayLinkScreen extends AbstractSimiScreen { int rows = stats.maxRows(); int startIndex = Math.min(blockEntity.targetLine, rows); - targetLineLabel = new Label(x + 65, y + 109, Components.immutableEmpty()).withShadow(); + targetLineLabel = new Label(x + 65, y + 109, CommonComponents.EMPTY).withShadow(); targetLineLabel.text = target.getLineOptionText(startIndex); if (rows > 1) { targetLineSelector = new ScrollInput(x + 61, y + 105, 135, 16).withRange(0, rows) - .titled(Lang.translateDirect("display_link.display_on")) - .inverted() - .calling(i -> targetLineLabel.text = target.getLineOptionText(i)) - .setState(startIndex); + .titled(CreateLang.translateDirect("display_link.display_on")) + .inverted() + .calling(i -> targetLineLabel.text = target.getLineOptionText(i)) + .setState(startIndex); addRenderableWidget(targetLineSelector); } @@ -154,35 +156,35 @@ public class DisplayLinkScreen extends AbstractSimiScreen { } sourceWidget = new ElementWidget(x + 37, y + 26) - .showingElement(GuiGameElement.of(sourceIcon)) - .withCallback((mX, mY) -> { - ScreenOpener.open(new PonderTagScreen(AllPonderTags.DISPLAY_SOURCES)); - }); + .showingElement(GuiGameElement.of(sourceIcon)) + .withCallback((mX, mY) -> { + ScreenOpener.open(new PonderTagScreen(AllCreatePonderTags.DISPLAY_SOURCES)); + }); sourceWidget.getToolTip().addAll(List.of( - Lang.translateDirect("display_link.reading_from"), - sourceState.getBlock().getName() - .withStyle(s -> s.withColor(sources.isEmpty() ? 0xF68989 : 0xF2C16D)), - Lang.translateDirect("display_link.attached_side"), - Lang.translateDirect("display_link.view_compatible") - .withStyle(ChatFormatting.GRAY) + CreateLang.translateDirect("display_link.reading_from"), + sourceState.getBlock().getName() + .withStyle(s -> s.withColor(sources.isEmpty() ? 0xF68989 : 0xF2C16D)), + CreateLang.translateDirect("display_link.attached_side"), + CreateLang.translateDirect("display_link.view_compatible") + .withStyle(ChatFormatting.GRAY) )); addRenderableWidget(sourceWidget); targetWidget = new ElementWidget(x + 37, y + 105) - .showingElement(GuiGameElement.of(targetIcon)) - .withCallback((mX, mY) -> { - ScreenOpener.open(new PonderTagScreen(AllPonderTags.DISPLAY_TARGETS)); - }); + .showingElement(GuiGameElement.of(targetIcon)) + .withCallback((mX, mY) -> { + ScreenOpener.open(new PonderTagScreen(AllCreatePonderTags.DISPLAY_TARGETS)); + }); targetWidget.getToolTip().addAll(List.of( - Lang.translateDirect("display_link.writing_to"), - targetState.getBlock().getName() - .withStyle(s -> s.withColor(target == null ? 0xF68989 : 0xF2C16D)), - Lang.translateDirect("display_link.targeted_location"), - Lang.translateDirect("display_link.view_compatible") - .withStyle(ChatFormatting.GRAY) + CreateLang.translateDirect("display_link.writing_to"), + targetState.getBlock().getName() + .withStyle(s -> s.withColor(target == null ? 0xF68989 : 0xF2C16D)), + CreateLang.translateDirect("display_link.targeted_location"), + CreateLang.translateDirect("display_link.view_compatible") + .withStyle(ChatFormatting.GRAY) )); addRenderableWidget(targetWidget); @@ -190,19 +192,19 @@ public class DisplayLinkScreen extends AbstractSimiScreen { if (!sources.isEmpty()) { int startIndex = Math.max(sources.indexOf(blockEntity.activeSource), 0); - sourceTypeLabel = new Label(x + 65, y + 30, Components.immutableEmpty()).withShadow(); + sourceTypeLabel = new Label(x + 65, y + 30, CommonComponents.EMPTY).withShadow(); sourceTypeLabel.text = sources.get(startIndex) - .getName(); + .getName(); if (sources.size() > 1) { List options = sources.stream() - .map(DisplaySource::getName) - .toList(); + .map(DisplaySource::getName) + .toList(); sourceTypeSelector = new SelectionScrollInput(x + 61, y + 26, 135, 16).forOptions(options) - .writingTo(sourceTypeLabel) - .titled(Lang.translateDirect("display_link.information_type")) - .calling(this::initGathererSourceSubOptions) - .setState(startIndex); + .writingTo(sourceTypeLabel) + .titled(CreateLang.translateDirect("display_link.information_type")) + .calling(this::initGathererSourceSubOptions) + .setState(startIndex); sourceTypeSelector.onChanged(); addRenderableWidget(sourceTypeSelector); } else @@ -219,8 +221,8 @@ public class DisplayLinkScreen extends AbstractSimiScreen { if (targetLineSelector != null) targetLineSelector - .titled(source instanceof SingleLineDisplaySource ? Lang.translateDirect("display_link.display_on") - : Lang.translateDirect("display_link.display_on_multiline")); + .titled(source instanceof SingleLineDisplaySource ? CreateLang.translateDirect("display_link.display_on") + : CreateLang.translateDirect("display_link.display_on_multiline")); configWidgets.forEach(s -> { s.forEach(this::removeWidget); @@ -229,9 +231,9 @@ public class DisplayLinkScreen extends AbstractSimiScreen { DisplayLinkContext context = new DisplayLinkContext(minecraft.level, blockEntity); configWidgets.forEachWithContext((s, first) -> source.initConfigurationWidgets(context, - new ModularGuiLineBuilder(font, s, guiLeft + 60, guiTop + (first ? 51 : 72)), first)); + new ModularGuiLineBuilder(font, s, guiLeft + 60, guiTop + (first ? 51 : 72)), first)); configWidgets - .forEach(s -> s.loadValues(blockEntity.getSourceConfig(), this::addRenderableWidget, this::addRenderableOnly)); + .forEach(s -> s.loadValues(blockEntity.getSourceConfig(), this::addRenderableWidget, this::addRenderableOnly)); } @Override @@ -240,13 +242,16 @@ public class DisplayLinkScreen extends AbstractSimiScreen { CompoundTag sourceData = new CompoundTag(); if (!sources.isEmpty()) { - sourceData.putString("Id", - sources.get(sourceTypeSelector == null ? 0 : sourceTypeSelector.getState()).id.toString()); + DisplaySource source = sources.get(sourceTypeSelector == null ? 0 : sourceTypeSelector.getState()); + ResourceLocation id = CreateBuiltInRegistries.DISPLAY_SOURCE.getKey(source); + if (id != null) { + sourceData.putString("Id", id.toString()); + } configWidgets.forEach(s -> s.saveValues(sourceData)); } AllPackets.getChannel().sendToServer(new DisplayLinkConfigurationPacket(blockEntity.getBlockPos(), sourceData, - targetLineSelector == null ? 0 : targetLineSelector.getState())); + targetLineSelector == null ? 0 : targetLineSelector.getState())); } @Override @@ -255,34 +260,34 @@ public class DisplayLinkScreen extends AbstractSimiScreen { int y = guiTop; background.render(graphics, x, y); - MutableComponent header = Lang.translateDirect("display_link.title"); - graphics.drawString(font, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x592424, false); + MutableComponent header = CreateLang.translateDirect("display_link.title"); + graphics.drawString(font, header, x + background.getWidth() / 2 - font.width(header) / 2, y + 4, 0x592424, false); if (sources.isEmpty()) - graphics.drawString(font, Lang.translateDirect("display_link.no_source"), x + 65, y + 30, 0xD3D3D3); + graphics.drawString(font, CreateLang.translateDirect("display_link.no_source"), x + 65, y + 30, 0xD3D3D3); if (target == null) - graphics.drawString(font, Lang.translateDirect("display_link.no_target"), x + 65, y + 109, 0xD3D3D3); + graphics.drawString(font, CreateLang.translateDirect("display_link.no_target"), x + 65, y + 109, 0xD3D3D3); PoseStack ms = graphics.pose(); ms.pushPose(); ms.translate(0, guiTop + 46, 0); configWidgets.getFirst() - .renderWidgetBG(guiLeft, graphics); + .renderWidgetBG(guiLeft, graphics); ms.translate(0, 21, 0); configWidgets.getSecond() - .renderWidgetBG(guiLeft, graphics); + .renderWidgetBG(guiLeft, graphics); ms.popPose(); ms.pushPose(); TransformStack.of(ms) - .pushPose() - .translate(x + background.width + 4, y + background.height + 4, 100) - .scale(40) - .rotateXDegrees(-22) - .rotateYDegrees(63); + .pushPose() + .translate(x + background.getWidth() + 4, y + background.getHeight() + 4, 100) + .scale(40) + .rotateXDegrees(-22) + .rotateYDegrees(63); GuiGameElement.of(blockEntity.getBlockState() - .setValue(DisplayLinkBlock.FACING, Direction.UP)) - .render(graphics); + .setValue(DisplayLinkBlock.FACING, Direction.UP)) + .render(graphics); ms.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/LinkBulbRenderer.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/LinkBulbRenderer.java new file mode 100644 index 0000000000..268c392bb1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/LinkBulbRenderer.java @@ -0,0 +1,62 @@ +package com.simibubi.create.content.redstone.displayLink; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.RenderTypes; + +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class LinkBulbRenderer extends SafeBlockEntityRenderer { + + public LinkBulbRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(LinkWithBulbBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + float glow = be.getGlow(partialTicks); + if (glow < .125f) + return; + + glow = (float) (1 - (2 * Math.pow(glow - .75f, 2))); + glow = Mth.clamp(glow, -1, 1); + + int color = (int) (200 * glow); + + BlockState blockState = be.getBlockState(); + var msr = TransformStack.of(ms); + + Direction face = be.getBulbFacing(blockState); + + ms.pushPose(); + + msr.center() + .rotateYDegrees(AngleHelper.horizontalAngle(face) + 180) + .rotateXDegrees(-AngleHelper.verticalAngle(face) - 90) + .uncenter(); + + CachedBuffers.partial(AllPartialModels.DISPLAY_LINK_TUBE, blockState) + .translate(be.getBulbOffset(blockState)) + .light(LightTexture.FULL_BRIGHT) + .renderInto(ms, buffer.getBuffer(RenderType.translucent())); + + CachedBuffers.partial(AllPartialModels.DISPLAY_LINK_GLOW, blockState) + .translate(be.getBulbOffset(blockState)) + .light(LightTexture.FULL_BRIGHT) + .color(color, color, color, 255) + .disableDiffuse() + .renderInto(ms, buffer.getBuffer(RenderTypes.additive())); + + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/LinkWithBulbBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/LinkWithBulbBlockEntity.java new file mode 100644 index 0000000000..a47a1145a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/LinkWithBulbBlockEntity.java @@ -0,0 +1,70 @@ +package com.simibubi.create.content.redstone.displayLink; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; + +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public abstract class LinkWithBulbBlockEntity extends SmartBlockEntity { + + private LerpedFloat glow; + private boolean sendPulse; + + public LinkWithBulbBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + glow = LerpedFloat.linear() + .startWithValue(0); + glow.chase(0, 0.5f, Chaser.EXP); + } + + @Override + public void tick() { + super.tick(); + if (isVirtual() || level.isClientSide()) + glow.tickChaser(); + } + + public float getGlow(float partialTicks) { + return glow.getValue(partialTicks); + } + + public void sendPulseNextSync() { + sendPulse = true; + } + + public void pulse() { + glow.setValue(2); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + if (clientPacket && sendPulse) { + sendPulse = false; + NBTHelper.putMarker(tag, "Pulse"); + } + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + if (clientPacket && tag.contains("Pulse")) + pulse(); + } + + public Vec3 getBulbOffset(BlockState state) { + return Vec3.ZERO; + } + + public Direction getBulbFacing(BlockState state) { + return state.getValue(DisplayLinkBlock.FACING); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/AccumulatedItemCountDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/AccumulatedItemCountDisplaySource.java index 8ebd8f3fdd..5d7bcd9404 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/AccumulatedItemCountDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/AccumulatedItemCountDisplaySource.java @@ -4,15 +4,15 @@ import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; -import com.simibubi.create.foundation.utility.Components; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; public class AccumulatedItemCountDisplaySource extends NumericSingleLineDisplaySource { @Override protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - return Components.literal(String.valueOf(context.sourceConfig() + return Component.literal(String.valueOf(context.sourceConfig() .getInt("Collected"))); } @@ -21,7 +21,7 @@ public class AccumulatedItemCountDisplaySource extends NumericSingleLineDisplayS .getOptionalValue(DisplayLinkBlock.POWERED) .orElse(true)) return; - + int collected = be.getSourceConfig() .getInt("Collected"); be.getSourceConfig() diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/BoilerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/BoilerDisplaySource.java index 8ea2a88aba..fdca9e10f9 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/BoilerDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/BoilerDisplaySource.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Optional; import java.util.stream.Stream; +import com.simibubi.create.api.behaviour.display.DisplaySource; import com.simibubi.create.content.fluids.tank.BoilerData; import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; @@ -11,11 +12,11 @@ import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStat import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.content.trains.display.FlapDisplayLayout; import com.simibubi.create.content.trains.display.FlapDisplaySection; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import joptsimple.internal.Strings; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; @@ -23,16 +24,16 @@ import net.minecraft.world.level.block.entity.LecternBlockEntity; public class BoilerDisplaySource extends DisplaySource { public static final List notEnoughSpaceSingle = - List.of(Lang.translateDirect("display_source.boiler.not_enough_space") - .append(Lang.translateDirect("display_source.boiler.for_boiler_status"))); + List.of(CreateLang.translateDirect("display_source.boiler.not_enough_space") + .append(CreateLang.translateDirect("display_source.boiler.for_boiler_status"))); public static final List notEnoughSpaceDouble = - List.of(Lang.translateDirect("display_source.boiler.not_enough_space"), - Lang.translateDirect("display_source.boiler.for_boiler_status")); + List.of(CreateLang.translateDirect("display_source.boiler.not_enough_space"), + CreateLang.translateDirect("display_source.boiler.for_boiler_status")); public static final List> notEnoughSpaceFlap = - List.of(List.of(Lang.translateDirect("display_source.boiler.not_enough_space")), - List.of(Lang.translateDirect("display_source.boiler.for_boiler_status"))); + List.of(List.of(CreateLang.translateDirect("display_source.boiler.not_enough_space")), + List.of(CreateLang.translateDirect("display_source.boiler.for_boiler_status"))); @Override public List provideText(DisplayLinkContext context, DisplayTargetStats stats) { @@ -50,8 +51,10 @@ public class BoilerDisplaySource extends DisplaySource { return reduce.orElse(EMPTY_LINE); }); - return List.of(componentList.reduce((comp1, comp2) -> comp1.append(Components.literal("\n")) - .append(comp2)) + return List.of(componentList.reduce((comp1, comp2) -> { + return comp1.append(Component.literal("\n")) + .append(comp2); + }) .orElse(EMPTY_LINE)); } @@ -128,12 +131,12 @@ public class BoilerDisplaySource extends DisplaySource { int lw = labelWidth(); if (forFlapDisplay) { - size = Components.literal(Strings.repeat(' ', lw - labelWidthOf("size"))).append(size); - water = Components.literal(Strings.repeat(' ', lw - labelWidthOf("water"))).append(water); - heat = Components.literal(Strings.repeat(' ', lw - labelWidthOf("heat"))).append(heat); + size = Component.literal(Strings.repeat(' ', lw - labelWidthOf("size"))).append(size); + water = Component.literal(Strings.repeat(' ', lw - labelWidthOf("water"))).append(water); + heat = Component.literal(Strings.repeat(' ', lw - labelWidthOf("heat"))).append(heat); } - return Stream.of(List.of(Lang.translateDirect(label, boiler.getHeatLevelTextComponent())), + return Stream.of(List.of(CreateLang.translateDirect(label, boiler.getHeatLevelTextComponent())), List.of(size, boiler.getSizeComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.RESET)), List.of(water, boiler.getWaterComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.RESET)), List.of(heat, boiler.getHeatComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.RESET))); @@ -150,8 +153,8 @@ public class BoilerDisplaySource extends DisplaySource { private MutableComponent labelOf(String label) { if (label.isBlank()) - return Components.empty(); - return Lang.translateDirect("boiler." + label); + return Component.empty(); + return CreateLang.translateDirect("boiler." + label); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ComputerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ComputerDisplaySource.java index 1d99ae70bd..986753e6ad 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ComputerDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ComputerDisplaySource.java @@ -3,12 +3,13 @@ package com.simibubi.create.content.redstone.displayLink.source; import java.util.ArrayList; import java.util.List; +import com.simibubi.create.api.behaviour.display.DisplaySource; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; -import com.simibubi.create.foundation.utility.Components; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; public class ComputerDisplaySource extends DisplaySource { @@ -19,7 +20,7 @@ public class ComputerDisplaySource extends DisplaySource { ListTag tag = context.sourceConfig().getList("ComputerSourceList", Tag.TAG_STRING); for (int i = 0; i < tag.size(); i++) { - components.add(Components.literal(tag.getString(i))); + components.add(Component.literal(tag.getString(i))); } return components; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/CurrentFloorDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/CurrentFloorDisplaySource.java index b61a5856a2..916a80d6c5 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/CurrentFloorDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/CurrentFloorDisplaySource.java @@ -3,8 +3,8 @@ package com.simibubi.create.content.redstone.displayLink.source; import com.simibubi.create.content.contraptions.elevator.ElevatorContactBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; -import com.simibubi.create.foundation.utility.Components; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; public class CurrentFloorDisplaySource extends SingleLineDisplaySource { @@ -13,9 +13,9 @@ public class CurrentFloorDisplaySource extends SingleLineDisplaySource { protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { if (!(context.getSourceBlockEntity() instanceof ElevatorContactBlockEntity ecbe)) return EMPTY_LINE; - return Components.literal(ecbe.lastReportedCurrentFloor); + return Component.literal(ecbe.lastReportedCurrentFloor); } - + @Override protected String getTranslationKey() { return "current_floor"; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DeathCounterDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DeathCounterDisplaySource.java index f051926fb7..e8e4668e81 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DeathCounterDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DeathCounterDisplaySource.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.redstone.displayLink.source; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; @@ -26,7 +26,7 @@ public class DeathCounterDisplaySource extends StatTrackingDisplaySource { @Override protected Component getObjectiveDisplayName() { - return Lang.translateDirect("display_source.scoreboard.objective.deaths"); + return CreateLang.translateDirect("display_source.scoreboard.objective.deaths"); } } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java deleted file mode 100644 index 5441352614..0000000000 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.simibubi.create.content.redstone.displayLink.source; - -import java.util.Arrays; -import java.util.List; - -import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.redstone.displayLink.DisplayBehaviour; -import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; -import com.simibubi.create.content.redstone.displayLink.target.DisplayBoardTarget; -import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; -import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; -import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; -import com.simibubi.create.content.trains.display.FlapDisplayLayout; -import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.NBTProcessors; - -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public abstract class DisplaySource extends DisplayBehaviour { - - public static final List EMPTY = ImmutableList.of(Components.empty()); - public static final MutableComponent EMPTY_LINE = Components.empty(); - public static final MutableComponent WHITESPACE = Components.literal(" "); - - public abstract List provideText(DisplayLinkContext context, DisplayTargetStats stats); - - public void transferData(DisplayLinkContext context, DisplayTarget activeTarget, int line) { - DisplayTargetStats stats = activeTarget.provideStats(context); - - if (activeTarget instanceof DisplayBoardTarget fddt) { - List> flapDisplayText = provideFlapDisplayText(context, stats); - fddt.acceptFlapText(line, flapDisplayText, context); - } - - List text = provideText(context, stats); - if (text.isEmpty()) - text = EMPTY; - - if (activeTarget.requiresComponentSanitization()) - for (MutableComponent component : text) - if (NBTProcessors.textComponentHasClickEvent(component)) - return; // Naughty - - activeTarget.acceptText(line, text, context); - } - - public void onSignalReset(DisplayLinkContext context) {}; - - public void populateData(DisplayLinkContext context) {}; - - public int getPassiveRefreshTicks() { - return 100; - }; - - public boolean shouldPassiveReset() { - return true; - } - - protected String getTranslationKey() { - return id.getPath(); - } - - public Component getName() { - return Components.translatable(id.getNamespace() + ".display_source." + getTranslationKey()); - } - - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout, int lineIndex) { - loadFlapDisplayLayout(context, flapDisplay, layout); - } - - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, - FlapDisplayLayout layout) { - if (!layout.isLayout("Default")) - layout.loadDefault(flapDisplay.getMaxCharCount()); - } - - public List> provideFlapDisplayText(DisplayLinkContext context, DisplayTargetStats stats) { - return provideText(context, stats).stream() - .map(Arrays::asList) - .toList(); - } - - @OnlyIn(Dist.CLIENT) - public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, - boolean isFirstLine) {} - -} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EnchantPowerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EnchantPowerDisplaySource.java index 4de9bc3620..6a8a8e14ef 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EnchantPowerDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EnchantPowerDisplaySource.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.redstone.displayLink.source; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; -import com.simibubi.create.foundation.utility.Components; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; @@ -38,7 +38,7 @@ public class EnchantPowerDisplaySource extends NumericSingleLineDisplaySource { int cost = EnchantmentHelper.getEnchantmentCost(random, 2, (int) enchantPower, stack); - return Components.literal(String.valueOf(cost)); + return Component.literal(String.valueOf(cost)); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EntityNameDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EntityNameDisplaySource.java index 8dd981462f..c24205668e 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EntityNameDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EntityNameDisplaySource.java @@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.AABB; @@ -24,7 +25,7 @@ public class EntityNameDisplaySource extends SingleLineDisplaySource { if (passengers.isEmpty()) return EMPTY_LINE; - return passengers.get(0).getDisplayName().copy(); + return Component.literal(passengers.get(0).getDisplayName().getString()); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FactoryGaugeDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FactoryGaugeDisplaySource.java new file mode 100644 index 0000000000..a301696e4e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FactoryGaugeDisplaySource.java @@ -0,0 +1,71 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelBehaviour; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelPosition; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; + +import net.createmod.catnip.data.IntAttached; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class FactoryGaugeDisplaySource extends ValueListDisplaySource { + + @Override + protected Stream> provideEntries(DisplayLinkContext context, int maxRows) { + List panels = context.blockEntity().factoryPanelSupport.getLinkedPanels(); + if (panels.isEmpty()) + return Stream.empty(); + return panels.stream() + .map(fpp -> createEntry(context.level(), fpp)) +// .sorted(IntAttached.comparator()) + .filter(Objects::nonNull) + .limit(maxRows); + } + + @Nullable + public IntAttached createEntry(Level level, FactoryPanelPosition pos) { + FactoryPanelBehaviour panel = FactoryPanelBehaviour.at(level, pos); + ItemStack filter = panel.getFilter(); + if (filter == null) + return null; + + int demand = panel.getAmount() * (panel.upTo ? 1 : filter.getMaxStackSize()); + String s = " "; + + if (demand != 0) { + int promised = panel.getPromised(); + if (panel.satisfied) + s = "\u2714"; + else if (promised != 0) + s = "\u2191"; + else + s = "\u25aa"; + } + + return IntAttached.with(panel.getLevelInStorage(), Component.literal(s + " ") + .withStyle(style -> style.withColor(panel.getIngredientStatusColor())) + .append(filter.getHoverName() + .plainCopy() + .withStyle(ChatFormatting.RESET))); + } + + @Override + protected String getTranslationKey() { + return "gauge_status"; + } + + @Override + protected boolean valueFirst() { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FillLevelDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FillLevelDisplaySource.java index c62551edd5..e02c865dfa 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FillLevelDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FillLevelDisplaySource.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.redstone.displayLink.source; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlockEntity; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.api.distmarker.Dist; @@ -16,9 +16,10 @@ public class FillLevelDisplaySource extends PercentOrProgressBarDisplaySource { BlockEntity be = context.getSourceBlockEntity(); if (!(be instanceof ThresholdSwitchBlockEntity tsbe)) return null; - return tsbe.currentLevel; + return Math.max(0, + (float) (tsbe.currentLevel - tsbe.currentMinLevel) / (tsbe.currentMaxLevel - tsbe.currentMinLevel)); } - + @Override protected boolean progressBarActive(DisplayLinkContext context) { return context.sourceConfig() @@ -37,8 +38,8 @@ public class FillLevelDisplaySource extends PercentOrProgressBarDisplaySource { if (isFirstLine) return; builder.addSelectionScrollInput(0, 120, - (si, l) -> si.forOptions(Lang.translatedOptions("display_source.fill_level", "percent", "progress_bar")) - .titled(Lang.translateDirect("display_source.fill_level.display")), + (si, l) -> si.forOptions(CreateLang.translatedOptions("display_source.fill_level", "percent", "progress_bar")) + .titled(CreateLang.translateDirect("display_source.fill_level.display")), "Mode"); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidAmountDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidAmountDisplaySource.java index dbed634dc6..6ae7949fb5 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidAmountDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidAmountDisplaySource.java @@ -5,9 +5,9 @@ import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStat import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; -import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.FluidFormatter; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.fluids.FluidStack; @@ -38,7 +38,7 @@ public class FluidAmountDisplaySource extends SingleLineDisplaySource { collected += stack.getAmount(); } - return Components.literal(FluidFormatter.asString(collected, false)); + return Component.literal(FluidFormatter.asString(collected, false)); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidListDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidListDisplaySource.java index 159640f9e7..d931a20945 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidListDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidListDisplaySource.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; +import net.minecraft.network.chat.Component; import org.apache.commons.lang3.mutable.MutableInt; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; @@ -15,11 +16,10 @@ import com.simibubi.create.content.trains.display.FlapDisplayLayout; import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.FluidFormatter; -import com.simibubi.create.foundation.utility.IntAttached; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.material.Fluid; @@ -63,7 +63,7 @@ public class FluidListDisplaySource extends ValueListDisplaySource { .limit(maxRows) .map(entry -> IntAttached.with( entry.getValue(), - Components.translatable(fluidNames.get(entry.getKey()).getTranslationKey())) + Component.translatable(fluidNames.get(entry.getKey()).getTranslationKey())) ); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemCountDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemCountDisplaySource.java index 752718a627..69d3eea768 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemCountDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemCountDisplaySource.java @@ -5,8 +5,8 @@ import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStat import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.Components; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; @@ -37,7 +37,7 @@ public class ItemCountDisplaySource extends NumericSingleLineDisplaySource { collected += stack.getCount(); } - return Components.literal(String.valueOf(collected)); + return Component.literal(String.valueOf(collected)); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemListDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemListDisplaySource.java index 2869bbe99f..085b78a642 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemListDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemListDisplaySource.java @@ -7,8 +7,8 @@ import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEnti import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.item.CountedItemStackList; -import com.simibubi.create.foundation.utility.IntAttached; +import net.createmod.catnip.data.IntAttached; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.items.IItemHandler; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemThroughputDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemThroughputDisplaySource.java index 38ff12f6c6..f62d2e1ca9 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemThroughputDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemThroughputDisplaySource.java @@ -5,7 +5,7 @@ import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.FloatTag; @@ -43,7 +43,7 @@ public class ItemThroughputDisplaySource extends AccumulatedItemCountDisplaySour } } - return Lang.number(rate) + return CreateLang.number(rate) .component(); } @@ -107,8 +107,8 @@ public class ItemThroughputDisplaySource extends AccumulatedItemCountDisplaySour return; builder.addSelectionScrollInput(0, 80, (si, l) -> { - si.forOptions(Lang.translatedOptions("display_source.item_throughput.interval", "second", "minute", "hour")) - .titled(Lang.translateDirect("display_source.item_throughput.interval")); + si.forOptions(CreateLang.translatedOptions("display_source.item_throughput.interval", "second", "minute", "hour")) + .titled(CreateLang.translateDirect("display_source.item_throughput.interval")); }, "Interval"); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticSpeedDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticSpeedDisplaySource.java index 6db6f24910..34124ff890 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticSpeedDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticSpeedDisplaySource.java @@ -4,7 +4,7 @@ import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.MutableComponent; import net.minecraftforge.api.distmarker.Dist; @@ -20,7 +20,7 @@ public class KineticSpeedDisplaySource extends NumericSingleLineDisplaySource { boolean absoluteValue = context.sourceConfig() .getInt("Directional") == 0; float speed = absoluteValue ? Math.abs(speedGauge.getSpeed()) : speedGauge.getSpeed(); - return Lang.number(speed) + return CreateLang.number(speed) .space() .translate("generic.unit.rpm") .component(); @@ -41,7 +41,7 @@ public class KineticSpeedDisplaySource extends NumericSingleLineDisplaySource { builder.addSelectionScrollInput(0, 95, (selectionScrollInput, label) -> { selectionScrollInput - .forOptions(Lang.translatedOptions("display_source.kinetic_speed", "absolute", "directional")); + .forOptions(CreateLang.translatedOptions("display_source.kinetic_speed", "absolute", "directional")); }, "Directional"); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticStressDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticStressDisplaySource.java index 343a2b283e..d39e8278cb 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticStressDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticStressDisplaySource.java @@ -4,9 +4,9 @@ import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.LangBuilder; import net.minecraft.network.chat.MutableComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -18,7 +18,7 @@ public class KineticStressDisplaySource extends PercentOrProgressBarDisplaySourc int mode = getMode(context); if (mode == 1) return super.formatNumeric(context, currentLevel); - LangBuilder builder = Lang.number(currentLevel); + LangBuilder builder = CreateLang.number(currentLevel); if (context.getTargetBlockEntity() instanceof FlapDisplayBlockEntity) builder.space(); return builder.translate("generic.unit.stress") @@ -69,9 +69,9 @@ public class KineticStressDisplaySource extends PercentOrProgressBarDisplaySourc return; builder.addSelectionScrollInput(0, 120, (si, l) -> si - .forOptions(Lang.translatedOptions("display_source.kinetic_stress", "progress_bar", "percent", + .forOptions(CreateLang.translatedOptions("display_source.kinetic_stress", "progress_bar", "percent", "current", "max", "remaining")) - .titled(Lang.translateDirect("display_source.kinetic_stress.display")), + .titled(CreateLang.translateDirect("display_source.kinetic_stress.display")), "Mode"); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NumericSingleLineDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NumericSingleLineDisplaySource.java index ffb702116b..06d31c6243 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NumericSingleLineDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NumericSingleLineDisplaySource.java @@ -2,15 +2,18 @@ package com.simibubi.create.content.redstone.displayLink.source; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.trains.display.FlapDisplaySection; -import com.simibubi.create.foundation.utility.Components; import net.minecraft.network.chat.Component; public abstract class NumericSingleLineDisplaySource extends SingleLineDisplaySource { - protected static final Component ZERO = Components.literal("0"); + protected static final Component ZERO; - @Override + static { + ZERO = Component.literal("0"); + } + + @Override protected String getFlapDisplayLayoutName(DisplayLinkContext context) { return "Number"; } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PackageAddressDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PackageAddressDisplaySource.java new file mode 100644 index 0000000000..c24654e012 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PackageAddressDisplaySource.java @@ -0,0 +1,67 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorPackage; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlock; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.IItemHandler; + +public class PackageAddressDisplaySource extends SingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + BlockEntity sourceBE = context.getSourceBlockEntity(); + if (!(sourceBE instanceof SmartObserverBlockEntity cobe)) + return EMPTY_LINE; + + InvManipulationBehaviour invManipulationBehaviour = cobe.getBehaviour(InvManipulationBehaviour.TYPE); + FilteringBehaviour filteringBehaviour = cobe.getBehaviour(FilteringBehaviour.TYPE); + IItemHandler handler = invManipulationBehaviour.getInventory(); + + if (handler == null) { + BlockPos targetPos = cobe.getBlockPos().relative(SmartObserverBlock.getTargetDirection(cobe.getBlockState())); + + if (context.level().getBlockEntity(targetPos) instanceof ChainConveyorBlockEntity ccbe) + for (ChainConveyorPackage box : ccbe.getLoopingPackages()) + if (filteringBehaviour.test(box.item)) + return Component.literal(PackageItem.getAddress(box.item)); + + return EMPTY_LINE; + } + + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.getStackInSlot(i); + if (PackageItem.isPackage(stack) && filteringBehaviour.test(stack)) + return Component.literal(PackageItem.getAddress(stack)); + } + + return EMPTY_LINE; + } + + @Override + protected String getTranslationKey() { + return "read_package_address"; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } + + @Override + protected String getFlapDisplayLayoutName(DisplayLinkContext context) { + return "Default"; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PercentOrProgressBarDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PercentOrProgressBarDisplaySource.java index b4985985b0..feba4eadc2 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PercentOrProgressBarDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PercentOrProgressBarDisplaySource.java @@ -8,8 +8,8 @@ import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.content.trains.display.FlapDisplaySection; -import com.simibubi.create.foundation.utility.Components; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.world.level.block.entity.SignBlockEntity; @@ -18,9 +18,11 @@ public abstract class PercentOrProgressBarDisplaySource extends NumericSingleLin @Override protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - Float currentLevel = getProgress(context); - if (currentLevel == null) + Float rawProgress = this.getProgress(context); + if (rawProgress == null) return EMPTY_LINE; + // clamp just in case - #7371 + float currentLevel = Mth.clamp(rawProgress, 0, 1); if (!progressBarActive(context)) return formatNumeric(context, currentLevel); @@ -47,11 +49,11 @@ public abstract class PercentOrProgressBarDisplaySource extends NumericSingleLin for (int i = 0; i < emptySpaces; i++) s.append("\u2592"); - return Components.literal(s.toString()); + return Component.literal(s.toString()); } protected MutableComponent formatNumeric(DisplayLinkContext context, Float currentLevel) { - return Components.literal(Mth.clamp((int) (currentLevel * 100), 0, 100) + "%"); + return Component.literal(Mth.clamp((int) (currentLevel * 100), 0, 100) + "%"); } @Nullable diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/RedstonePowerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/RedstonePowerDisplaySource.java index 45ebde9fb1..8777d283ce 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/RedstonePowerDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/RedstonePowerDisplaySource.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.redstone.displayLink.source; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; @@ -12,7 +12,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class RedstonePowerDisplaySource extends PercentOrProgressBarDisplaySource { - + @Override protected String getTranslationKey() { return "redstone_power"; @@ -20,9 +20,9 @@ public class RedstonePowerDisplaySource extends PercentOrProgressBarDisplaySourc @Override protected MutableComponent formatNumeric(DisplayLinkContext context, Float currentLevel) { - return Components.literal(String.valueOf((int) (currentLevel * 15))); + return Component.literal(String.valueOf((int) (currentLevel * 15))); } - + @Override protected boolean allowsLabeling(DisplayLinkContext context) { return true; @@ -52,9 +52,9 @@ public class RedstonePowerDisplaySource extends PercentOrProgressBarDisplaySourc if (isFirstLine) return; builder.addSelectionScrollInput(0, 120, - (si, l) -> si.forOptions(Lang.translatedOptions("display_source.redstone_power", "number", "progress_bar")) - .titled(Lang.translateDirect("display_source.redstone_power.display")), + (si, l) -> si.forOptions(CreateLang.translatedOptions("display_source.redstone_power", "number", "progress_bar")) + .titled(CreateLang.translateDirect("display_source.redstone_power.display")), "Mode"); } - + } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ScoreboardDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ScoreboardDisplaySource.java index 1081078ae1..2a0251e824 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ScoreboardDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ScoreboardDisplaySource.java @@ -5,11 +5,11 @@ import java.util.stream.Stream; import com.google.common.collect.ImmutableList; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.IntAttached; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; @@ -40,15 +40,17 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource { return sLevel.getScoreboard() .getPlayerScores(objective) .stream() - .map(score -> IntAttached.with(score.getScore(), Components.literal(score.getOwner()) - .copy())) + .map(score -> { + return IntAttached.with(score.getScore(), Component.literal(score.getOwner()) + .copy()); + }) .sorted(IntAttached.comparator()) .limit(maxRows); } private ImmutableList> notFound(String objective) { return ImmutableList - .of(IntAttached.with(404, Lang.translateDirect("display_source.scoreboard.objective_not_found", objective))); + .of(IntAttached.with(404, CreateLang.translateDirect("display_source.scoreboard.objective_not_found", objective))); } @Override @@ -61,9 +63,9 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource { if (isFirstLine) builder.addTextInput(0, 137, (e, t) -> { e.setValue(""); - t.withTooltip(ImmutableList.of(Lang.translateDirect("display_source.scoreboard.objective") + t.withTooltip(ImmutableList.of(CreateLang.translateDirect("display_source.scoreboard.objective") .withStyle(s -> s.withColor(0x5391E1)), - Lang.translateDirect("gui.schedule.lmb_edit") + CreateLang.translateDirect("gui.schedule.lmb_edit") .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC))); }, "Objective"); else diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/SingleLineDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/SingleLineDisplaySource.java index a07064dc59..2652ef3d47 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/SingleLineDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/SingleLineDisplaySource.java @@ -3,17 +3,19 @@ package com.simibubi.create.content.redstone.displayLink.source; import java.util.List; import com.google.common.collect.ImmutableList; +import com.simibubi.create.api.behaviour.display.DisplaySource; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.content.trains.display.FlapDisplayLayout; import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -34,9 +36,9 @@ public abstract class SingleLineDisplaySource extends DisplaySource { protected void addLabelingTextBox(ModularGuiLineBuilder builder) { builder.addTextInput(0, 137, (e, t) -> { e.setValue(""); - t.withTooltip(ImmutableList.of(Lang.translateDirect("display_source.label") + t.withTooltip(ImmutableList.of(CreateLang.translateDirect("display_source.label") .withStyle(s -> s.withColor(0x5391E1)), - Lang.translateDirect("gui.schedule.lmb_edit") + CreateLang.translateDirect("gui.schedule.lmb_edit") .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC))); }, "Label"); } @@ -50,8 +52,9 @@ public abstract class SingleLineDisplaySource extends DisplaySource { if (allowsLabeling(context)) { String label = context.sourceConfig() .getString("Label"); - if (!label.isEmpty()) - line = Components.literal(label + " ").append(line); + if (!label.isEmpty()) { + line = Component.literal(label + " ").append(line); + } } return ImmutableList.of(line); @@ -63,8 +66,9 @@ public abstract class SingleLineDisplaySource extends DisplaySource { if (allowsLabeling(context)) { String label = context.sourceConfig() .getString("Label"); - if (!label.isEmpty()) - return ImmutableList.of(ImmutableList.of(Components.literal(label + " "), provideLine(context, stats))); + if (!label.isEmpty()) { + return ImmutableList.of(ImmutableList.of(Component.literal(label + " "), provideLine(context, stats))); + } } return super.provideFlapDisplayText(context, stats); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StatTrackingDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StatTrackingDisplaySource.java index 14391ef1bd..b8f34dbed7 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StatTrackingDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StatTrackingDisplaySource.java @@ -4,8 +4,8 @@ import java.util.stream.Stream; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.IntAttached; +import net.createmod.catnip.data.IntAttached; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerLevel; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StationSummaryDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StationSummaryDisplaySource.java index f56ddfffdc..e5bd95a974 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StationSummaryDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StationSummaryDisplaySource.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; import com.google.common.collect.ImmutableList; +import com.simibubi.create.api.behaviour.display.DisplaySource; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; @@ -16,26 +17,38 @@ import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.content.trains.station.StationBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class StationSummaryDisplaySource extends DisplaySource { - protected static final MutableComponent UNPREDICTABLE = Components.literal(" ~ "); + protected static final MutableComponent UNPREDICTABLE; - protected static final List EMPTY_ENTRY_4 = - ImmutableList.of(WHITESPACE, Components.literal(" . "), WHITESPACE, WHITESPACE); - protected static final List EMPTY_ENTRY_5 = - ImmutableList.of(WHITESPACE, Components.literal(" . "), WHITESPACE, WHITESPACE, WHITESPACE); + static { + UNPREDICTABLE = Component.literal(" ~ "); + } - @Override + protected static final List EMPTY_ENTRY_4; + + static { + EMPTY_ENTRY_4 = ImmutableList.of(WHITESPACE, Component.literal(" . "), WHITESPACE, WHITESPACE); + } + + protected static final List EMPTY_ENTRY_5; + + static { + EMPTY_ENTRY_5 = ImmutableList.of(WHITESPACE, Component.literal(" . "), WHITESPACE, WHITESPACE, WHITESPACE); + } + + @Override public List provideText(DisplayLinkContext context, DisplayTargetStats stats) { return EMPTY; } @@ -57,7 +70,7 @@ public class StationSummaryDisplaySource extends DisplaySource { } else if (prediction.ticks < 200) { lines.add(WHITESPACE); - lines.add(Lang.translateDirect("display_source.station_summary.now")); + lines.add(CreateLang.translateDirect("display_source.station_summary.now")); } else { int min = prediction.ticks / 1200; @@ -67,9 +80,9 @@ public class StationSummaryDisplaySource extends DisplaySource { min++; sec = 0; } - lines.add(min > 0 ? Components.literal(String.valueOf(min)) : WHITESPACE); - lines.add(min > 0 ? Lang.translateDirect("display_source.station_summary.minutes") - : Lang.translateDirect("display_source.station_summary.seconds", sec)); + lines.add(min > 0 ? Component.literal(String.valueOf(min)) : WHITESPACE); + lines.add(min > 0 ? CreateLang.translateDirect("display_source.station_summary.minutes") + : CreateLang.translateDirect("display_source.station_summary.seconds", sec)); } lines.add(prediction.train.name.copy()); @@ -86,7 +99,7 @@ public class StationSummaryDisplaySource extends DisplaySource { platform = platform.replace(string, ""); platform = platform.replace("*", "?"); - lines.add(Components.literal(platform.trim())); + lines.add(Component.literal(platform.trim())); list.add(lines); }); @@ -187,16 +200,16 @@ public class StationSummaryDisplaySource extends DisplaySource { if (isFirstLine) { builder.addTextInput(0, 137, (e, t) -> { e.setValue(""); - t.withTooltip(ImmutableList.of(Lang.translateDirect("display_source.station_summary.filter") + t.withTooltip(ImmutableList.of(CreateLang.translateDirect("display_source.station_summary.filter") .withStyle(s -> s.withColor(0x5391E1)), - Lang.translateDirect("gui.schedule.lmb_edit") + CreateLang.translateDirect("gui.schedule.lmb_edit") .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC))); }, "Filter"); return; } builder.addScrollInput(0, 32, (si, l) -> { - si.titled(Lang.translateDirect("display_source.station_summary.train_name_column")) + si.titled(CreateLang.translateDirect("display_source.station_summary.train_name_column")) .withRange(0, 73) .withShiftStep(12); si.setState(50); @@ -204,7 +217,7 @@ public class StationSummaryDisplaySource extends DisplaySource { }, "NameColumn"); builder.addScrollInput(36, 22, (si, l) -> { - si.titled(Lang.translateDirect("display_source.station_summary.platform_column")) + si.titled(CreateLang.translateDirect("display_source.station_summary.platform_column")) .withRange(0, 16) .withShiftStep(4); si.setState(3); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StopWatchDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StopWatchDisplaySource.java index 5b47472a95..b67254c192 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StopWatchDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StopWatchDisplaySource.java @@ -4,8 +4,8 @@ import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.content.trains.display.FlapDisplaySection; -import com.simibubi.create.foundation.utility.Components; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; public class StopWatchDisplaySource extends SingleLineDisplaySource { @@ -32,7 +32,7 @@ public class StopWatchDisplaySource extends SingleLineDisplaySource { int minutes = (diff / 60 / 20) % 60; int seconds = (diff / 20) % 60; - MutableComponent component = Components.literal((hours == 0 ? "" : (hours < 10 ? " " : "") + hours + ":") + MutableComponent component = Component.literal((hours == 0 ? "" : (hours < 10 ? " " : "") + hours + ":") + (minutes < 10 ? hours == 0 ? " " : "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds); return component; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TimeOfDayDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TimeOfDayDisplaySource.java index ec95ba5c8e..7cda01ff71 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TimeOfDayDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TimeOfDayDisplaySource.java @@ -1,14 +1,13 @@ package com.simibubi.create.content.redstone.displayLink.source; -import com.simibubi.create.Create; import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerLevel; import net.minecraftforge.api.distmarker.Dist; @@ -16,9 +15,13 @@ import net.minecraftforge.api.distmarker.OnlyIn; public class TimeOfDayDisplaySource extends SingleLineDisplaySource { - public static final MutableComponent EMPTY_TIME = Components.literal("--:--"); - - @Override + public static final MutableComponent EMPTY_TIME; + + static { + EMPTY_TIME = Component.literal("--:--"); + } + + @Override protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { if (!(context.level()instanceof ServerLevel sLevel)) return EMPTY_TIME; @@ -35,7 +38,7 @@ public class TimeOfDayDisplaySource extends SingleLineDisplaySource { int dayTime = (int) (sLevel.getDayTime() % 24000); int hours = (dayTime / 1000 + 6) % 24; int minutes = (dayTime % 1000) * 60 / 1000; - MutableComponent suffix = Lang.translateDirect("generic.daytime." + (hours > 11 ? "pm" : "am")); + MutableComponent suffix = CreateLang.translateDirect("generic.daytime." + (hours > 11 ? "pm" : "am")); minutes = minutes / 5 * 5; if (c12) { @@ -45,11 +48,11 @@ public class TimeOfDayDisplaySource extends SingleLineDisplaySource { } if (!isNatural) { - hours = Create.RANDOM.nextInt(70) + 24; - minutes = Create.RANDOM.nextInt(40) + 60; + hours = sLevel.random.nextInt(70) + 24; + minutes = sLevel.random.nextInt(40) + 60; } - MutableComponent component = Components.literal( + MutableComponent component = Component.literal( (hours < 10 ? " " : "") + hours + ":" + (minutes < 10 ? "0" : "") + minutes + (c12 ? " " : "")); return c12 ? component.append(suffix) : component; @@ -78,8 +81,8 @@ public class TimeOfDayDisplaySource extends SingleLineDisplaySource { return; builder.addSelectionScrollInput(0, 60, (si, l) -> { - si.forOptions(Lang.translatedOptions("display_source.time", "12_hour", "24_hour")) - .titled(Lang.translateDirect("display_source.time.format")); + si.forOptions(CreateLang.translatedOptions("display_source.time", "12_hour", "24_hour")) + .titled(CreateLang.translateDirect("display_source.time.format")); }, "Cycle"); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ValueListDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ValueListDisplaySource.java index 057171755c..84bea15fd8 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ValueListDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ValueListDisplaySource.java @@ -9,19 +9,21 @@ import java.util.stream.Stream; import org.apache.commons.lang3.mutable.MutableInt; +import com.simibubi.create.api.behaviour.display.DisplaySource; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.content.trains.display.FlapDisplayLayout; import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.LecternBlockEntity; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -63,7 +65,7 @@ public abstract class ValueListDisplaySource extends DisplaySource { current = atIndex; continue; } - current.append(Components.literal("\n")) + current.append(Component.literal("\n")) .append(atIndex); if ((i + 1) % ENTRIES_PER_PAGE == 0) { condensed.add(current); @@ -99,7 +101,7 @@ public abstract class ValueListDisplaySource extends DisplaySource { : Arrays.asList(name, shortened.getFirst(), shortened.getSecond()); } - MutableComponent formattedNumber = Components.literal(String.valueOf(number)).append(WHITESPACE); + MutableComponent formattedNumber = Component.literal(String.valueOf(number)).append(WHITESPACE); return valueFirst() ? Arrays.asList(formattedNumber, name) : Arrays.asList(name, formattedNumber); } @@ -136,15 +138,17 @@ public abstract class ValueListDisplaySource extends DisplaySource { } private Couple shorten(int number) { - if (number >= 1000000) - return Couple.create(Components.literal(String.valueOf(number / 1000000)), - Lang.translateDirect("display_source.value_list.million") - .append(WHITESPACE)); - if (number >= 1000) - return Couple.create(Components.literal(String.valueOf(number / 1000)), - Lang.translateDirect("display_source.value_list.thousand") - .append(WHITESPACE)); - return Couple.create(Components.literal(String.valueOf(number)), WHITESPACE); + if (number >= 1000000) { + return Couple.create(Component.literal(String.valueOf(number / 1000000)), + CreateLang.translateDirect("display_source.value_list.million") + .append(WHITESPACE)); + } + if (number >= 1000) { + return Couple.create(Component.literal(String.valueOf(number / 1000)), + CreateLang.translateDirect("display_source.value_list.thousand") + .append(WHITESPACE)); + } + return Couple.create(Component.literal(String.valueOf(number)), WHITESPACE); } protected boolean shortenNumbers(DisplayLinkContext context) { @@ -162,8 +166,8 @@ public abstract class ValueListDisplaySource extends DisplaySource { @OnlyIn(Dist.CLIENT) protected void addFullNumberConfig(ModularGuiLineBuilder builder) { builder.addSelectionScrollInput(0, 75, - (si, l) -> si.forOptions(Lang.translatedOptions("display_source.value_list", "shortened", "full_number")) - .titled(Lang.translateDirect("display_source.value_list.display")), + (si, l) -> si.forOptions(CreateLang.translatedOptions("display_source.value_list", "shortened", "full_number")) + .titled(CreateLang.translateDirect("display_source.value_list.display")), "Format"); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayBoardTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayBoardTarget.java index ba2ae4053f..742f309994 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayBoardTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayBoardTarget.java @@ -2,8 +2,9 @@ package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplayTarget; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; -import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; import com.simibubi.create.content.redstone.displayLink.source.SingleLineDisplaySource; import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.content.trains.display.FlapDisplayLayout; @@ -14,6 +15,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.AABB; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java deleted file mode 100644 index f59159e496..0000000000 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.simibubi.create.content.redstone.displayLink.target; - -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.redstone.displayLink.DisplayBehaviour; -import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.VoxelShape; - -public abstract class DisplayTarget extends DisplayBehaviour { - - public abstract void acceptText(int line, List text, DisplayLinkContext context); - - public abstract DisplayTargetStats provideStats(DisplayLinkContext context); - - public AABB getMultiblockBounds(LevelAccessor level, BlockPos pos) { - VoxelShape shape = level.getBlockState(pos) - .getShape(level, pos); - if (shape.isEmpty()) - return new AABB(pos); - return shape.bounds() - .move(pos); - } - - public Component getLineOptionText(int line) { - return Lang.translateDirect("display_target.line", line + 1); - } - - public static void reserve(int line, BlockEntity target, DisplayLinkContext context) { - if (line == 0) - return; - - CompoundTag tag = target.getPersistentData(); - CompoundTag compound = tag.getCompound("DisplayLink"); - compound.putLong("Line" + line, context.blockEntity() - .getBlockPos() - .asLong()); - tag.put("DisplayLink", compound); - } - - public boolean isReserved(int line, BlockEntity target, DisplayLinkContext context) { - CompoundTag tag = target.getPersistentData(); - CompoundTag compound = tag.getCompound("DisplayLink"); - - if (!compound.contains("Line" + line)) - return false; - - long l = compound.getLong("Line" + line); - BlockPos reserved = BlockPos.of(l); - - if (!reserved.equals(context.blockEntity() - .getBlockPos()) && AllBlocks.DISPLAY_LINK.has(target.getLevel() - .getBlockState(reserved))) - return true; - - compound.remove("Line" + line); - if (compound.isEmpty()) - tag.remove("DisplayLink"); - return false; - } - - public boolean requiresComponentSanitization() { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTargetStats.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTargetStats.java index 13dff95505..a3960db8b1 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTargetStats.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTargetStats.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.redstone.displayLink.target; +import com.simibubi.create.api.behaviour.display.DisplayTarget; + public record DisplayTargetStats(int maxRows, int maxColumns, DisplayTarget type) { } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java index 15ec2a0726..0e8dd76543 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java @@ -2,8 +2,9 @@ package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; +import com.simibubi.create.api.behaviour.display.DisplayTarget; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -65,7 +66,7 @@ public class LecternDisplayTarget extends DisplayTarget { } public Component getLineOptionText(int line) { - return Lang.translateDirect("display_target.page", line + 1); + return CreateLang.translateDirect("display_target.page", line + 1); } private ItemStack signBook(ItemStack book) { @@ -80,7 +81,7 @@ public class LecternDisplayTarget extends DisplayTarget { return written; } - + @Override public boolean requiresComponentSanitization() { return true; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java index 3c7a4d69de..705085bc07 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java @@ -2,9 +2,10 @@ package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; +import com.simibubi.create.api.behaviour.display.DisplayTarget; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity; @@ -41,7 +42,7 @@ public class SignDisplayTarget extends DisplayTarget { public DisplayTargetStats provideStats(DisplayLinkContext context) { return new DisplayTargetStats(4, 15, this); } - + @Override public boolean requiresComponentSanitization() { return true; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SingleLineDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SingleLineDisplayTarget.java index e1a59719f2..eeb0b64673 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SingleLineDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SingleLineDisplayTarget.java @@ -2,8 +2,9 @@ package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; +import com.simibubi.create.api.behaviour.display.DisplayTarget; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -14,19 +15,19 @@ public abstract class SingleLineDisplayTarget extends DisplayTarget { public final void acceptText(int line, List text, DisplayLinkContext context) { acceptLine(text.get(0), context); } - + protected abstract void acceptLine(MutableComponent text, DisplayLinkContext context); @Override public final DisplayTargetStats provideStats(DisplayLinkContext context) { return new DisplayTargetStats(1, getWidth(context), this); } - + @Override public Component getLineOptionText(int line) { - return Lang.translateDirect("display_target.single_line"); + return CreateLang.translateDirect("display_target.single_line"); } - + protected abstract int getWidth(DisplayLinkContext context); } diff --git a/src/main/java/com/simibubi/create/content/redstone/link/IRedstoneLinkable.java b/src/main/java/com/simibubi/create/content/redstone/link/IRedstoneLinkable.java index 4d44880cbb..bb5438196e 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/IRedstoneLinkable.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/IRedstoneLinkable.java @@ -1,22 +1,22 @@ package com.simibubi.create.content.redstone.link; import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; public interface IRedstoneLinkable { public int getTransmittedStrength(); - + public void setReceivedStrength(int power); - + public boolean isListening(); - + public boolean isAlive(); - + public Couple getNetworkKey(); - + public BlockPos getLocation(); - + } diff --git a/src/main/java/com/simibubi/create/content/redstone/link/LinkBehaviour.java b/src/main/java/com/simibubi/create/content/redstone/link/LinkBehaviour.java index d09c93142d..65ca26405f 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/LinkBehaviour.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/LinkBehaviour.java @@ -13,8 +13,8 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -204,7 +204,7 @@ public class LinkBehaviour extends BlockEntityBehaviour implements IRedstoneLink public boolean testHit(Boolean first, Vec3 hit) { BlockState state = blockEntity.getBlockState(); Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); - return (first ? firstSlot : secondSlot).testHit(state, localHit); + return (first ? firstSlot : secondSlot).testHit(getWorld(), getPos(), state, localHit); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/link/LinkHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/LinkHandler.java index ab4489dad3..a178ca67e2 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/LinkHandler.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/LinkHandler.java @@ -59,8 +59,8 @@ public class LinkHandler { .add(Vec3.atLowerCornerOf(ray.getDirection() .getNormal()) .scale(.25f)); - fakePlayerChoice = localHit.distanceToSqr(behaviour.firstSlot.getLocalOffset(blockState)) > localHit - .distanceToSqr(behaviour.secondSlot.getLocalOffset(blockState)); + fakePlayerChoice = localHit.distanceToSqr(behaviour.firstSlot.getLocalOffset(world, pos, blockState)) > localHit + .distanceToSqr(behaviour.secondSlot.getLocalOffset(world, pos, blockState)); } for (boolean first : Arrays.asList(false, true)) { diff --git a/src/main/java/com/simibubi/create/content/redstone/link/LinkRenderer.java b/src/main/java/com/simibubi/create/content/redstone/link/LinkRenderer.java index fe9dd8b563..280bdadb3a 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/LinkRenderer.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/LinkRenderer.java @@ -11,11 +11,12 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxRenderer; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.MultiBufferSource; @@ -34,10 +35,9 @@ public class LinkRenderer { public static void tick() { Minecraft mc = Minecraft.getInstance(); HitResult target = mc.hitResult; - if (target == null || !(target instanceof BlockHitResult)) + if (target == null || !(target instanceof BlockHitResult result)) return; - BlockHitResult result = (BlockHitResult) target; ClientLevel world = mc.level; BlockPos pos = result.getBlockPos(); @@ -45,8 +45,8 @@ public class LinkRenderer { if (behaviour == null) return; - Component freq1 = Lang.translateDirect("logistics.firstFrequency"); - Component freq2 = Lang.translateDirect("logistics.secondFrequency"); + Component freq1 = CreateLang.translateDirect("logistics.firstFrequency"); + Component freq2 = CreateLang.translateDirect("logistics.secondFrequency"); for (boolean first : Iterate.trueAndFalse) { AABB bb = new AABB(Vec3.ZERO, Vec3.ZERO).inflate(.25f); @@ -63,7 +63,7 @@ public class LinkRenderer { if (!empty) box.wideOutline(); - CreateClient.OUTLINER.showValueBox(Pair.of(Boolean.valueOf(first), pos), box.transform(transform)) + Outliner.getInstance().showOutline(Pair.of(Boolean.valueOf(first), pos), box.transform(transform)) .highlightFace(result.getDirection()); if (!hit) @@ -72,13 +72,13 @@ public class LinkRenderer { List tip = new ArrayList<>(); tip.add(label.copy()); tip.add( - Lang.translateDirect(empty ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace")); + CreateLang.translateDirect(empty ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace")); CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); } } public static void renderOnBlockEntity(SmartBlockEntity be, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { + MultiBufferSource buffer, int light, int overlay) { if (be == null || be.isRemoved()) return; @@ -98,7 +98,7 @@ public class LinkRenderer { ItemStack stack = first ? behaviour.frequencyFirst.getStack() : behaviour.frequencyLast.getStack(); ms.pushPose(); - transform.transform(be.getBlockState(), ms); + transform.transform(be.getLevel(), be.getBlockPos(), be.getBlockState(), ms); ValueBoxRenderer.renderItemIntoValueBox(stack, ms, buffer, light, overlay); ms.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlock.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlock.java index 4e8bf06df8..9b1aeadfb7 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlock.java @@ -4,8 +4,8 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -41,22 +41,22 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE } @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { - if (worldIn.isClientSide) + if (level.isClientSide) return; Direction blockFacing = state.getValue(FACING); if (fromPos.equals(pos.relative(blockFacing.getOpposite()))) { - if (!canSurvive(state, worldIn, pos)) { - worldIn.destroyBlock(pos, true); + if (!canSurvive(state, level, pos)) { + level.destroyBlock(pos, true); return; } } - if (!worldIn.getBlockTicks() + if (!level.getBlockTicks() .willTickThisTick(pos, this)) - worldIn.scheduleTick(pos, this, 0); + level.scheduleTick(pos, this, 1); } @Override @@ -71,6 +71,11 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE updateTransmittedSignal(state, worldIn, pos); } + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + public void updateTransmittedSignal(BlockState state, Level worldIn, BlockPos pos) { if (worldIn.isClientSide) return; @@ -78,6 +83,21 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE return; int power = getPower(worldIn, pos); + int powerFromPanels = getBlockEntityOptional(worldIn, pos).map(be -> { + if (be.panelSupport == null) + return 0; + Boolean tri = be.panelSupport.shouldBePoweredTristate(); + if (tri == null) + return -1; + return tri ? 15 : 0; + }) + .orElse(0); + + // Suppress update if an input panel exists but is not loaded + if (powerFromPanels == -1) + return; + + power = Math.max(power, powerFromPanels); boolean previouslyPowered = state.getValue(POWERED); if (previouslyPowered != power > 0) @@ -113,7 +133,7 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE if (!state.getValue(RECEIVER)) return 0; return getBlockEntityOptional(blockAccess, pos).map(RedstoneLinkBlockEntity::getReceivedSignal) - .orElse(0); + .orElse(0); } @Override @@ -123,10 +143,12 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE } @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (player.isShiftKeyDown()) - return toggleMode(state, worldIn, pos); + if (player.isShiftKeyDown() && toggleMode(state, level, pos) == InteractionResult.SUCCESS) { + level.scheduleTick(pos, this, 1); + return InteractionResult.SUCCESS; + } return InteractionResult.PASS; } @@ -138,7 +160,7 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE Boolean wasReceiver = state.getValue(RECEIVER); boolean blockPowered = worldIn.hasNeighborSignal(pos); worldIn.setBlock(pos, state.cycle(RECEIVER) - .setValue(POWERED, blockPowered), 3); + .setValue(POWERED, blockPowered), 3); be.transmit(wasReceiver ? 0 : getPower(worldIn, pos)); return InteractionResult.SUCCESS; }); @@ -146,8 +168,11 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE @Override public InteractionResult onWrenched(BlockState state, UseOnContext context) { - if (toggleMode(state, context.getLevel(), context.getClickedPos()) == InteractionResult.SUCCESS) + if (toggleMode(state, context.getLevel(), context.getClickedPos()) == InteractionResult.SUCCESS) { + context.getLevel() + .scheduleTick(context.getClickedPos(), this, 1); return InteractionResult.SUCCESS; + } return super.onWrenched(state, context); } @@ -190,7 +215,7 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE public Class getBlockEntityClass() { return RedstoneLinkBlockEntity.class; } - + @Override public BlockEntityType getBlockEntityType() { return AllBlockEntityTypes.REDSTONE_LINK.get(); diff --git a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlockEntity.java index 7b5b706d22..707f1b83ab 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlockEntity.java @@ -5,6 +5,7 @@ import java.util.List; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSupportBehaviour; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; @@ -23,12 +24,18 @@ public class RedstoneLinkBlockEntity extends SmartBlockEntity { private LinkBehaviour link; private boolean transmitter; + public FactoryPanelSupportBehaviour panelSupport; + public RedstoneLinkBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } @Override - public void addBehaviours(List behaviours) {} + public void addBehaviours(List behaviours) { + behaviours.add(panelSupport = new FactoryPanelSupportBehaviour(this, () -> link != null && link.isListening(), + () -> receivedSignal > 0, () -> AllBlocks.REDSTONE_LINK.get() + .updateTransmittedSignal(getBlockState(), level, worldPosition))); + } @Override public void addBehavioursDeferred(List behaviours) { @@ -115,6 +122,7 @@ public class RedstoneLinkBlockEntity extends SmartBlockEntity { level.blockUpdated(attachedPos, level.getBlockState(attachedPos) .getBlock()); receivedSignalChanged = false; + panelSupport.notifyPanels(); } } diff --git a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkFrequencySlot.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkFrequencySlot.java index 07b4d27976..6244bbc097 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkFrequencySlot.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkFrequencySlot.java @@ -2,12 +2,14 @@ package com.simibubi.create.content.redstone.link; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -21,7 +23,7 @@ public class RedstoneLinkFrequencySlot extends ValueBoxTransform.Dual { Vec3 vertical = VecHelper.voxelSpace(10f, 2.5f, 5.5f); @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Direction facing = state.getValue(RedstoneLinkBlock.FACING); Vec3 location = VecHelper.voxelSpace(8f, 3.01f, 5.5f); @@ -40,7 +42,7 @@ public class RedstoneLinkFrequencySlot extends ValueBoxTransform.Dual { } @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { Direction facing = state.getValue(RedstoneLinkBlock.FACING); float yRot = facing.getAxis() .isVertical() ? 0 : AngleHelper.horizontalAngle(facing) + 180; diff --git a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkNetworkHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkNetworkHandler.java index 5faa0f30ef..22f244fbbc 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkNetworkHandler.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkNetworkHandler.java @@ -9,10 +9,10 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.WorldHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.levelWrappers.WorldHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -104,13 +104,13 @@ public class RedstoneLinkNetworkHandler { globalPowerVersion.incrementAndGet(); int power = 0; - for (Iterator iterator = network.iterator(); iterator.hasNext();) { + for (Iterator iterator = network.iterator(); iterator.hasNext(); ) { IRedstoneLinkable other = iterator.next(); if (!other.isAlive()) { iterator.remove(); continue; } - + if (!withinRange(actor, other)) continue; @@ -118,8 +118,7 @@ public class RedstoneLinkNetworkHandler { power = Math.max(other.getTransmittedStrength(), power); } - if (actor instanceof LinkBehaviour) { - LinkBehaviour linkBehaviour = (LinkBehaviour) actor; + if (actor instanceof LinkBehaviour linkBehaviour) { // fix one-to-one loading order problem if (linkBehaviour.isListening()) { linkBehaviour.newPosition = true; diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlock.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlock.java index a2b793a585..52102c3ca7 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlock.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.block.IBE; @@ -25,7 +25,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; public class LecternControllerBlock extends LecternBlock - implements IBE, ISpecialBlockItemRequirement { + implements IBE, SpecialBlockItemRequirement { public LecternControllerBlock(Properties properties) { super(properties); diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlockEntity.java index 9d4915ca94..ff4549568f 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlockEntity.java @@ -22,6 +22,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.ForgeMod; @@ -31,15 +32,16 @@ public class LecternControllerBlockEntity extends SmartBlockEntity { private CompoundTag controllerNbt = new CompoundTag(); private UUID user; - private UUID prevUser; // used only on client - private boolean deactivatedThisTick; // used only on server + private UUID prevUser; // used only on client + private boolean deactivatedThisTick; // used only on server public LecternControllerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } @Override - public void addBehaviours(List behaviours) { } + public void addBehaviours(List behaviours) { + } @Override protected void write(CompoundTag compound, boolean clientPacket) { @@ -70,10 +72,12 @@ public class LecternControllerBlockEntity extends SmartBlockEntity { } public ItemStack getController() { - return getController(); + return createLinkedController(); } - public boolean hasUser() { return user != null; } + public boolean hasUser() { + return user != null; + } public boolean isUsedBy(Player player) { return hasUser() && user.equals(player.getUUID()); @@ -125,12 +129,11 @@ public class LecternControllerBlockEntity extends SmartBlockEntity { return; Entity entity = ((ServerLevel) level).getEntity(user); - if (!(entity instanceof Player)) { + if (!(entity instanceof Player player)) { stopUsing(null); return; } - Player player = (Player) entity; if (!playerInRange(player, level, worldPosition) || !playerIsUsingLectern(player)) stopUsing(player); } diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerRenderer.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerRenderer.java index eb705d8ce6..45290387b1 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerRenderer.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerRenderer.java @@ -5,9 +5,9 @@ import com.simibubi.create.AllItems; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerClientHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerClientHandler.java index f01e525d70..deff75be25 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerClientHandler.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerClientHandler.java @@ -14,15 +14,14 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.redstone.link.LinkBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; -import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.ControlsUtil; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.FontHelper.Palette; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.ChatFormatting; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; @@ -30,9 +29,11 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.client.gui.overlay.ForgeGui; import net.minecraftforge.client.gui.overlay.IGuiOverlay; @@ -189,8 +190,8 @@ public class LinkedControllerClientHandler { VoxelShape shape = mc.level.getBlockState(selectedLocation) .getShape(mc.level, selectedLocation); if (!shape.isEmpty()) - CreateClient.OUTLINER.showAABB("controller", shape.bounds() - .move(selectedLocation)) + Outliner.getInstance().showAABB("controller", shape.bounds() + .move(selectedLocation)) .colored(0xB73C2D) .lineWidth(1 / 16f); @@ -198,9 +199,9 @@ public class LinkedControllerClientHandler { LinkBehaviour linkBehaviour = BlockEntityBehaviour.get(mc.level, selectedLocation, LinkBehaviour.TYPE); if (linkBehaviour != null) { AllPackets.getChannel().sendToServer(new LinkedControllerBindPacket(integer, selectedLocation)); - Lang.translate("linked_controller.key_bound", controls.get(integer) - .getTranslatedKeyMessage() - .getString()) + CreateLang.translate("linked_controller.key_bound", controls.get(integer) + .getTranslatedKeyMessage() + .getString()) .sendStatus(mc.player); } MODE = Mode.IDLE; @@ -213,7 +214,7 @@ public class LinkedControllerClientHandler { } public static void renderOverlay(ForgeGui gui, GuiGraphics graphics, float partialTicks, int width1, - int height1) { + int height1) { Minecraft mc = Minecraft.getInstance(); if (mc.options.hideGui) return; @@ -223,7 +224,7 @@ public class LinkedControllerClientHandler { PoseStack poseStack = graphics.pose(); poseStack.pushPose(); - Screen tooltipScreen = new Screen(Components.immutableEmpty()) { + Screen tooltipScreen = new Screen(CommonComponents.EMPTY) { }; tooltipScreen.init(mc, width1, height1); @@ -236,9 +237,9 @@ public class LinkedControllerClientHandler { } List list = new ArrayList<>(); - list.add(Lang.translateDirect("linked_controller.bind_mode") + list.add(CreateLang.translateDirect("linked_controller.bind_mode") .withStyle(ChatFormatting.GOLD)); - list.addAll(TooltipHelper.cutTextComponent(Lang.translateDirect("linked_controller.press_keybind", keys), + list.addAll(TooltipHelper.cutTextComponent(CreateLang.translateDirect("linked_controller.press_keybind", keys), Palette.ALL_GRAY)); int width = 0; diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItem.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItem.java index 8988c489d7..644262d3d6 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItem.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItem.java @@ -7,8 +7,8 @@ import com.simibubi.create.AllItems; import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler; import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItemRenderer.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItemRenderer.java index 27d2dfb6a6..90e4de56d5 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItemRenderer.java @@ -9,12 +9,12 @@ import com.simibubi.create.content.redstone.link.controller.LinkedControllerClie import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.resources.model.BakedModel; @@ -60,33 +60,33 @@ public class LinkedControllerItemRenderer extends CustomRenderedItemModelRendere } static void resetButtons() { - for (int i = 0; i < buttons.size(); i++) { - buttons.get(i).startWithValue(0); + for (LerpedFloat button : buttons) { + button.startWithValue(0); } } @Override protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, - ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, - int overlay) { + ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { renderNormal(stack, model, renderer, transformType, ms, light); } protected static void renderNormal(ItemStack stack, CustomRenderedItemModel model, - PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, - int light) { + PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, + int light) { render(stack, model, renderer, transformType, ms, light, RenderType.NORMAL, false, false); } public static void renderInLectern(ItemStack stack, CustomRenderedItemModel model, - PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, - int light, boolean active, boolean renderDepression) { + PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, + int light, boolean active, boolean renderDepression) { render(stack, model, renderer, transformType, ms, light, RenderType.LECTERN, active, renderDepression); } protected static void render(ItemStack stack, CustomRenderedItemModel model, - PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, - int light, RenderType renderType, boolean active, boolean renderDepression) { + PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, + int light, RenderType renderType, boolean active, boolean renderDepression) { float pt = AnimationTickHolder.getPartialTicks(); var msr = TransformStack.of(ms); @@ -96,9 +96,9 @@ public class LinkedControllerItemRenderer extends CustomRenderedItemModelRendere Minecraft mc = Minecraft.getInstance(); boolean rightHanded = mc.options.mainHand().get() == HumanoidArm.RIGHT; ItemDisplayContext mainHand = - rightHanded ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; + rightHanded ? ItemDisplayContext.FIRST_PERSON_RIGHT_HAND : ItemDisplayContext.FIRST_PERSON_LEFT_HAND; ItemDisplayContext offHand = - rightHanded ? ItemDisplayContext.FIRST_PERSON_LEFT_HAND : ItemDisplayContext.FIRST_PERSON_RIGHT_HAND; + rightHanded ? ItemDisplayContext.FIRST_PERSON_LEFT_HAND : ItemDisplayContext.FIRST_PERSON_RIGHT_HAND; active = false; boolean noControllerInMain = !AllItems.LINKED_CONTROLLER.isIn(mc.player.getMainHandItem()); @@ -163,7 +163,7 @@ public class LinkedControllerItemRenderer extends CustomRenderedItemModelRendere } protected static void renderButton(PartialItemModelRenderer renderer, PoseStack ms, int light, float pt, BakedModel button, - float b, int index, boolean renderDepression) { + float b, int index, boolean renderDepression) { ms.pushPose(); if (renderDepression) { float depression = b * buttons.get(index).getValue(pt); diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerScreen.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerScreen.java index 916e5ff73d..9f12f565a6 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerScreen.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerScreen.java @@ -9,12 +9,12 @@ import java.util.List; import com.google.common.collect.ImmutableList; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.utility.ControlsUtil; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.Rect2i; @@ -36,19 +36,19 @@ public class LinkedControllerScreen extends AbstractSimiContainerScreen { menu.clearContents(); menu.sendClearPacket(); }); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { minecraft.player.closeContainer(); }); @@ -56,13 +56,13 @@ public class LinkedControllerScreen extends AbstractSimiContainerScreenat(x + background.width - 4, y + background.height - 56, -200) + .GuiRenderBuilder>at(x + background.getWidth() - 4, y + background.getHeight() - 56, -200) .scale(5) .render(graphics); } @@ -104,7 +104,7 @@ public class LinkedControllerScreen extends AbstractSimiContainerScreen addToTooltip(List list, int slot) { if (slot < 0 || slot >= 12) return list; - list.add(Lang.translateDirect("linked_controller.frequency_slot_" + ((slot % 2) + 1), ControlsUtil.getControls() + list.add(CreateLang.translateDirect("linked_controller.frequency_slot_" + ((slot % 2) + 1), ControlsUtil.getControls() .get(slot / 2) .getTranslatedKeyMessage() .getString()) diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerServerHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerServerHandler.java index 727fadc9a2..e5e631a6f5 100644 --- a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerServerHandler.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerServerHandler.java @@ -14,10 +14,10 @@ import com.simibubi.create.content.redstone.link.IRedstoneLinkable; import com.simibubi.create.content.redstone.link.LinkBehaviour; import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.WorldAttached; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.data.WorldAttached; import net.minecraft.core.BlockPos; import net.minecraft.world.level.LevelAccessor; @@ -30,12 +30,12 @@ public class LinkedControllerServerHandler { public static void tick(LevelAccessor world) { Map> map = receivedInputs.get(world); for (Iterator>> iterator = map.entrySet() - .iterator(); iterator.hasNext();) { + .iterator(); iterator.hasNext(); ) { Entry> entry = iterator.next(); Collection list = entry.getValue(); - for (Iterator entryIterator = list.iterator(); entryIterator.hasNext();) { + for (Iterator entryIterator = list.iterator(); entryIterator.hasNext(); ) { ManualFrequencyEntry manualFrequencyEntry = entryIterator.next(); manualFrequencyEntry.decrement(); if (!manualFrequencyEntry.isAlive()) { @@ -50,13 +50,13 @@ public class LinkedControllerServerHandler { } public static void receivePressed(LevelAccessor world, BlockPos pos, UUID uniqueID, List> collect, - boolean pressed) { + boolean pressed) { Map> map = receivedInputs.get(world); Collection list = map.computeIfAbsent(uniqueID, $ -> new ArrayList<>()); - WithNext: for (Couple activated : collect) { - for (Iterator iterator = list.iterator(); iterator.hasNext();) { - ManualFrequencyEntry entry = iterator.next(); + WithNext: + for (Couple activated : collect) { + for (ManualFrequencyEntry entry : list) { if (entry.getSecond() .equals(activated)) { if (!pressed) @@ -73,8 +73,8 @@ public class LinkedControllerServerHandler { ManualFrequencyEntry entry = new ManualFrequencyEntry(pos, activated); Create.REDSTONE_LINK_NETWORK_HANDLER.addToNetwork(world, entry); list.add(entry); - - for (IRedstoneLinkable linkable : Create.REDSTONE_LINK_NETWORK_HANDLER.getNetworkOf(world, entry)) + + for (IRedstoneLinkable linkable : Create.REDSTONE_LINK_NETWORK_HANDLER.getNetworkOf(world, entry)) if (linkable instanceof LinkBehaviour lb && lb.isListening()) AllAdvancements.LINKED_CONTROLLER.awardTo(world.getPlayerByUUID(uniqueID)); } @@ -110,7 +110,8 @@ public class LinkedControllerServerHandler { } @Override - public void setReceivedStrength(int power) {} + public void setReceivedStrength(int power) { + } @Override public boolean isListening() { diff --git a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlock.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlock.java index aedc160410..a2a4a4f88e 100644 --- a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlock.java @@ -8,14 +8,14 @@ import java.util.function.BiConsumer; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.equipment.clipboard.ClipboardEntry; import com.simibubi.create.content.equipment.wrench.IWrenchable; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -48,7 +48,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; public class NixieTubeBlock extends DoubleFaceAttachedBlock - implements IBE, IWrenchable, SimpleWaterloggedBlock, ISpecialBlockItemRequirement { + implements IBE, IWrenchable, SimpleWaterloggedBlock, SpecialBlockItemRequirement { protected final DyeColor color; @@ -221,13 +221,13 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock } @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, - boolean p_220069_6_) { - if (worldIn.isClientSide) + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, + boolean isMoving) { + if (level.isClientSide) return; - if (!worldIn.getBlockTicks() + if (!level.getBlockTicks() .willTickThisTick(pos, this)) - worldIn.scheduleTick(pos, this, 0); + level.scheduleTick(pos, this, 1); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlockEntity.java index b1c13be2c1..cb8c888cd5 100644 --- a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlockEntity.java @@ -9,13 +9,13 @@ import com.simibubi.create.content.trains.signal.SignalBlockEntity; import com.simibubi.create.content.trains.signal.SignalBlockEntity.SignalState; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.DynamicComponent; +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -82,7 +82,7 @@ public class NixieTubeBlockEntity extends SmartBlockEntity { public MutableComponent getFullText() { return customText.map(DynamicComponent::get) - .orElse(Components.literal("" + redstoneStrength)); + .orElse(Component.literal("" + redstoneStrength)); } public void updateRedstoneStrength(int signalStrength) { diff --git a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeRenderer.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeRenderer.java index 130097e594..92ec27bf0b 100644 --- a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeRenderer.java +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeRenderer.java @@ -6,16 +6,16 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.redstone.nixieTube.DoubleFaceAttachedBlock.DoubleAttachFace; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.RenderTypes; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.DyeHelper; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.font.glyphs.BakedGlyph; @@ -137,7 +137,7 @@ public class NixieTubeRenderer extends SafeBlockEntityRenderer { - private float offBelow; - private float onAbove; + private int offBelow; + private int onAbove; private boolean invert; + private boolean inStacks; - public ConfigureThresholdSwitchPacket(BlockPos pos, float offBelow, float onAbove, boolean invert) { + public ConfigureThresholdSwitchPacket(BlockPos pos, int offBelow, int onAbove, boolean invert, boolean inStacks) { super(pos); this.offBelow = offBelow; this.onAbove = onAbove; this.invert = invert; + this.inStacks = inStacks; } public ConfigureThresholdSwitchPacket(FriendlyByteBuf buffer) { @@ -24,16 +26,18 @@ public class ConfigureThresholdSwitchPacket extends BlockEntityConfigurationPack @Override protected void readSettings(FriendlyByteBuf buffer) { - offBelow = buffer.readFloat(); - onAbove = buffer.readFloat(); + offBelow = buffer.readInt(); + onAbove = buffer.readInt(); invert = buffer.readBoolean(); + inStacks = buffer.readBoolean(); } @Override protected void writeSettings(FriendlyByteBuf buffer) { - buffer.writeFloat(offBelow); - buffer.writeFloat(onAbove); + buffer.writeInt(offBelow); + buffer.writeInt(onAbove); buffer.writeBoolean(invert); + buffer.writeBoolean(inStacks); } @Override @@ -41,6 +45,7 @@ public class ConfigureThresholdSwitchPacket extends BlockEntityConfigurationPack be.offWhenBelow = offBelow; be.onWhenAbove = onAbove; be.setInverted(invert); + be.inStacks = inStacks; } } diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlock.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlock.java index cc80582ff5..b967183968 100644 --- a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlock.java @@ -4,8 +4,8 @@ import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.content.redstone.DirectedDirectionalBlock; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.gui.ScreenOpener; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlockEntity.java index 0163ed260c..26b901d7bc 100644 --- a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlockEntity.java @@ -6,6 +6,8 @@ import com.simibubi.create.compat.thresholdSwitch.FunctionalStorage; import com.simibubi.create.compat.thresholdSwitch.SophisticatedStorage; import com.simibubi.create.compat.thresholdSwitch.StorageDrawers; import com.simibubi.create.compat.thresholdSwitch.ThresholdSwitchCompat; +import com.simibubi.create.content.logistics.stockTicker.StockTickerBlockEntity; +import com.simibubi.create.content.processing.recipe.ProcessingInventory; import com.simibubi.create.content.redstone.DirectedDirectionalBlock; import com.simibubi.create.content.redstone.FilteredDetectorFilterSlot; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; @@ -16,10 +18,12 @@ import com.simibubi.create.foundation.blockEntity.behaviour.inventory.CapManipul import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.math.BlockFace; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; @@ -27,15 +31,21 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.ticks.TickPriority; +import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; public class ThresholdSwitchBlockEntity extends SmartBlockEntity { - public float onWhenAbove; - public float offWhenBelow; - public float currentLevel; + public int onWhenAbove; + public int offWhenBelow; + + public int currentMinLevel; + public int currentLevel; + public int currentMaxLevel; + public boolean inStacks; + private boolean redstoneState; private boolean inverted; private boolean poweredAfterDelay; @@ -53,8 +63,8 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { public ThresholdSwitchBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); - onWhenAbove = .75f; - offWhenBelow = .25f; + onWhenAbove = 128; + offWhenBelow = 64; currentLevel = -1; redstoneState = false; inverted = false; @@ -64,9 +74,12 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { @Override protected void read(CompoundTag compound, boolean clientPacket) { - onWhenAbove = compound.getFloat("OnAbove"); - offWhenBelow = compound.getFloat("OffBelow"); - currentLevel = compound.getFloat("Current"); + onWhenAbove = compound.getInt("OnAboveAmount"); + offWhenBelow = compound.getInt("OffBelowAmount"); + currentLevel = compound.getInt("CurrentAmount"); + currentMinLevel = compound.getInt("CurrentMinAmount"); + currentMaxLevel = compound.getInt("CurrentMaxAmount"); + inStacks = compound.getBoolean("InStacks"); redstoneState = compound.getBoolean("Powered"); inverted = compound.getBoolean("Inverted"); poweredAfterDelay = compound.getBoolean("PoweredAfterDelay"); @@ -74,15 +87,18 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { } protected void writeCommon(CompoundTag compound) { - compound.putFloat("OnAbove", onWhenAbove); - compound.putFloat("OffBelow", offWhenBelow); + compound.putFloat("OnAboveAmount", onWhenAbove); + compound.putFloat("OffBelowAmount", offWhenBelow); compound.putBoolean("Inverted", inverted); } @Override public void write(CompoundTag compound, boolean clientPacket) { writeCommon(compound); - compound.putFloat("Current", currentLevel); + compound.putInt("CurrentAmount", currentLevel); + compound.putInt("CurrentMinAmount", currentMinLevel); + compound.putInt("CurrentMaxAmount", currentMaxLevel); + compound.putBoolean("InStacks", inStacks); compound.putBoolean("Powered", redstoneState); compound.putBoolean("PoweredAfterDelay", poweredAfterDelay); super.write(compound, clientPacket); @@ -94,33 +110,52 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { super.writeSafe(compound); } - public float getStockLevel() { + public int getMinLevel() { + return currentMinLevel; + } + + public int getStockLevel() { return currentLevel; } + public int getMaxLevel() { + return currentMaxLevel; + } + public void updateCurrentLevel() { boolean changed = false; - float occupied = 0; - float totalSpace = 0; - float prevLevel = currentLevel; + int prevLevel = currentLevel; + int prevMaxLevel = currentMaxLevel; + + BlockPos target = getTargetPos(); + BlockEntity targetBlockEntity = level.getBlockEntity(target); observedInventory.findNewCapability(); observedTank.findNewCapability(); - BlockPos target = worldPosition.relative(ThresholdSwitchBlock.getTargetDirection(getBlockState())); - BlockEntity targetBlockEntity = level.getBlockEntity(target); - if (targetBlockEntity instanceof ThresholdSwitchObservable observable) { - currentLevel = observable.getPercent() / 100f; + currentMinLevel = observable.getMinValue(); + currentLevel = observable.getCurrentValue(); + currentMaxLevel = observable.getMaxValue(); + + /*} else if (StorageDrawers.isDrawer(targetBlockEntity) && observedInventory.hasInventory()) { + currentMinLevel = 0; + currentLevel = StorageDrawers.getItemCount(observedInventory.getInventory(), filtering); + currentMaxLevel = StorageDrawers.getTotalStorageSpace(observedInventory.getInventory()); + */ } else if (observedInventory.hasInventory() || observedTank.hasInventory()) { + currentMinLevel = 0; + currentLevel = 0; + currentMaxLevel = 0; + if (observedInventory.hasInventory()) { // Item inventory IItemHandler inv = observedInventory.getInventory(); if (invVersionTracker.stillWaiting(inv)) { - occupied = prevLevel; - totalSpace = 1f; + currentLevel = prevLevel; + currentMaxLevel = prevMaxLevel; } else { invVersionTracker.awaitNewVersion(inv); @@ -139,9 +174,9 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { if (space == 0) continue; - totalSpace += 1; + currentMaxLevel += space; if (filtering.test(stackInSlot)) - occupied += count * (1f / space); + currentLevel += count; } } } @@ -156,18 +191,19 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { if (space == 0) continue; - totalSpace += 1; + currentMaxLevel += space; if (filtering.test(stackInSlot)) - occupied += count * (1f / space); + currentLevel += count; } } - currentLevel = occupied / totalSpace; - } else { // No compatible inventories found + currentMinLevel = -1; + currentMaxLevel = -1; if (currentLevel == -1) return; + level.setBlock(worldPosition, getBlockState().setValue(ThresholdSwitchBlock.LEVEL, 0), 3); currentLevel = -1; redstoneState = false; @@ -176,7 +212,7 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { return; } - currentLevel = Mth.clamp(currentLevel, 0, 1); + currentLevel = Mth.clamp(currentLevel, currentMinLevel, currentMaxLevel); changed = currentLevel != prevLevel; boolean previouslyPowered = redstoneState; @@ -187,8 +223,9 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { boolean update = previouslyPowered != redstoneState; int displayLevel = 0; + float normedLevel = (float) (currentLevel - currentMinLevel) / (currentMaxLevel - currentMinLevel); if (currentLevel > 0) - displayLevel = (int) (1 + currentLevel * 4); + displayLevel = (int) (1 + normedLevel * 4); level.setBlock(worldPosition, getBlockState().setValue(ThresholdSwitchBlock.LEVEL, displayLevel), update ? 3 : 2); @@ -201,6 +238,50 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { } } + private boolean isSuitableInventory(BlockEntity be) { + return be != null && !(be instanceof StockTickerBlockEntity || be.getCapability(ForgeCapabilities.ITEM_HANDLER) + .filter(ProcessingInventory.class::isInstance) + .isPresent()); + } + + private BlockPos getTargetPos() { + return worldPosition.relative(ThresholdSwitchBlock.getTargetDirection(getBlockState())); + } + + public ItemStack getDisplayItemForScreen() { + BlockPos target = getTargetPos(); + return new ItemStack(level.getBlockState(target) + .getBlock()); + } + + public static enum ThresholdType { + UNSUPPORTED, ITEM, FLUID, CUSTOM; + } + + public MutableComponent format(int value, boolean stacks) { + ThresholdType type = getTypeOfCurrentTarget(); + if (type == ThresholdType.CUSTOM) + if (level.getBlockEntity(getTargetPos()) instanceof ThresholdSwitchObservable tso) + return tso.format(value); + + String suffix = type == ThresholdType.ITEM + ? stacks ? "schedule.condition.threshold.stacks" : "schedule.condition.threshold.items" + : "schedule.condition.threshold.buckets"; + return CreateLang.text(value + " ") + .add(CreateLang.translate(suffix)) + .component(); + } + + public ThresholdType getTypeOfCurrentTarget() { + if (observedInventory.hasInventory()) + return ThresholdType.ITEM; + if (observedTank.hasInventory()) + return ThresholdType.FLUID; + if (level.getBlockEntity(getTargetPos()) instanceof ThresholdSwitchObservable) + return ThresholdType.CUSTOM; + return ThresholdType.UNSUPPORTED; + } + protected void scheduleBlockTick() { Block block = getBlockState().getBlock(); if (!level.getBlockTicks() @@ -218,8 +299,8 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { @Override public void addBehaviours(List behaviours) { - behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(true)) - .withCallback($ -> { + behaviours + .add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(true)).withCallback($ -> { this.updateCurrentLevel(); invVersionTracker.reset(); })); @@ -229,7 +310,8 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { InterfaceProvider towardBlockFacing = (w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s)); - behaviours.add(observedInventory = new InvManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); + behaviours.add(observedInventory = new InvManipulationBehaviour(this, towardBlockFacing).bypassSidedness() + .withFilter(this::isSuitableInventory)); behaviours.add(observedTank = new TankManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); } @@ -248,6 +330,7 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity { public void updatePowerAfterDelay() { poweredAfterDelay = shouldBePowered(); level.blockUpdated(worldPosition, getBlockState().getBlock()); + sendData(); } public boolean isPowered() { diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchGenerator.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchGenerator.java index d85e974d68..703db6260f 100644 --- a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchGenerator.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.redstone.thresholdSwitch; import com.simibubi.create.Create; import com.simibubi.create.foundation.data.SpecialBlockStateGen; -import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; +import net.createmod.catnip.lang.Lang; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.client.model.generators.ModelFile; @@ -26,10 +26,10 @@ public class ThresholdSwitchGenerator extends SpecialBlockStateGen { public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { int level = state.getValue(ThresholdSwitchBlock.LEVEL); - String path = "threshold_switch/block_" + Lang.asId(state.getValue(ThresholdSwitchBlock.TARGET) + String path = "block/threshold_switch/block_" + Lang.asId(state.getValue(ThresholdSwitchBlock.TARGET) .name()); return prov.models() - .withExistingParent(path + "_" + level, Create.asResource("block/" + path)) + .withExistingParent(path + "_" + level, Create.asResource(path)) .texture("level", Create.asResource("block/threshold_switch/level_" + level)); } diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchObservable.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchObservable.java index 039945c2a6..f304a33672 100644 --- a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchObservable.java +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchObservable.java @@ -1,7 +1,15 @@ package com.simibubi.create.content.redstone.thresholdSwitch; +import net.minecraft.network.chat.MutableComponent; + public interface ThresholdSwitchObservable { - public float getPercent(); + public int getMaxValue(); + + public int getMinValue(); + + public int getCurrentValue(); + + public MutableComponent format(int value); } diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchScreen.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchScreen.java index 1c64ee4799..5bdbf72594 100644 --- a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchScreen.java +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchScreen.java @@ -1,103 +1,131 @@ package com.simibubi.create.content.redstone.thresholdSwitch; +import java.util.ArrayList; +import java.util.List; + import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlockEntity.ThresholdType; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.ScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; +import com.simibubi.create.foundation.utility.CreateLang; +import com.simibubi.create.infrastructure.ponder.AllCreatePonderTags; +import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.ScreenOpener; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; +import net.createmod.ponder.foundation.ui.PonderTagScreen; +import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.RedstoneTorchBlock; public class ThresholdSwitchScreen extends AbstractSimiScreen { private ScrollInput offBelow; private ScrollInput onAbove; + private SelectionScrollInput inStacks; + private IconButton confirmButton; private IconButton flipSignals; - private final Component invertSignal = Lang.translateDirect("gui.threshold_switch.invert_signal"); + private final Component invertSignal = CreateLang.translateDirect("gui.threshold_switch.invert_signal"); private final ItemStack renderedItem = new ItemStack(AllBlocks.THRESHOLD_SWITCH.get()); private AllGuiTextures background; private ThresholdSwitchBlockEntity blockEntity; private int lastModification; - private LerpedFloat cursor; - private LerpedFloat cursorLane; - public ThresholdSwitchScreen(ThresholdSwitchBlockEntity be) { - super(Lang.translateDirect("gui.threshold_switch.title")); - background = AllGuiTextures.STOCKSWITCH; + super(CreateLang.translateDirect("gui.threshold_switch.title")); + background = AllGuiTextures.THRESHOLD_SWITCH; this.blockEntity = be; lastModification = -1; } @Override protected void init() { - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); setWindowOffset(-20, 0); super.init(); int x = guiLeft; int y = guiTop; - cursor = LerpedFloat.linear() - .startWithValue(blockEntity.getLevelForDisplay()); - cursorLane = LerpedFloat.linear() - .startWithValue(blockEntity.getState() ? 1 : 0); + inStacks = (SelectionScrollInput) new SelectionScrollInput(x + 100, y + 23, 52, 42) + .forOptions(List.of(CreateLang.translateDirect("schedule.condition.threshold.items"), + CreateLang.translateDirect("schedule.condition.threshold.stacks"))) + .titled(CreateLang.translateDirect("schedule.condition.threshold.item_measure")) + .setState(blockEntity.inStacks ? 1 : 0); - offBelow = new ScrollInput(x + 36, y + 42, 102, 18).withRange(0, 100) - .titled(Components.empty()) + offBelow = new ScrollInput(x + 48, y + 47, 1, 18) + .withRange(blockEntity.getMinLevel(), blockEntity.getMaxLevel() + 1 - getValueStep()) + .titled(CreateLang.translateDirect("gui.threshold_switch.lower_threshold")) .calling(state -> { lastModification = 0; - offBelow.titled(Lang.translateDirect("gui.threshold_switch.move_to_upper_at", state)); - if (onAbove.getState() <= state) { - onAbove.setState(state + 1); + int valueStep = getValueStep(); + if (onAbove.getState() / valueStep <= state / valueStep) { + onAbove.setState((state + valueStep) / valueStep * valueStep); onAbove.onChanged(); } }) - .setState((int) (blockEntity.offWhenBelow * 100)); + .withStepFunction(sc -> sc.shift ? 10 * getValueStep() : getValueStep()) + .setState(blockEntity.offWhenBelow); - onAbove = new ScrollInput(x + 36, y + 20, 102, 18).withRange(1, 101) - .titled(Components.empty()) + onAbove = new ScrollInput(x + 48, y + 23, 1, 18) + .withRange(blockEntity.getMinLevel() + getValueStep(), blockEntity.getMaxLevel() + 1) + .titled(CreateLang.translateDirect("gui.threshold_switch.upper_threshold")) .calling(state -> { lastModification = 0; - onAbove.titled(Lang.translateDirect("gui.threshold_switch.move_to_lower_at", state)); - if (offBelow.getState() >= state) { - offBelow.setState(state - 1); + int valueStep = getValueStep(); + if (offBelow.getState() / valueStep >= state / valueStep) { + offBelow.setState((state - valueStep) / valueStep * valueStep); offBelow.onChanged(); } }) - .setState((int) (blockEntity.onWhenAbove * 100)); + .withStepFunction(sc -> sc.shift ? 10 * getValueStep() : getValueStep()) + .setState(blockEntity.onWhenAbove); onAbove.onChanged(); offBelow.onChanged(); addRenderableWidget(onAbove); addRenderableWidget(offBelow); + addRenderableWidget(inStacks); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); - confirmButton.withCallback(() -> { - onClose(); - }); + confirmButton = + new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> onClose()); addRenderableWidget(confirmButton); - flipSignals = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_FLIP); - flipSignals.withCallback(() -> { - send(!blockEntity.isInverted()); - }); + flipSignals = new IconButton(x + background.getWidth() - 62, y + background.getHeight() - 24, AllIcons.I_FLIP); + flipSignals.withCallback(() -> send(!blockEntity.isInverted())); flipSignals.setToolTip(invertSignal); addRenderableWidget(flipSignals); + + updateInputBoxes(); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int pButton) { + int itemX = guiLeft + 13; + int itemY = guiTop + 80; + if (mouseX >= itemX && mouseX < itemX + 16 && mouseY >= itemY && mouseY < itemY + 16) { + ScreenOpener.open(new PonderTagScreen(AllCreatePonderTags.THRESHOLD_SWITCH_TARGETS)); + return true; + } + return super.mouseClicked(mouseX, mouseY, pButton); } @Override @@ -106,48 +134,146 @@ public class ThresholdSwitchScreen extends AbstractSimiScreen { int y = guiTop; background.render(graphics, x, y); + graphics.drawString(font, title, x + background.getWidth() / 2 - font.width(title) / 2, y + 4, 0x592424, false); - AllGuiTextures.STOCKSWITCH_POWERED_LANE.render(graphics, x + 37, y + (blockEntity.isInverted() ? 20 : 42)); - AllGuiTextures.STOCKSWITCH_UNPOWERED_LANE.render(graphics, x + 37, y + (blockEntity.isInverted() ? 42 : 20)); - graphics.drawString(font, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, 0x592424, false); + ThresholdType typeOfCurrentTarget = blockEntity.getTypeOfCurrentTarget(); + boolean forItems = typeOfCurrentTarget == ThresholdType.ITEM; + AllGuiTextures inputBg = + forItems ? AllGuiTextures.THRESHOLD_SWITCH_ITEMCOUNT_INPUTS : AllGuiTextures.THRESHOLD_SWITCH_MISC_INPUTS; - AllGuiTextures sprite = AllGuiTextures.STOCKSWITCH_INTERVAL; - float lowerBound = offBelow.getState(); - float upperBound = onAbove.getState(); + inputBg.render(graphics, x + 44, y + 21); + inputBg.render(graphics, x + 44, y + 21 + 24); - sprite.bind(); - graphics.blit(sprite.location, (int) (x + upperBound) + 37, y + 20, (int) (sprite.startX + upperBound), sprite.startY, - (int) (sprite.width - upperBound), sprite.height); - graphics.blit(sprite.location, x + 37, y + 42, sprite.startX, sprite.startY, (int) (lowerBound), sprite.height); + int valueStep = 1; + boolean stacks = inStacks.getState() == 1; + if (typeOfCurrentTarget == ThresholdType.FLUID) + valueStep = 1000; - AllGuiTextures.STOCKSWITCH_ARROW_UP.render(graphics, (int) (x + lowerBound + 36) - 2, y + 37); - AllGuiTextures.STOCKSWITCH_ARROW_DOWN.render(graphics, (int) (x + upperBound + 36) - 3, y + 19); + if (forItems) { + Component suffix = + inStacks.getState() == 0 ? CreateLang.translateDirect("schedule.condition.threshold.items") + : CreateLang.translateDirect("schedule.condition.threshold.stacks"); + valueStep = inStacks.getState() == 0 ? 1 : 64; + graphics.drawString(font, suffix, x + 105, y + 28, 0xFFFFFFFF, true); + graphics.drawString(font, suffix, x + 105, y + 28 + 24, 0xFFFFFFFF, true); - if (blockEntity.currentLevel != -1) { - AllGuiTextures cursor = AllGuiTextures.STOCKSWITCH_CURSOR; - PoseStack ms = graphics.pose(); - ms.pushPose(); - ms.translate(Math.min(99, this.cursor.getValue(partialTicks) * sprite.width), - cursorLane.getValue(partialTicks) * 22, 0); - cursor.render(graphics, x + 34, y + 21); - ms.popPose(); } + graphics.drawString(font, + Component.literal("\u2265 " + (typeOfCurrentTarget == ThresholdType.UNSUPPORTED ? "" + : forItems ? onAbove.getState() / valueStep + : blockEntity.format(onAbove.getState() / valueStep, stacks) + .getString())), + x + 53, y + 28, 0xFFFFFFFF, true); + graphics.drawString(font, + Component.literal("\u2264 " + (typeOfCurrentTarget == ThresholdType.UNSUPPORTED ? "" + : forItems ? offBelow.getState() / valueStep + : blockEntity.format(offBelow.getState() / valueStep, stacks) + .getString())), + x + 53, y + 28 + 24, 0xFFFFFFFF, true); + GuiGameElement.of(renderedItem).at(x + background.width + 6, y + background.height - 56, -200) + .GuiRenderBuilder>at(x + background.getWidth() + 6, y + background.getHeight() - 56, -200) .scale(5) .render(graphics); + + int itemX = x + 13; + int itemY = y + 80; + + ItemStack displayItem = blockEntity.getDisplayItemForScreen(); + GuiGameElement.of(displayItem.isEmpty() ? new ItemStack(Items.BARRIER) : displayItem).at(itemX, itemY, 0) + .render(graphics); + + int torchX = x + 23; + int torchY = y + 24; + + boolean highlightTopRow = blockEntity.isInverted() ^ blockEntity.isPowered(); + AllGuiTextures.THRESHOLD_SWITCH_CURRENT_STATE.render(graphics, torchX - 3, + torchY - 4 + (highlightTopRow ? 0 : 24)); + + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(torchX - 5, torchY + 14, 200); + TransformStack.of(ms) + .rotateXDegrees(-22.5f) + .rotateYDegrees(45); + + for (boolean power : Iterate.trueAndFalse) { + GuiGameElement.of(Blocks.REDSTONE_TORCH.defaultBlockState() + .setValue(RedstoneTorchBlock.LIT, blockEntity.isInverted() ^ power)) + .scale(20) + .render(graphics); + ms.translate(0, 26, 0); + } + + ms.popPose(); + + if (mouseX >= itemX && mouseX < itemX + 16 && mouseY >= itemY && mouseY < itemY + 16) { + ArrayList list = new ArrayList<>(); + if (displayItem.isEmpty()) { + list.add(CreateLang.translateDirect("gui.threshold_switch.not_attached")); + list.add(CreateLang.translateDirect("display_link.view_compatible") + .withStyle(ChatFormatting.DARK_GRAY)); + graphics.renderComponentTooltip(font, list, mouseX, mouseY); + return; + } + + list.add(displayItem.getHoverName()); + if (typeOfCurrentTarget == ThresholdType.UNSUPPORTED) { + list.add(CreateLang.translateDirect("gui.threshold_switch.incompatible") + .withStyle(ChatFormatting.GRAY)); + list.add(CreateLang.translateDirect("display_link.view_compatible") + .withStyle(ChatFormatting.DARK_GRAY)); + graphics.renderComponentTooltip(font, list, mouseX, mouseY); + return; + } + + CreateLang + .translate("gui.threshold_switch.currently", + blockEntity.format(blockEntity.currentLevel / valueStep, stacks)) + .style(ChatFormatting.DARK_AQUA) + .addTo(list); + + if (blockEntity.currentMinLevel / valueStep == 0) + CreateLang + .translate("gui.threshold_switch.range_max", + blockEntity.format(blockEntity.currentMaxLevel / valueStep, stacks)) + .style(ChatFormatting.GRAY) + .addTo(list); + else + CreateLang + .translate("gui.threshold_switch.range", blockEntity.currentMinLevel / valueStep, + blockEntity.format(blockEntity.currentMaxLevel / valueStep, stacks)) + .style(ChatFormatting.GRAY) + .addTo(list); + + list.add(CreateLang.translateDirect("display_link.view_compatible") + .withStyle(ChatFormatting.DARK_GRAY)); + + graphics.renderComponentTooltip(font, list, mouseX, mouseY); + return; + } + + for (boolean power : Iterate.trueAndFalse) { + int thisTorchY = power ? torchY : torchY + 26; + if (mouseX >= torchX && mouseX < torchX + 16 && mouseY >= thisTorchY && mouseY < thisTorchY + 16) { + graphics.renderComponentTooltip(font, + List.of(CreateLang + .translate(power ^ blockEntity.isInverted() ? "gui.threshold_switch.power_on_when" + : "gui.threshold_switch.power_off_when") + .color(AbstractSimiWidget.HEADER_RGB) + .component()), + mouseX, mouseY); + return; + } + } } @Override public void tick() { super.tick(); - cursor.chase(blockEntity.getLevelForDisplay(), 1 / 4f, Chaser.EXP); - cursor.tickChaser(); - cursorLane.chase(blockEntity.getState() ? 1 : 0, 1 / 4f, Chaser.EXP); - cursorLane.tickChaser(); - if (lastModification >= 0) lastModification++; @@ -155,6 +281,51 @@ public class ThresholdSwitchScreen extends AbstractSimiScreen { lastModification = -1; send(blockEntity.isInverted()); } + + if (inStacks == null) + return; + + updateInputBoxes(); + } + + private void updateInputBoxes() { + ThresholdType typeOfCurrentTarget = blockEntity.getTypeOfCurrentTarget(); + boolean forItems = typeOfCurrentTarget == ThresholdType.ITEM; + final int valueStep = getValueStep(); + inStacks.active = inStacks.visible = forItems; + onAbove.setWidth(forItems ? 48 : 103); + offBelow.setWidth(forItems ? 48 : 103); + + onAbove.visible = typeOfCurrentTarget != ThresholdType.UNSUPPORTED; + offBelow.visible = typeOfCurrentTarget != ThresholdType.UNSUPPORTED; + + int min = blockEntity.currentMinLevel + valueStep; + int max = blockEntity.currentMaxLevel; + onAbove.withRange(min, max + 1); + int roundedState = Mth.clamp((onAbove.getState() / valueStep) * valueStep, min, max); + if (roundedState != onAbove.getState()) { + onAbove.setState(roundedState); + onAbove.onChanged(); + } + + min = blockEntity.currentMinLevel; + max = blockEntity.currentMaxLevel - valueStep; + offBelow.withRange(min, max + 1); + roundedState = Mth.clamp((offBelow.getState() / valueStep) * valueStep, min, max); + if (roundedState != offBelow.getState()) { + offBelow.setState(roundedState); + offBelow.onChanged(); + } + } + + private int getValueStep() { + boolean stacks = inStacks.getState() == 1; + int valueStep = 1; + if (blockEntity.getTypeOfCurrentTarget() == ThresholdType.FLUID) + valueStep = 1000; + else if (stacks) + valueStep = 64; + return valueStep; } @Override @@ -164,8 +335,8 @@ public class ThresholdSwitchScreen extends AbstractSimiScreen { protected void send(boolean invert) { AllPackets.getChannel() - .sendToServer(new ConfigureThresholdSwitchPacket(blockEntity.getBlockPos(), offBelow.getState() / 100f, - onAbove.getState() / 100f, invert)); + .sendToServer(new ConfigureThresholdSwitchPacket(blockEntity.getBlockPos(), offBelow.getState(), + onAbove.getState(), invert, inStacks.getState() == 1)); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicAndQuillItem.java b/src/main/java/com/simibubi/create/content/schematics/SchematicAndQuillItem.java index a72b0ad2c7..b113f7b529 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicAndQuillItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicAndQuillItem.java @@ -4,9 +4,9 @@ import java.util.Iterator; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; @@ -27,9 +27,9 @@ public class SchematicAndQuillItem extends Item { } public static void replaceStructureVoidWithAir(CompoundTag nbt) { - String air = RegisteredObjects.getKeyOrThrow(Blocks.AIR) + String air = CatnipServices.REGISTRIES.getKeyOrThrow(Blocks.AIR) .toString(); - String structureVoid = RegisteredObjects.getKeyOrThrow(Blocks.STRUCTURE_VOID) + String structureVoid = CatnipServices.REGISTRIES.getKeyOrThrow(Blocks.STRUCTURE_VOID) .toString(); NBTHelper.iterateCompoundList(nbt.getList("palette", 10), c -> { diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicChunkSource.java b/src/main/java/com/simibubi/create/content/schematics/SchematicChunkSource.java deleted file mode 100644 index 11aea1308e..0000000000 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicChunkSource.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.simibubi.create.content.schematics; - -import java.util.List; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -import javax.annotation.Nullable; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Holder; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.FullChunkStatus; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.flag.FeatureFlagSet; -import net.minecraft.world.item.crafting.RecipeManager; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkSource; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.LightChunk; -import net.minecraft.world.level.dimension.BuiltinDimensionTypes; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.entity.LevelEntityGetter; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.level.gameevent.GameEvent.Context; -import net.minecraft.world.level.lighting.LevelLightEngine; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.saveddata.maps.MapItemSavedData; -import net.minecraft.world.level.storage.WritableLevelData; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.scores.Scoreboard; -import net.minecraft.world.ticks.BlackholeTickAccess; -import net.minecraft.world.ticks.LevelTickAccess; - -public class SchematicChunkSource extends ChunkSource { - private final Level fallbackWorld; - - public SchematicChunkSource(Level world) { - fallbackWorld = world; - } - - @Nullable - @Override - public LightChunk getChunkForLighting(int x, int z) { - return getChunk(x, z); - } - - @Override - public Level getLevel() { - return fallbackWorld; - } - - @Nullable - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus status, boolean p_212849_4_) { - return getChunk(x, z); - } - - public ChunkAccess getChunk(int x, int z) { - return new EmptierChunk(fallbackWorld.registryAccess()); - } - - @Override - public String gatherStats() { - return "WrappedChunkProvider"; - } - - @Override - public LevelLightEngine getLightEngine() { - return fallbackWorld.getLightEngine(); - } - - @Override - public void tick(BooleanSupplier p_202162_, boolean p_202163_) {} - - @Override - public int getLoadedChunksCount() { - return 0; - } - - public static class EmptierChunk extends LevelChunk { - - private static final class DummyLevel extends Level { - - private DummyLevel(WritableLevelData pLevelData, ResourceKey pDimension, - RegistryAccess pRegistryAccess, Holder pDimensionTypeRegistration, - Supplier pProfiler, boolean pIsClientSide, boolean pIsDebug, long pBiomeZoomSeed, - int pMaxChainedNeighborUpdates) { - super(pLevelData, pDimension, pRegistryAccess, pDimensionTypeRegistration, pProfiler, pIsClientSide, pIsDebug, - pBiomeZoomSeed, pMaxChainedNeighborUpdates); - access = pRegistryAccess; - } - - private final RegistryAccess access; - - private DummyLevel(RegistryAccess access) { - this(null, null, access, access.registryOrThrow(Registries.DIMENSION_TYPE) - .getHolderOrThrow(BuiltinDimensionTypes.OVERWORLD), null, false, false, 0, 0); - } - - @Override - public ChunkSource getChunkSource() { - return null; - } - - @Override - public void levelEvent(Player pPlayer, int pType, BlockPos pPos, int pData) {} - - @Override - public void gameEvent(Entity pEntity, GameEvent pEvent, BlockPos pPos) {} - - @Override - public void gameEvent(GameEvent p_220404_, Vec3 p_220405_, Context p_220406_) {} - - @Override - public RegistryAccess registryAccess() { - return access; - } - - @Override - public List players() { - return null; - } - - @Override - public Holder getUncachedNoiseBiome(int pX, int pY, int pZ) { - return null; - } - - @Override - public float getShade(Direction pDirection, boolean pShade) { - return 0; - } - - @Override - public void sendBlockUpdated(BlockPos pPos, BlockState pOldState, BlockState pNewState, int pFlags) {} - - @Override - public void playSound(Player pPlayer, double pX, double pY, double pZ, SoundEvent pSound, - SoundSource pCategory, float pVolume, float pPitch) {} - - @Override - public void playSound(Player pPlayer, Entity pEntity, SoundEvent pEvent, SoundSource pCategory, - float pVolume, float pPitch) {} - - @Override - public void playSeededSound(Player p_220363_, double p_220364_, double p_220365_, double p_220366_, - SoundEvent p_220367_, SoundSource p_220368_, float p_220369_, float p_220370_, long p_220371_) {} - - @Override - public void playSeededSound(Player p_220372_, Entity p_220373_, Holder p_220374_, SoundSource p_220375_, - float p_220376_, float p_220377_, long p_220378_) {} - - @Override - public String gatherChunkSourceStats() { - return null; - } - - @Override - public Entity getEntity(int pId) { - return null; - } - - @Override - public MapItemSavedData getMapData(String pMapName) { - return null; - } - - @Override - public void setMapData(String pMapId, MapItemSavedData pData) {} - - @Override - public int getFreeMapId() { - return 0; - } - - @Override - public void destroyBlockProgress(int pBreakerId, BlockPos pPos, int pProgress) {} - - @Override - public Scoreboard getScoreboard() { - return null; - } - - @Override - public RecipeManager getRecipeManager() { - return null; - } - - @Override - protected LevelEntityGetter getEntities() { - return null; - } - - @Override - public LevelTickAccess getBlockTicks() { - return BlackholeTickAccess.emptyLevelList(); - } - - @Override - public LevelTickAccess getFluidTicks() { - return BlackholeTickAccess.emptyLevelList(); - } - - @Override - public FeatureFlagSet enabledFeatures() { - return FeatureFlagSet.of(); - } - - @Override - public void playSeededSound(Player pPlayer, double pX, double pY, double pZ, Holder pSound, - SoundSource pSource, float pVolume, float pPitch, long pSeed) {} - } - - public EmptierChunk(RegistryAccess registryAccess) { - super(new DummyLevel(registryAccess), null); - } - - public BlockState getBlockState(BlockPos p_180495_1_) { - return Blocks.VOID_AIR.defaultBlockState(); - } - - @Nullable - public BlockState setBlockState(BlockPos p_177436_1_, BlockState p_177436_2_, boolean p_177436_3_) { - return null; - } - - public FluidState getFluidState(BlockPos p_204610_1_) { - return Fluids.EMPTY.defaultFluidState(); - } - - public int getLightEmission(BlockPos p_217298_1_) { - return 0; - } - - @Nullable - public BlockEntity getBlockEntity(BlockPos p_177424_1_, EntityCreationType p_177424_2_) { - return null; - } - - public void addAndRegisterBlockEntity(BlockEntity p_150813_1_) {} - - public void setBlockEntity(BlockEntity p_177426_2_) {} - - public void removeBlockEntity(BlockPos p_177425_1_) {} - - public void markUnsaved() {} - - public boolean isEmpty() { - return true; - } - - public boolean isYSpaceEmpty(int p_76606_1_, int p_76606_2_) { - return true; - } - - public FullChunkStatus getFullStatus() { - return FullChunkStatus.FULL; - } - } -} diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicExport.java b/src/main/java/com/simibubi/create/content/schematics/SchematicExport.java index 66bbc923b7..7069fee813 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicExport.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicExport.java @@ -9,8 +9,8 @@ import java.nio.file.StandardOpenOption; import javax.annotation.Nullable; import com.simibubi.create.Create; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.FilesHelper; -import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -48,7 +48,7 @@ public class SchematicExport { SchematicAndQuillItem.clampGlueBoxes(level, new AABB(origin, origin.offset(bounds)), data); if (fileName.isEmpty()) - fileName = Lang.translateDirect("schematicAndQuill.fallbackName").getString(); + fileName = CreateLang.translateDirect("schematicAndQuill.fallbackName").getString(); if (!overwrite) fileName = FilesHelper.findFirstValidFilename(fileName, dir, "nbt"); if (!fileName.endsWith(".nbt")) diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicInstances.java b/src/main/java/com/simibubi/create/content/schematics/SchematicInstances.java index 91c47780c5..c04cbc2b20 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicInstances.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicInstances.java @@ -7,12 +7,12 @@ import javax.annotation.Nullable; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.simibubi.create.content.contraptions.StructureTransform; -import com.simibubi.create.foundation.utility.WorldAttached; +import net.createmod.catnip.data.WorldAttached; +import net.createmod.catnip.levelWrappers.SchematicLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.world.item.ItemStack; @@ -24,25 +24,25 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp public class SchematicInstances { - private static final WorldAttached> LOADED_SCHEMATICS = new WorldAttached<>($ -> CacheBuilder.newBuilder() + private static final WorldAttached> LOADED_SCHEMATICS = new WorldAttached<>($ -> CacheBuilder.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES) .build()); @Nullable - public static SchematicWorld get(Level world, ItemStack schematic) { - Cache map = LOADED_SCHEMATICS.get(world); + public static SchematicLevel get(Level world, ItemStack schematic) { + Cache map = LOADED_SCHEMATICS.get(world); int hash = getHash(schematic); - SchematicWorld ifPresent = map.getIfPresent(hash); + SchematicLevel ifPresent = map.getIfPresent(hash); if (ifPresent != null) return ifPresent; - SchematicWorld loadWorld = loadWorld(world, schematic); + SchematicLevel loadWorld = loadWorld(world, schematic); if (loadWorld == null) return null; map.put(hash, loadWorld); return loadWorld; } - private static SchematicWorld loadWorld(Level wrapped, ItemStack schematic) { + private static SchematicLevel loadWorld(Level wrapped, ItemStack schematic) { if (schematic == null || !schematic.hasTag()) return null; if (!schematic.getTag() @@ -50,7 +50,7 @@ public class SchematicInstances { return null; StructureTemplate activeTemplate = - SchematicItem.loadSchematic(wrapped.holderLookup(Registries.BLOCK), schematic); + SchematicItem.loadSchematic(wrapped, schematic); if (activeTemplate.getSize() .equals(Vec3i.ZERO)) @@ -58,7 +58,7 @@ public class SchematicInstances { BlockPos anchor = NbtUtils.readBlockPos(schematic.getTag() .getCompound("Anchor")); - SchematicWorld world = new SchematicWorld(anchor, wrapped); + SchematicLevel world = new SchematicLevel(anchor, wrapped); StructurePlaceSettings settings = SchematicItem.getSettings(schematic); activeTemplate.placeInWorld(world, anchor, anchor, settings, wrapped.getRandom(), Block.UPDATE_CLIENTS); @@ -66,7 +66,7 @@ public class SchematicInstances { settings.getRotation(), settings.getMirror()); for (BlockEntity be : world.getBlockEntities()) transform.apply(be); - + return world; } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/SchematicItem.java index 9bcffbcb5b..1b2d0c245c 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicItem.java @@ -12,19 +12,19 @@ import java.util.zip.GZIPInputStream; import javax.annotation.Nonnull; +import net.minecraft.core.registries.Registries; + import org.slf4j.Logger; import com.mojang.logging.LogUtils; import com.simibubi.create.AllItems; import com.simibubi.create.content.schematics.client.SchematicEditScreen; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.ScreenOpener; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderGetter; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; @@ -39,7 +39,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; @@ -47,7 +46,6 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.util.thread.SidedThreadGroups; public class SchematicItem extends Item { @@ -57,7 +55,7 @@ public class SchematicItem extends Item { super(properties); } - public static ItemStack create(HolderGetter lookup, String schematic, String owner) { + public static ItemStack create(Level level, String schematic, String owner) { ItemStack blueprint = AllItems.SCHEMATIC.asStack(); CompoundTag tag = new CompoundTag(); @@ -69,7 +67,7 @@ public class SchematicItem extends Item { tag.putString("Mirror", Mirror.NONE.name()); blueprint.setTag(tag); - writeSize(lookup, blueprint); + writeSize(level, blueprint); return blueprint; } @@ -78,18 +76,19 @@ public class SchematicItem extends Item { public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { if (stack.hasTag()) { if (stack.getTag() - .contains("File")) - tooltip.add(Components.literal(ChatFormatting.GOLD + stack.getTag() - .getString("File"))); + .contains("File")) { + tooltip.add(Component.literal(ChatFormatting.GOLD + stack.getTag() + .getString("File"))); + } } else { - tooltip.add(Lang.translateDirect("schematic.invalid").withStyle(ChatFormatting.RED)); + tooltip.add(CreateLang.translateDirect("schematic.invalid").withStyle(ChatFormatting.RED)); } super.appendHoverText(stack, worldIn, tooltip, flagIn); } - public static void writeSize(HolderGetter lookup, ItemStack blueprint) { + public static void writeSize(Level level, ItemStack blueprint) { CompoundTag tag = blueprint.getTag(); - StructureTemplate t = loadSchematic(lookup, blueprint); + StructureTemplate t = loadSchematic(level, blueprint); tag.put("Bounds", NBTHelper.writeVec3i(t.getSize())); blueprint.setTag(tag); SchematicInstances.clearHash(blueprint); @@ -109,7 +108,7 @@ public class SchematicItem extends Item { return settings; } - public static StructureTemplate loadSchematic(HolderGetter lookup, ItemStack blueprint) { + public static StructureTemplate loadSchematic(Level level, ItemStack blueprint) { StructureTemplate t = new StructureTemplate(); String owner = blueprint.getTag() .getString("Owner"); @@ -122,7 +121,7 @@ public class SchematicItem extends Item { Path dir; Path file; - if (Thread.currentThread().getThreadGroup() == SidedThreadGroups.SERVER) { + if (!level.isClientSide()) { dir = Paths.get("schematics", "uploaded").toAbsolutePath(); file = Paths.get(owner, schematic); } else { @@ -137,7 +136,7 @@ public class SchematicItem extends Item { try (DataInputStream stream = new DataInputStream(new BufferedInputStream( new GZIPInputStream(Files.newInputStream(path, StandardOpenOption.READ))))) { CompoundTag nbt = NbtIo.read(stream, new NbtAccounter(0x20000000L)); - t.load(lookup, nbt); + t.load(level.holderLookup(Registries.BLOCK), nbt); } catch (IOException e) { LOGGER.warn("Failed to read schematic", e); } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java b/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java index 9e633dd646..85b8291d57 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java @@ -6,17 +6,17 @@ import java.util.stream.Collectors; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.api.contraption.BlockMovementChecks; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.schematics.cannon.MaterialChecklist; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.blockEntity.IMergeableBE; -import com.simibubi.create.foundation.utility.BBHelper; import com.simibubi.create.foundation.utility.BlockHelper; +import net.createmod.catnip.levelWrappers.SchematicLevel; +import net.createmod.catnip.math.BBHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtUtils; @@ -32,6 +32,7 @@ import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.material.Fluids; public class SchematicPrinter { @@ -41,7 +42,7 @@ public class SchematicPrinter { private boolean schematicLoaded; private boolean isErrored; - private SchematicWorld blockReader; + private SchematicLevel blockReader; private BlockPos schematicAnchor; private BlockPos currentPos; @@ -65,7 +66,7 @@ public class SchematicPrinter { schematicLoaded = true; } } - + printingEntityIndex = compound.getInt("EntityProgress"); printStage = PrintStage.valueOf(compound.getString("PrintStage")); compound.getList("DeferredBlocks", 10).stream() @@ -78,7 +79,7 @@ public class SchematicPrinter { compound.put("CurrentPos", NbtUtils.writeBlockPos(currentPos)); if (schematicAnchor != null) compound.put("Anchor", NbtUtils.writeBlockPos(schematicAnchor)); - + compound.putInt("EntityProgress", printingEntityIndex); compound.putString("PrintStage", printStage.name()); ListTag tagDeferredBlocks = new ListTag(); @@ -92,12 +93,12 @@ public class SchematicPrinter { return; StructureTemplate activeTemplate = - SchematicItem.loadSchematic(originalWorld.holderLookup(Registries.BLOCK), blueprint); + SchematicItem.loadSchematic(originalWorld, blueprint); StructurePlaceSettings settings = SchematicItem.getSettings(blueprint, processNBT); schematicAnchor = NbtUtils.readBlockPos(blueprint.getTag() .getCompound("Anchor")); - blockReader = new SchematicWorld(schematicAnchor, originalWorld); + blockReader = new SchematicLevel(schematicAnchor, originalWorld); try { activeTemplate.placeInWorld(blockReader, schematicAnchor, schematicAnchor, settings, @@ -111,7 +112,7 @@ public class SchematicPrinter { BlockPos extraBounds = StructureTemplate.calculateRelativePosition(settings, new BlockPos(activeTemplate.getSize()) .offset(-1, -1, -1)); - blockReader.bounds = BBHelper.encapsulate(blockReader.bounds, extraBounds); + blockReader.setBounds(BBHelper.encapsulate(blockReader.getBounds(), extraBounds)); StructureTransform transform = new StructureTransform(settings.getRotationPivot(), Direction.Axis.Y, settings.getRotation(), settings.getMirror()); @@ -140,7 +141,7 @@ public class SchematicPrinter { public boolean isLoaded() { return schematicLoaded; } - + public boolean isErrored() { return isErrored; } @@ -177,9 +178,7 @@ public class SchematicPrinter { BlockPos target = getCurrentTarget(); if (printStage == PrintStage.ENTITIES) { - Entity entity = blockReader.getEntityStream() - .collect(Collectors.toList()) - .get(printingEntityIndex); + Entity entity = blockReader.getEntityList().get(printingEntityIndex); entityHandler.handle(target, entity); } else { BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); @@ -213,7 +212,7 @@ public class SchematicPrinter { BlockState toReplace = world.getBlockState(pos); BlockEntity toReplaceBE = world.getBlockEntity(pos); BlockState toReplaceOther = null; - + if (state.hasProperty(BlockStateProperties.BED_PART) && state.hasProperty(BlockStateProperties.HORIZONTAL_FACING) && state.getValue(BlockStateProperties.BED_PART) == BedPart.FOOT) toReplaceOther = world.getBlockState(pos.relative(state.getValue(BlockStateProperties.HORIZONTAL_FACING))); @@ -240,9 +239,7 @@ public class SchematicPrinter { public ItemRequirement getCurrentRequirement() { if (printStage == PrintStage.ENTITIES) - return ItemRequirement.of(blockReader.getEntityStream() - .collect(Collectors.toList()) - .get(printingEntityIndex)); + return ItemRequirement.of(blockReader.getEntityList().get(printingEntityIndex)); BlockPos target = getCurrentTarget(); BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); @@ -275,19 +272,18 @@ public class SchematicPrinter { } public void markAllEntityRequirements(MaterialChecklist checklist) { - blockReader.getEntityStream() - .forEach(entity -> { - ItemRequirement requirement = ItemRequirement.of(entity); - if (requirement.isEmpty()) - return; - if (requirement.isInvalid()) - return; - checklist.require(requirement); - }); + for (Entity entity : blockReader.getEntityList()) { + ItemRequirement requirement = ItemRequirement.of(entity); + if (requirement.isEmpty()) + return; + if (requirement.isInvalid()) + return; + checklist.require(requirement); + } } public boolean advanceCurrentPos() { - List entities = blockReader.getEntityStream().collect(Collectors.toList()); + List entities = blockReader.getEntityList(); do { if (printStage == PrintStage.BLOCKS) { @@ -343,4 +339,15 @@ public class SchematicPrinter { || BlockMovementChecks.isBrittle(state); } + public void sendBlockUpdates(Level level) { + BoundingBox bounds = blockReader.getBounds(); + BlockPos.betweenClosedStream(bounds.inflatedBy(1)) + .filter(pos -> !bounds.isInside(pos)) + .filter( + pos -> level.isLoaded(pos.offset(schematicAnchor)) && level.getFluidState(pos.offset(schematicAnchor)) + .is(Fluids.WATER)) + .forEach( + pos -> level.scheduleTick(pos.offset(schematicAnchor), Fluids.WATER, Fluids.WATER.getTickDelay(level))); + } + } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java index 5cb282b2e5..41b3fd0537 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java @@ -6,8 +6,8 @@ import javax.annotation.Nullable; import com.mojang.serialization.Codec; import com.simibubi.create.AllStructureProcessorTypes; -import com.simibubi.create.foundation.utility.NBTProcessors; +import net.createmod.catnip.nbt.NBTProcessors; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.Entity; diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java b/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java deleted file mode 100644 index 7c8fcc4e45..0000000000 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java +++ /dev/null @@ -1,277 +0,0 @@ -package com.simibubi.create.content.schematics; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import com.simibubi.create.Create; -import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; -import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; -import com.simibubi.create.foundation.utility.BBHelper; -import com.simibubi.create.foundation.utility.NBTProcessors; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.Registries; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.entity.decoration.ItemFrame; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.Biomes; -import net.minecraft.world.level.block.AbstractFurnaceBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.ticks.BlackholeTickAccess; -import net.minecraft.world.ticks.LevelTickAccess; - -public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor { - - protected Map blocks; - protected Map blockEntities; - protected List renderedBlockEntities; - protected List entities; - protected BoundingBox bounds; - - public BlockPos anchor; - public boolean renderMode; - - public SchematicWorld(Level original) { - this(BlockPos.ZERO, original); - } - - public SchematicWorld(BlockPos anchor, Level original) { - super(original); - setChunkSource(new SchematicChunkSource(this)); - this.blocks = new HashMap<>(); - this.blockEntities = new HashMap<>(); - this.bounds = new BoundingBox(BlockPos.ZERO); - this.anchor = anchor; - this.entities = new ArrayList<>(); - this.renderedBlockEntities = new ArrayList<>(); - } - - public Set getAllPositions() { - return blocks.keySet(); - } - - @Override - public boolean addFreshEntity(Entity entityIn) { - if (entityIn instanceof ItemFrame itemFrame) - itemFrame.setItem(NBTProcessors.withUnsafeNBTDiscarded(itemFrame.getItem())); - if (entityIn instanceof ArmorStand armorStand) - for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) - armorStand.setItemSlot(equipmentSlot, - NBTProcessors.withUnsafeNBTDiscarded(armorStand.getItemBySlot(equipmentSlot))); - - return entities.add(entityIn); - } - - public Stream getEntityStream() { - return entities.stream(); - } - - @Override - public BlockEntity getBlockEntity(BlockPos pos) { - if (isOutsideBuildHeight(pos)) - return null; - if (blockEntities.containsKey(pos)) - return blockEntities.get(pos); - if (!blocks.containsKey(pos.subtract(anchor))) - return null; - - BlockState blockState = getBlockState(pos); - if (blockState.hasBlockEntity()) { - try { - BlockEntity blockEntity = ((EntityBlock) blockState.getBlock()).newBlockEntity(pos, blockState); - if (blockEntity != null) { - onBEadded(blockEntity, pos); - blockEntities.put(pos, blockEntity); - renderedBlockEntities.add(blockEntity); - } - return blockEntity; - } catch (Exception e) { - Create.LOGGER.debug("Could not create BlockEntity of block " + blockState, e); - } - } - return null; - } - - protected void onBEadded(BlockEntity blockEntity, BlockPos pos) { - blockEntity.setLevel(this); - } - - @Override - public BlockState getBlockState(BlockPos globalPos) { - BlockPos pos = globalPos.subtract(anchor); - - if (pos.getY() - bounds.minY() == -1 && !renderMode) - return Blocks.DIRT.defaultBlockState(); - if (getBounds().isInside(pos) && blocks.containsKey(pos)) - return processBlockStateForPrinting(blocks.get(pos)); - return Blocks.AIR.defaultBlockState(); - } - - public Map getBlockMap() { - return blocks; - } - - @Override - public FluidState getFluidState(BlockPos pos) { - return getBlockState(pos).getFluidState(); - } - - @Override - public Holder getBiome(BlockPos pos) { - return world.registryAccess() - .lookupOrThrow(Registries.BIOME) - .getOrThrow(Biomes.PLAINS); - } - - @Override - public int getBrightness(LightLayer lightLayer, BlockPos pos) { - return 15; - } - - @Override - public float getShade(Direction face, boolean hasShade) { - return 1f; - } - - @Override - public LevelTickAccess getBlockTicks() { - return BlackholeTickAccess.emptyLevelList(); - } - - @Override - public LevelTickAccess getFluidTicks() { - return BlackholeTickAccess.emptyLevelList(); - } - - @Override - public List getEntities(Entity arg0, AABB arg1, Predicate arg2) { - return Collections.emptyList(); - } - - @Override - public List getEntitiesOfClass(Class arg0, AABB arg1, Predicate arg2) { - return Collections.emptyList(); - } - - @Override - public List players() { - return Collections.emptyList(); - } - - @Override - public int getSkyDarken() { - return 0; - } - - @Override - public boolean isStateAtPosition(BlockPos pos, Predicate predicate) { - return predicate.test(getBlockState(pos)); - } - - @Override - public boolean destroyBlock(BlockPos arg0, boolean arg1) { - return setBlock(arg0, Blocks.AIR.defaultBlockState(), 3); - } - - @Override - public boolean removeBlock(BlockPos arg0, boolean arg1) { - return setBlock(arg0, Blocks.AIR.defaultBlockState(), 3); - } - - @Override - public boolean setBlock(BlockPos pos, BlockState arg1, int arg2) { - pos = pos.immutable() - .subtract(anchor); - bounds = BBHelper.encapsulate(bounds, pos); - blocks.put(pos, arg1); - if (blockEntities.containsKey(pos)) { - BlockEntity blockEntity = blockEntities.get(pos); - if (!blockEntity.getType() - .isValid(arg1)) { - blockEntities.remove(pos); - renderedBlockEntities.remove(blockEntity); - } - } - - BlockEntity blockEntity = getBlockEntity(pos); - if (blockEntity != null) - blockEntities.put(pos, blockEntity); - - return true; - } - - @Override - public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) {} - - public BoundingBox getBounds() { - return bounds; - } - - public Iterable getBlockEntities() { - return blockEntities.values(); - } - - public Iterable getRenderedBlockEntities() { - return renderedBlockEntities; - } - - protected BlockState processBlockStateForPrinting(BlockState state) { - if (state.getBlock() instanceof AbstractFurnaceBlock && state.hasProperty(BlockStateProperties.LIT)) - state = state.setValue(BlockStateProperties.LIT, false); - return state; - } - - @Override - public ServerLevel getLevel() { - if (this.world instanceof ServerLevel) { - return (ServerLevel) this.world; - } - throw new IllegalStateException("Cannot use IServerWorld#getWorld in a client environment"); - } - - public void fixControllerBlockEntities() { - for (BlockEntity blockEntity : blockEntities.values()) { - if (!(blockEntity instanceof IMultiBlockEntityContainer multiBlockEntity)) - continue; - BlockPos lastKnown = multiBlockEntity.getLastKnownPos(); - BlockPos current = blockEntity.getBlockPos(); - if (lastKnown == null || current == null) - continue; - if (multiBlockEntity.isController()) - continue; - if (!lastKnown.equals(current)) { - BlockPos newControllerPos = multiBlockEntity.getController() - .offset(current.subtract(lastKnown)); - if (multiBlockEntity instanceof SmartBlockEntity sbe) - sbe.markVirtual(); - multiBlockEntity.setController(newControllerPos); - } - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java index 741274fe09..b02abb1787 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java @@ -18,16 +18,15 @@ import com.simibubi.create.AllItems; import com.simibubi.create.Create; import com.simibubi.create.content.schematics.SchematicExport.SchematicExportResult; import com.simibubi.create.content.schematics.table.SchematicTableBlockEntity; -import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.FilesHelper; -import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CSchematics; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.level.Level; @@ -104,7 +103,7 @@ public class ServerSchematicLoader { } Path playerSchematicsPath = Paths.get(getSchematicPath(), player.getGameProfile() - .getName()) + .getName()) .toAbsolutePath(); Path uploadPath = playerSchematicsPath.resolve(schematic) @@ -164,10 +163,10 @@ public class ServerSchematicLoader { protected boolean validateSchematicSizeOnServer(ServerPlayer player, long size) { Integer maxFileSize = getConfig().maxTotalSchematicSize.get(); if (size > maxFileSize * 1000) { - player.sendSystemMessage(Lang.translateDirect("schematics.uploadTooLarge") - .append(Components.literal(" (" + size / 1000 + " KB)."))); - player.sendSystemMessage(Lang.translateDirect("schematics.maxAllowedSize") - .append(Components.literal(" " + maxFileSize + " KB"))); + player.sendSystemMessage(CreateLang.translateDirect("schematics.uploadTooLarge") + .append(Component.literal(" (" + size / 1000 + " KB)."))); + player.sendSystemMessage(CreateLang.translateDirect("schematics.maxAllowedSize") + .append(Component.literal(" " + maxFileSize + " KB"))); return false; } return true; @@ -242,9 +241,8 @@ public class ServerSchematicLoader { public SchematicTableBlockEntity getTable(Level world, BlockPos pos) { BlockEntity be = world.getBlockEntity(pos); - if (!(be instanceof SchematicTableBlockEntity)) + if (!(be instanceof SchematicTableBlockEntity table)) return null; - SchematicTableBlockEntity table = (SchematicTableBlockEntity) be; return table; } @@ -271,7 +269,7 @@ public class ServerSchematicLoader { if (table == null) return; table.finishUpload(); - table.inventory.setStackInSlot(1, SchematicItem.create(world.holderLookup(Registries.BLOCK), schematic, player.getGameProfile() + table.inventory.setStackInSlot(1, SchematicItem.create(world, schematic, player.getGameProfile() .getName())); } catch (IOException e) { @@ -282,7 +280,7 @@ public class ServerSchematicLoader { } public void handleInstantSchematic(ServerPlayer player, String schematic, Level world, BlockPos pos, - BlockPos bounds) { + BlockPos bounds) { String playerName = player.getGameProfile().getName(); String playerPath = getSchematicPath() + "/" + playerName; String playerSchematicId = playerName + "/" + schematic; @@ -315,14 +313,14 @@ public class ServerSchematicLoader { return; SchematicExportResult result = SchematicExport.saveSchematic( - playerSchematics, schematic, true, - world, pos, pos.offset(bounds).offset(-1, -1, -1) + playerSchematics, schematic, true, + world, pos, pos.offset(bounds).offset(-1, -1, -1) ); if (result != null) player.setItemInHand(InteractionHand.MAIN_HAND, - SchematicItem.create(world.holderLookup(Registries.BLOCK), schematic, playerName)); + SchematicItem.create(world, schematic, playerName)); else - Lang.translate("schematicAndQuill.instant_failed") + CreateLang.translate("schematicAndQuill.instant_failed") .style(ChatFormatting.RED) .sendStatus(player); } diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/MaterialChecklist.java b/src/main/java/com/simibubi/create/content/schematics/cannon/MaterialChecklist.java index 5c87847a9a..24f0edf739 100644 --- a/src/main/java/com/simibubi/create/content/schematics/cannon/MaterialChecklist.java +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/MaterialChecklist.java @@ -12,8 +12,7 @@ import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides; import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides.ClipboardType; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -86,8 +85,8 @@ public class MaterialChecklist { MutableComponent textComponent; if (blocksNotLoaded) { - textComponent = Components.literal("\n" + ChatFormatting.RED); - textComponent = textComponent.append(Lang.translateDirect("materialChecklist.blocksNotLoaded")); + textComponent = Component.literal("\n" + ChatFormatting.RED); + textComponent = textComponent.append(CreateLang.translateDirect("materialChecklist.blocksNotLoaded")); pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); } @@ -103,7 +102,7 @@ public class MaterialChecklist { return name1.compareTo(name2); }); - textComponent = Components.empty(); + textComponent = Component.empty(); List completed = new ArrayList<>(); for (Item item : keys) { int amount = getRequiredAmount(item); @@ -117,10 +116,10 @@ public class MaterialChecklist { if (itemsWritten == MAX_ENTRIES_PER_PAGE) { itemsWritten = 0; - textComponent.append(Components.literal("\n >>>") + textComponent.append(Component.literal("\n >>>") .withStyle(ChatFormatting.BLUE)); pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); - textComponent = Components.empty(); + textComponent = Component.empty(); } itemsWritten++; @@ -130,10 +129,10 @@ public class MaterialChecklist { for (Item item : completed) { if (itemsWritten == MAX_ENTRIES_PER_PAGE) { itemsWritten = 0; - textComponent.append(Components.literal("\n >>>") + textComponent.append(Component.literal("\n >>>") .withStyle(ChatFormatting.DARK_GREEN)); pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); - textComponent = Components.empty(); + textComponent = Component.empty(); } itemsWritten++; @@ -146,7 +145,7 @@ public class MaterialChecklist { tag.putBoolean("readonly", true); tag.putString("author", "Schematicannon"); tag.putString("title", ChatFormatting.BLUE + "Material Checklist"); - textComponent = Lang.translateDirect("materialChecklist") + textComponent = CreateLang.translateDirect("materialChecklist") .setStyle(Style.EMPTY.withColor(ChatFormatting.BLUE) .withItalic(Boolean.FALSE)); book.getOrCreateTagElement("display") @@ -165,7 +164,7 @@ public class MaterialChecklist { List currentPage = new ArrayList<>(); if (blocksNotLoaded) { - currentPage.add(new ClipboardEntry(false, Lang.translateDirect("materialChecklist.blocksNotLoaded") + currentPage.add(new ClipboardEntry(false, CreateLang.translateDirect("materialChecklist.blocksNotLoaded") .withStyle(ChatFormatting.RED))); } @@ -194,7 +193,7 @@ public class MaterialChecklist { if (itemsWritten == MAX_ENTRIES_PER_CLIPBOARD_PAGE) { itemsWritten = 0; - currentPage.add(new ClipboardEntry(false, Components.literal(">>>") + currentPage.add(new ClipboardEntry(false, Component.literal(">>>") .withStyle(ChatFormatting.DARK_GRAY))); pages.add(currentPage); currentPage = new ArrayList<>(); @@ -202,13 +201,13 @@ public class MaterialChecklist { itemsWritten++; currentPage.add(new ClipboardEntry(false, entry(new ItemStack(item), amount, true, false)) - .displayItem(new ItemStack(item))); + .displayItem(new ItemStack(item), amount)); } for (Item item : completed) { if (itemsWritten == MAX_ENTRIES_PER_CLIPBOARD_PAGE) { itemsWritten = 0; - currentPage.add(new ClipboardEntry(true, Components.literal(">>>") + currentPage.add(new ClipboardEntry(true, Component.literal(">>>") .withStyle(ChatFormatting.DARK_GREEN))); pages.add(currentPage); currentPage = new ArrayList<>(); @@ -216,14 +215,14 @@ public class MaterialChecklist { itemsWritten++; currentPage.add(new ClipboardEntry(true, entry(new ItemStack(item), getRequiredAmount(item), false, false)) - .displayItem(new ItemStack(item))); + .displayItem(new ItemStack(item), 0)); } pages.add(currentPage); ClipboardEntry.saveAll(pages, clipboard); ClipboardOverrides.switchTo(ClipboardType.WRITTEN, clipboard); clipboard.getOrCreateTagElement("display") - .putString("Name", Component.Serializer.toJson(Lang.translateDirect("materialChecklist") + .putString("Name", Component.Serializer.toJson(CreateLang.translateDirect("materialChecklist") .setStyle(Style.EMPTY.withItalic(Boolean.FALSE)))); tag.putBoolean("Readonly", true); clipboard.setTag(tag); @@ -240,8 +239,8 @@ public class MaterialChecklist { private MutableComponent entry(ItemStack item, int amount, boolean unfinished, boolean forBook) { int stacks = amount / 64; int remainder = amount % 64; - MutableComponent tc = Components.empty(); - tc.append(Components.translatable(item.getDescriptionId()) + MutableComponent tc = Component.empty(); + tc.append(Component.translatable(item.getDescriptionId()) .setStyle(Style.EMPTY .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(item))))); @@ -249,9 +248,9 @@ public class MaterialChecklist { tc.append(" \u2714"); if (!unfinished || forBook) tc.withStyle(unfinished ? ChatFormatting.BLUE : ChatFormatting.DARK_GREEN); - return tc.append(Components.literal("\n" + " x" + amount) + return tc.append(Component.literal("\n" + " x" + amount) .withStyle(ChatFormatting.BLACK)) - .append(Components.literal(" | " + stacks + "\u25A4 +" + remainder + (forBook ? "\n" : "")) + .append(Component.literal(" | " + stacks + "\u25A4 +" + remainder + (forBook ? "\n" : "")) .withStyle(ChatFormatting.GRAY)); } diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlockEntity.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlockEntity.java index 9f3a21447e..78f7667a1f 100644 --- a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlockEntity.java @@ -24,11 +24,11 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CSchematics; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -566,6 +566,8 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP } public void finishedPrinting() { + if (replaceMode == ConfigureSchematicannonPacket.Option.REPLACE_EMPTY.ordinal()) + printer.sendBlockUpdates(level); inventory.setStackInSlot(0, ItemStack.EMPTY); inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get(), inventory.getStackInSlot(1) .getCount() + 1)); @@ -652,9 +654,9 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP if (remainingFuel > getShotsPerGunpowder()) { remainingFuel = getShotsPerGunpowder(); sendUpdate = true; - return; + return; } - + if (remainingFuel > 0) return; @@ -829,7 +831,7 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP @Override public Component getDisplayName() { - return Lang.translateDirect("gui.schematicannon.title"); + return CreateLang.translateDirect("gui.schematicannon.title"); } public void updateChecklist() { diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonRenderer.java index e34e3e3e1f..ab69eb1454 100644 --- a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonRenderer.java @@ -9,11 +9,11 @@ import com.simibubi.create.content.schematics.cannon.LaunchedItem.ForBelt; import com.simibubi.create.content.schematics.cannon.LaunchedItem.ForBlockState; import com.simibubi.create.content.schematics.cannon.LaunchedItem.ForEntity; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.VirtualRenderHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.ponder.render.VirtualRenderHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -56,14 +56,14 @@ public class SchematicannonRenderer extends SafeBlockEntityRenderer replaceLevelIndicators; protected Vector replaceLevelButtons; @@ -82,7 +83,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen { sendOptionUpdate(Option.PLAY, true); }); - playIndicator = new Indicator(x + 75, y + 79, Components.immutableEmpty()); - pauseButton = new IconButton(x + 93, y + 86, AllIcons.I_PAUSE); + playIndicator = new Indicator(x + 75, y + 79, CommonComponents.EMPTY); + pauseButton = new IconButton(x + 93, y + 85, AllIcons.I_PAUSE); pauseButton.withCallback(() -> { sendOptionUpdate(Option.PAUSE, true); }); - pauseIndicator = new Indicator(x + 93, y + 79, Components.immutableEmpty()); - resetButton = new IconButton(x + 111, y + 86, AllIcons.I_STOP); + pauseIndicator = new Indicator(x + 93, y + 79, CommonComponents.EMPTY); + resetButton = new IconButton(x + 111, y + 85, AllIcons.I_STOP); resetButton.withCallback(() -> { sendOptionUpdate(Option.STOP, true); }); - resetIndicator = new Indicator(x + 111, y + 79, Components.immutableEmpty()); + resetIndicator = new Indicator(x + 111, y + 79, CommonComponents.EMPTY); resetIndicator.state = State.RED; addRenderableWidgets(playButton, playIndicator, pauseButton, pauseIndicator, resetButton, resetIndicator); - confirmButton = new IconButton(x + 180, y + 117, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + 180, y + 111, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { minecraft.player.closeContainer(); }); addRenderableWidget(confirmButton); - showSettingsButton = new IconButton(x + 9, y + 117, AllIcons.I_PLACEMENT_SETTINGS); + showSettingsButton = new IconButton(x + 8, y + 111, AllIcons.I_PLACEMENT_SETTINGS); showSettingsButton.withCallback(() -> { showSettingsIndicator.state = placementSettingsHidden() ? State.GREEN : State.OFF; initPlacementSettings(); }); - showSettingsButton.setToolTip(Lang.translateDirect(_showSettings)); + showSettingsButton.setToolTip(CreateLang.translateDirect(_showSettings)); addRenderableWidget(showSettingsButton); - showSettingsIndicator = new Indicator(x + 9, y + 111, Components.immutableEmpty()); - addRenderableWidget(showSettingsIndicator); + showSettingsIndicator = new Indicator(x + 9, y + 111, CommonComponents.EMPTY); +// addRenderableWidget(showSettingsIndicator); - extraAreas = ImmutableList.of(new Rect2i(x + BG_TOP.width, y + BG_TOP.height + BG_BOTTOM.height - 62, 84, 92)); + extraAreas = ImmutableList.of(new Rect2i(x + BG_TOP.getWidth(), y + BG_TOP.getHeight() + BG_BOTTOM.getHeight() - 62, 84, 92)); tick(); } @@ -144,14 +145,14 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen(4); List icons = ImmutableList.of(AllIcons.I_DONT_REPLACE, AllIcons.I_REPLACE_SOLID, AllIcons.I_REPLACE_ANY, AllIcons.I_REPLACE_EMPTY); - List toolTips = ImmutableList.of(Lang.translateDirect("gui.schematicannon.option.dontReplaceSolid"), - Lang.translateDirect("gui.schematicannon.option.replaceWithSolid"), - Lang.translateDirect("gui.schematicannon.option.replaceWithAny"), - Lang.translateDirect("gui.schematicannon.option.replaceWithEmpty")); + List toolTips = ImmutableList.of(CreateLang.translateDirect("gui.schematicannon.option.dontReplaceSolid"), + CreateLang.translateDirect("gui.schematicannon.option.replaceWithSolid"), + CreateLang.translateDirect("gui.schematicannon.option.replaceWithAny"), + CreateLang.translateDirect("gui.schematicannon.option.replaceWithEmpty")); for (int i = 0; i < 4; i++) { - replaceLevelIndicators.add(new Indicator(x + 33 + i * 18, y + 111, Components.immutableEmpty())); - IconButton replaceLevelButton = new IconButton(x + 33 + i * 18, y + 117, icons.get(i)); + replaceLevelIndicators.add(new Indicator(x + 33 + i * 18, y + 111, CommonComponents.EMPTY)); + IconButton replaceLevelButton = new IconButton(x + 33 + i * 18, y + 111, icons.get(i)); int replaceMode = i; replaceLevelButton.withCallback(() -> { if (menu.contentHolder.replaceMode != replaceMode) @@ -161,24 +162,24 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen { sendOptionUpdate(Option.SKIP_MISSING, !menu.contentHolder.skipMissing); }); - skipMissingButton.setToolTip(Lang.translateDirect("gui.schematicannon.option.skipMissing")); - skipMissingIndicator = new Indicator(x + 111, y + 111, Components.immutableEmpty()); - Collections.addAll(placementSettingWidgets, skipMissingButton, skipMissingIndicator); + skipMissingButton.setToolTip(CreateLang.translateDirect("gui.schematicannon.option.skipMissing")); + skipMissingIndicator = new Indicator(x + 111, y + 111, CommonComponents.EMPTY); + Collections.addAll(placementSettingWidgets, skipMissingButton); - skipBlockEntitiesButton = new IconButton(x + 129, y + 117, AllIcons.I_SKIP_BLOCK_ENTITIES); + skipBlockEntitiesButton = new IconButton(x + 135, y + 111, AllIcons.I_SKIP_BLOCK_ENTITIES); skipBlockEntitiesButton.withCallback(() -> { sendOptionUpdate(Option.SKIP_BLOCK_ENTITIES, !menu.contentHolder.replaceBlockEntities); }); - skipBlockEntitiesButton.setToolTip(Lang.translateDirect("gui.schematicannon.option.skipBlockEntities")); - skipBlockEntitiesIndicator = new Indicator(x + 129, y + 111, Components.immutableEmpty()); - Collections.addAll(placementSettingWidgets, skipBlockEntitiesButton, skipBlockEntitiesIndicator); + skipBlockEntitiesButton.setToolTip(CreateLang.translateDirect("gui.schematicannon.option.skipBlockEntities")); + skipBlockEntitiesIndicator = new Indicator(x + 129, y + 111, CommonComponents.EMPTY); + Collections.addAll(placementSettingWidgets, skipBlockEntitiesButton); addRenderableWidgets(placementSettingWidgets); } @@ -195,11 +196,11 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen tip = button.getToolTip(); tip.add((enabled ? optionEnabled : optionDisabled).plainCopy() - .withStyle(BLUE)); + .withStyle(enabled ? ChatFormatting.DARK_GREEN : ChatFormatting.RED)); tip.addAll(TooltipHelper - .cutTextComponent(Lang.translateDirect("gui.schematicannon.option." + tooltipKey + ".description"), Palette.ALL_GRAY)); + .cutTextComponent(CreateLang.translateDirect("gui.schematicannon.option." + tooltipKey + ".description"), Palette.ALL_GRAY)); } @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - int invX = getLeftOfCentered(AllGuiTextures.PLAYER_INVENTORY.width); - int invY = topPos + BG_TOP.height + BG_BOTTOM.height + 2; + int invX = getLeftOfCentered(AllGuiTextures.PLAYER_INVENTORY.getWidth()); + int invY = topPos + BG_TOP.getHeight() + BG_BOTTOM.getHeight() + 2; renderPlayerInventory(graphics, invX, invY); int x = leftPos; int y = topPos; BG_TOP.render(graphics, x, y); - BG_BOTTOM.render(graphics, x, y + BG_TOP.height); + BG_BOTTOM.render(graphics, x, y + BG_TOP.getHeight()); + AllGuiTextures.SCHEMATIC_TITLE.render(graphics, x, y - 2); SchematicannonBlockEntity be = menu.contentHolder; renderPrintingProgress(graphics, x, y, be.schematicProgress); @@ -292,28 +293,28 @@ public class SchematicannonScreen extends AbstractSimiContainerScreenat(x + BG_TOP.width, y + BG_TOP.height + BG_BOTTOM.height - 48, -200) + .GuiRenderBuilder>at(x + BG_TOP.getWidth(), y + BG_TOP.getHeight() + BG_BOTTOM.getHeight() - 48, -200) .scale(5) .render(graphics); - graphics.drawCenteredString(font, title, x + (BG_TOP.width - 8) / 2, y + 3, 0xFFFFFF); + graphics.drawString(font, title, x + (BG_TOP.getWidth() - 8 - font.width(title)) / 2, y + 2, 0x505050, false); - Component msg = Lang.translateDirect("schematicannon.status." + be.statusMsg); + Component msg = CreateLang.translateDirect("schematicannon.status." + be.statusMsg); int stringWidth = font.width(msg); if (be.missingItem != null) { stringWidth += 16; GuiGameElement.of(be.missingItem).at(x + 128, y + 49, 100) + .GuiRenderBuilder>at(x + 128, y + 49, 100) .scale(1) .render(graphics); } - graphics.drawString(font, msg, x + 103 - stringWidth / 2, y + 53, 0xCCDDFF); + graphics.drawString(font, msg, x + 103 - stringWidth / 2, y + 53, 0xDDEEFF); if ("schematicErrored".equals(be.statusMsg)) - graphics.drawString(font, Lang.translateDirect("schematicannon.status.schematicErroredCheckLogs"), - x + 103 - stringWidth / 2, y + 65, 0xCCDDFF); + graphics.drawString(font, CreateLang.translateDirect("schematicannon.status.schematicErroredCheckLogs"), + x + 103 - stringWidth / 2, y + 65, 0xDDEEFF); } protected void renderBlueprintHighlight(GuiGraphics graphics, int x, int y) { @@ -323,13 +324,13 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen= fuelX && mouseY >= fuelY && mouseX <= fuelX + AllGuiTextures.SCHEMATICANNON_FUEL.width - && mouseY <= fuelY + AllGuiTextures.SCHEMATICANNON_FUEL.height) { + if (mouseX >= fuelX && mouseY >= fuelY && mouseX <= fuelX + AllGuiTextures.SCHEMATICANNON_FUEL.getWidth() + && mouseY <= fuelY + AllGuiTextures.SCHEMATICANNON_FUEL.getHeight()) { List tooltip = getFuelLevelTooltip(be); graphics.renderComponentTooltip(font, tooltip, mouseX, mouseY); } @@ -358,15 +359,15 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen tooltip = new ArrayList<>(); if (be.hasCreativeCrate) { - tooltip.add(Lang.translateDirect(_gunpowderLevel, "" + 100)); - tooltip.add(Components.literal("(").append(AllBlocks.CREATIVE_CRATE.get() - .getName()) + tooltip.add(CreateLang.translateDirect(_gunpowderLevel, "" + 100)); + tooltip.add(Component.literal("(").append(AllBlocks.CREATIVE_CRATE.get() + .getName()) .append(")") .withStyle(DARK_PURPLE)); return tooltip; } int fillPercent = (int) ((be.remainingFuel / (float) be.getShotsPerGunpowder()) * 100); - tooltip.add(Lang.translateDirect(_gunpowderLevel, fillPercent)); - tooltip.add(Lang.translateDirect(_shotsRemaining, Components.literal(Integer.toString(shotsLeft)).withStyle(BLUE)) + tooltip.add(CreateLang.translateDirect(_gunpowderLevel, fillPercent)); + tooltip.add(CreateLang.translateDirect(_shotsRemaining, Component.literal(Integer.toString(shotsLeft)).withStyle(BLUE)) .withStyle(GRAY)); - if (shotsLeftWithItems != shotsLeft) - tooltip.add(Lang + if (shotsLeftWithItems != shotsLeft) { + tooltip.add(CreateLang .translateDirect(_shotsRemainingWithBackup, - Components.literal(Integer.toString(shotsLeftWithItems)).withStyle(BLUE)) + Component.literal(Integer.toString(shotsLeftWithItems)).withStyle(BLUE)) .withStyle(GRAY)); + } return tooltip; } diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonVisual.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonVisual.java index c71cd5151d..3b601520c1 100644 --- a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonVisual.java +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonVisual.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.schematics.cannon; import java.util.function.Consumer; -import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPartialModels; import dev.engine_room.flywheel.api.instance.Instance; @@ -11,7 +10,6 @@ import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; -import dev.engine_room.flywheel.lib.transform.TransformStack; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; import net.minecraft.core.Direction; @@ -21,49 +19,58 @@ public class SchematicannonVisual extends AbstractBlockEntityVisual maxSize * 1000) { LocalPlayer player = Minecraft.getInstance().player; if (player != null) { - player.displayClientMessage(Lang.translateDirect("schematics.uploadTooLarge").append(" (" + size / 1000 + " KB)."), false); - player.displayClientMessage(Lang.translateDirect("schematics.maxAllowedSize").append(" " + maxSize + " KB"), false); + player.displayClientMessage(CreateLang.translateDirect("schematics.uploadTooLarge").append(" (" + size / 1000 + " KB)."), false); + player.displayClientMessage(CreateLang.translateDirect("schematics.maxAllowedSize").append(" " + maxSize + " KB"), false); } return false; } return true; } + /** + * Checks if a given file is GZIP-encoded by checking its header, + * of which the first two bytes should contain the magic number (0x1F, 0x8B) + */ + public static boolean isGZIPEncoded(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] bytes = new byte[2]; + if (fis.read(bytes) != 2) + return false; + + int byte1 = bytes[0] & 0xFF; + int byte2 = bytes[1] & 0xFF; + + return byte1 == 0x1F && byte2 == 0x8B; + } catch (IOException exception) { + return false; + } + } + private void continueUpload(String schematic) { if (activeUploads.containsKey(schematic)) { Integer maxPacketSize = AllConfigs.server().schematics.maxSchematicPacketSize.get(); @@ -133,12 +162,12 @@ public class ClientSchematicLoader { try { Files.list(Paths.get("schematics/")) - .filter(f -> !Files.isDirectory(f) && f.getFileName().toString().endsWith(".nbt")).forEach(path -> { - if (Files.isDirectory(path)) - return; + .filter(f -> !Files.isDirectory(f) && f.getFileName().toString().endsWith(".nbt")).forEach(path -> { + if (Files.isDirectory(path)) + return; - availableSchematics.add(Components.literal(path.getFileName().toString())); - }); + availableSchematics.add(Component.literal(path.getFileName().toString())); + }); } catch (NoSuchFileException e) { // No Schematics created yet } catch (IOException e) { diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java index 4189525922..7524f90477 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java @@ -9,18 +9,17 @@ import com.simibubi.create.AllKeys; import com.simibubi.create.AllPackets; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.Create; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.schematics.SchematicExport; import com.simibubi.create.content.schematics.SchematicExport.SchematicExportResult; import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.outliner.Outliner; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.gui.ScreenOpener; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -64,9 +63,12 @@ public class SchematicAndQuillHandler { if (bb.contains(projectedView)) delta *= -1; - int x = (int) (vec.getX() * delta); - int y = (int) (vec.getY() * delta); - int z = (int) (vec.getZ() * delta); + // Round away from zero to avoid an implicit floor + int intDelta = (int) (delta > 0 ? Math.ceil(delta) : Math.floor(delta)); + + int x = vec.getX() * intDelta; + int y = vec.getY() * intDelta; + int z = vec.getZ() * intDelta; AxisDirection axisDirection = selectedFace.getAxisDirection(); if (axisDirection == AxisDirection.NEGATIVE) @@ -80,7 +82,7 @@ public class SchematicAndQuillHandler { firstPos = BlockPos.containing(bb.minX, bb.minY, bb.minZ); secondPos = BlockPos.containing(bb.maxX, bb.maxY, bb.maxZ); LocalPlayer player = Minecraft.getInstance().player; - Lang.translate("schematicAndQuill.dimensions", (int) bb.getXsize() + 1, (int) bb.getYsize() + 1, + CreateLang.translate("schematicAndQuill.dimensions", (int) bb.getXsize() + 1, (int) bb.getYsize() + 1, (int) bb.getZsize() + 1) .sendStatus(player); @@ -106,20 +108,20 @@ public class SchematicAndQuillHandler { } if (selectedPos == null) { - Lang.translate("schematicAndQuill.noTarget") + CreateLang.translate("schematicAndQuill.noTarget") .sendStatus(player); return true; } if (firstPos != null) { secondPos = selectedPos; - Lang.translate("schematicAndQuill.secondPos") + CreateLang.translate("schematicAndQuill.secondPos") .sendStatus(player); return true; } firstPos = selectedPos; - Lang.translate("schematicAndQuill.firstPos") + CreateLang.translate("schematicAndQuill.firstPos") .sendStatus(player); return true; } @@ -128,7 +130,7 @@ public class SchematicAndQuillHandler { LocalPlayer player = Minecraft.getInstance().player; firstPos = null; secondPos = null; - Lang.translate("schematicAndQuill.abort") + CreateLang.translate("schematicAndQuill.abort") .sendStatus(player); } @@ -208,13 +210,13 @@ public class SchematicAndQuillHandler { ); LocalPlayer player = Minecraft.getInstance().player; if (result == null) { - Lang.translate("schematicAndQuill.failed") + CreateLang.translate("schematicAndQuill.failed") .style(ChatFormatting.RED) .sendStatus(player); return; } Path file = result.file(); - Lang.translate("schematicAndQuill.saved", file.getFileName()) + CreateLang.translate("schematicAndQuill.saved", file.getFileName()) .sendStatus(player); firstPos = null; secondPos = null; @@ -231,7 +233,7 @@ public class SchematicAndQuillHandler { } private Outliner outliner() { - return CreateClient.OUTLINER; + return Outliner.getInstance(); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java index 15360d3eb3..ffb94adec8 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java @@ -4,21 +4,21 @@ import java.util.List; import com.simibubi.create.AllItems; import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; import net.minecraft.core.BlockPos; import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Mirror; @@ -28,11 +28,11 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlac public class SchematicEditScreen extends AbstractSimiScreen { private final List rotationOptions = - Lang.translatedOptions("schematic.rotation", "none", "cw90", "cw180", "cw270"); + CreateLang.translatedOptions("schematic.rotation", "none", "cw90", "cw180", "cw270"); private final List mirrorOptions = - Lang.translatedOptions("schematic.mirror", "none", "leftRight", "frontBack"); - private final Component rotationLabel = Lang.translateDirect("schematic.rotation"); - private final Component mirrorLabel = Lang.translateDirect("schematic.mirror"); + CreateLang.translatedOptions("schematic.mirror", "none", "leftRight", "frontBack"); + private final Component rotationLabel = CreateLang.translateDirect("schematic.rotation"); + private final Component mirrorLabel = CreateLang.translateDirect("schematic.mirror"); private AllGuiTextures background; @@ -52,19 +52,19 @@ public class SchematicEditScreen extends AbstractSimiScreen { @Override protected void init() { - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); setWindowOffset(-6, 0); super.init(); int x = guiLeft; - int y = guiTop; + int y = guiTop + 2; - xInput = new EditBox(font, x + 50, y + 26, 34, 10, Components.immutableEmpty()); - yInput = new EditBox(font, x + 90, y + 26, 34, 10, Components.immutableEmpty()); - zInput = new EditBox(font, x + 130, y + 26, 34, 10, Components.immutableEmpty()); + xInput = new EditBox(font, x + 50, y + 26, 34, 10, CommonComponents.EMPTY); + yInput = new EditBox(font, x + 90, y + 26, 34, 10, CommonComponents.EMPTY); + zInput = new EditBox(font, x + 130, y + 26, 34, 10, CommonComponents.EMPTY); BlockPos anchor = handler.getTransformation() - .getAnchor(); + .getAnchor(); if (handler.isDeployed()) { xInput.setValue("" + anchor.getX()); yInput.setValue("" + anchor.getY()); @@ -76,7 +76,7 @@ public class SchematicEditScreen extends AbstractSimiScreen { zInput.setValue("" + alt.getZ()); } - for (EditBox widget : new EditBox[] { xInput, yInput, zInput }) { + for (EditBox widget : new EditBox[]{xInput, yInput, zInput}) { widget.setMaxLength(6); widget.setBordered(false); widget.setTextColor(0xFFFFFF); @@ -96,14 +96,14 @@ public class SchematicEditScreen extends AbstractSimiScreen { StructurePlaceSettings settings = handler.getTransformation() .toSettings(); - Label labelR = new Label(x + 50, y + 48, Components.immutableEmpty()).withShadow(); + Label labelR = new Label(x + 50, y + 48, CommonComponents.EMPTY).withShadow(); rotationArea = new SelectionScrollInput(x + 45, y + 43, 118, 18).forOptions(rotationOptions) .titled(rotationLabel.plainCopy()) .setState(settings.getRotation() .ordinal()) .writingTo(labelR); - Label labelM = new Label(x + 50, y + 70, Components.immutableEmpty()).withShadow(); + Label labelM = new Label(x + 50, y + 70, CommonComponents.EMPTY).withShadow(); mirrorArea = new SelectionScrollInput(x + 45, y + 65, 118, 18).forOptions(mirrorOptions) .titled(mirrorLabel.plainCopy()) .setState(settings.getMirror() @@ -114,7 +114,7 @@ public class SchematicEditScreen extends AbstractSimiScreen { addRenderableWidgets(labelR, labelM, rotationArea, mirrorArea); confirmButton = - new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 26, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> { onClose(); }); @@ -157,12 +157,12 @@ public class SchematicEditScreen extends AbstractSimiScreen { background.render(graphics, x, y); String title = handler.getCurrentSchematicName(); - graphics.drawCenteredString(font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); + graphics.drawString(font, title, x + (background.getWidth() - 8 - font.width(title)) / 2, y + 4, 0x505050, false); GuiGameElement.of(AllItems.SCHEMATIC.asStack()) - .at(x + background.width + 6, y + background.height - 40, -200) - .scale(3) - .render(graphics); + .at(x + background.getWidth() + 6, y + background.getHeight() - 40, -200) + .scale(3) + .render(graphics); } @Override diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java index f2661348dd..f15496ae27 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java @@ -13,23 +13,24 @@ import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.schematics.SchematicInstances; import com.simibubi.create.content.schematics.SchematicItem; -import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.content.schematics.client.tools.ToolType; import com.simibubi.create.content.schematics.packet.SchematicPlacePacket; import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; -import com.simibubi.create.foundation.outliner.AABBOutline; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.levelWrappers.SchematicLevel; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.outliner.AABBOutline; +import net.createmod.catnip.render.SuperRenderTypeBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Vec3i; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; @@ -48,6 +49,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.client.gui.overlay.ForgeGui; import net.minecraftforge.client.gui.overlay.IGuiOverlay; @@ -97,8 +99,6 @@ public class SchematicHandler implements IGuiOverlay { if (activeSchematicItem != null && transformation != null) transformation.tick(); - renderers.forEach(SchematicRenderer::tick); - LocalPlayer player = mc.player; ItemStack stack = findBlueprintInHand(player); if (stack == null) { @@ -151,14 +151,14 @@ public class SchematicHandler implements IGuiOverlay { private void setupRenderer() { Level clientWorld = Minecraft.getInstance().level; StructureTemplate schematic = - SchematicItem.loadSchematic(clientWorld.holderLookup(Registries.BLOCK), activeSchematicItem); + SchematicItem.loadSchematic(clientWorld, activeSchematicItem); Vec3i size = schematic.getSize(); if (size.equals(Vec3i.ZERO)) return; - SchematicWorld w = new SchematicWorld(clientWorld); - SchematicWorld wMirroredFB = new SchematicWorld(clientWorld); - SchematicWorld wMirroredLR = new SchematicWorld(clientWorld); + SchematicLevel w = new SchematicLevel(clientWorld); + SchematicLevel wMirroredFB = new SchematicLevel(clientWorld); + SchematicLevel wMirroredLR = new SchematicLevel(clientWorld); StructurePlaceSettings placementSettings = new StructurePlaceSettings(); StructureTransform transform; BlockPos pos; @@ -169,9 +169,9 @@ public class SchematicHandler implements IGuiOverlay { schematic.placeInWorld(w, pos, pos, placementSettings, w.getRandom(), Block.UPDATE_CLIENTS); for (BlockEntity blockEntity : w.getBlockEntities()) blockEntity.setLevel(w); - w.fixControllerBlockEntities(); + fixControllerBlockEntities(w); } catch (Exception e) { - Minecraft.getInstance().player.displayClientMessage(Lang.translate("schematic.error") + Minecraft.getInstance().player.displayClientMessage(CreateLang.translate("schematic.error") .component(), false); Create.LOGGER.error("Failed to load Schematic for Previewing", e); return; @@ -184,7 +184,7 @@ public class SchematicHandler implements IGuiOverlay { placementSettings.getMirror()); for (BlockEntity be : wMirroredFB.getRenderedBlockEntities()) transform.apply(be); - wMirroredFB.fixControllerBlockEntities(); + fixControllerBlockEntities(wMirroredFB); placementSettings.setMirror(Mirror.LEFT_RIGHT); pos = BlockPos.ZERO.south(size.getZ() - 1); @@ -193,7 +193,7 @@ public class SchematicHandler implements IGuiOverlay { placementSettings.getMirror()); for (BlockEntity be : wMirroredLR.getRenderedBlockEntities()) transform.apply(be); - wMirroredLR.fixControllerBlockEntities(); + fixControllerBlockEntities(wMirroredLR); renderers.get(0) .display(w); @@ -203,6 +203,26 @@ public class SchematicHandler implements IGuiOverlay { .display(wMirroredLR); } + private void fixControllerBlockEntities(SchematicLevel level) { + for (BlockEntity blockEntity : level.getBlockEntities()) { + if (!(blockEntity instanceof IMultiBlockEntityContainer multiBlockEntity)) + continue; + BlockPos lastKnown = multiBlockEntity.getLastKnownPos(); + BlockPos current = blockEntity.getBlockPos(); + if (lastKnown == null || current == null) + continue; + if (multiBlockEntity.isController()) + continue; + if (!lastKnown.equals(current)) { + BlockPos newControllerPos = multiBlockEntity.getController() + .offset(current.subtract(lastKnown)); + if (multiBlockEntity instanceof SmartBlockEntity sbe) + sbe.markVirtual(); + multiBlockEntity.setController(newControllerPos); + } + } + } + public void render(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera) { boolean present = activeSchematicItem != null; if (!active && !present) @@ -268,8 +288,7 @@ public class SchematicHandler implements IGuiOverlay { Minecraft mc = Minecraft.getInstance(); if (mc.player.isShiftKeyDown()) return false; - if (mc.hitResult instanceof BlockHitResult) { - BlockHitResult blockRayTraceResult = (BlockHitResult) mc.hitResult; + if (mc.hitResult instanceof BlockHitResult blockRayTraceResult) { BlockState clickedBlock = mc.level.getBlockState(blockRayTraceResult.getBlockPos()); if (AllBlocks.SCHEMATICANNON.has(clickedBlock)) return false; @@ -299,7 +318,7 @@ public class SchematicHandler implements IGuiOverlay { return false; if (selectionScreen.focused) { - selectionScreen.cycle((int) delta); + selectionScreen.cycle((int) Math.signum(delta)); return true; } if (AllKeys.ctrlDown()) @@ -323,11 +342,11 @@ public class SchematicHandler implements IGuiOverlay { private boolean itemLost(Player player) { for (int i = 0; i < Inventory.getSelectionSize(); i++) { if (player.getInventory() - .getItem(i) - .is(activeSchematicItem.getItem())) + .getItem(i) + .is(activeSchematicItem.getItem())) continue; if (!ItemStack.matches(player.getInventory() - .getItem(i), activeSchematicItem)) + .getItem(i), activeSchematicItem)) continue; return false; } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java index af57f07bd5..a15ae33f6b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java @@ -4,25 +4,25 @@ import org.lwjgl.glfw.GLFW; import com.simibubi.create.AllItems; import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; public class SchematicPromptScreen extends AbstractSimiScreen { private AllGuiTextures background; - private final Component convertLabel = Lang.translateDirect("schematicAndQuill.convert"); - private final Component abortLabel = Lang.translateDirect("action.discard"); - private final Component confirmLabel = Lang.translateDirect("action.saveToFile"); + private final Component convertLabel = CreateLang.translateDirect("schematicAndQuill.convert"); + private final Component abortLabel = CreateLang.translateDirect("action.discard"); + private final Component confirmLabel = CreateLang.translateDirect("action.saveToFile"); private EditBox nameField; private IconButton confirm; @@ -30,19 +30,19 @@ public class SchematicPromptScreen extends AbstractSimiScreen { private IconButton convert; public SchematicPromptScreen() { - super(Lang.translateDirect("schematicAndQuill.title")); + super(CreateLang.translateDirect("schematicAndQuill.title")); background = AllGuiTextures.SCHEMATIC_PROMPT; } @Override public void init() { - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); super.init(); int x = guiLeft; - int y = guiTop; + int y = guiTop + 2; - nameField = new EditBox(font, x + 49, y + 26, 131, 10, Components.immutableEmpty()); + nameField = new EditBox(font, x + 49, y + 26, 131, 10, CommonComponents.EMPTY); nameField.setTextColor(-1); nameField.setTextColorUneditable(-1); nameField.setBordered(false); @@ -80,16 +80,16 @@ public class SchematicPromptScreen extends AbstractSimiScreen { int y = guiTop; background.render(graphics, x, y); - graphics.drawCenteredString(font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); + graphics.drawString(font, title, x + (background.getWidth() - 8 - font.width(title)) / 2, y + 4, 0x505050, false); GuiGameElement.of(AllItems.SCHEMATIC.asStack()) - .at(x + 22, y + 23, 0) - .render(graphics); + .at(x + 22, y + 24, 0) + .render(graphics); GuiGameElement.of(AllItems.SCHEMATIC_AND_QUILL.asStack()) - .scale(3) - .at(x + background.width + 6, y + background.height - 40, -200) - .render(graphics); + .scale(3) + .at(x + background.getWidth() + 6, y + background.getHeight() - 38, -200) + .render(graphics); } @Override diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java index a119bf330f..9139a79a90 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java @@ -4,13 +4,12 @@ import java.util.LinkedHashMap; import java.util.Map; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.foundation.render.BlockEntityRenderHelper; -import com.simibubi.create.foundation.render.ShadedBlockSbbBuilder; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import dev.engine_room.flywheel.lib.model.ModelUtil; +import net.createmod.catnip.render.ShadedBlockSbbBuilder; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.render.SuperRenderTypeBuffer; +import net.createmod.catnip.levelWrappers.SchematicLevel; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.BlockRenderDispatcher; @@ -32,14 +31,14 @@ public class SchematicRenderer { private final Map bufferCache = new LinkedHashMap<>(getLayerCount()); private boolean active; private boolean changed; - protected SchematicWorld schematic; + protected SchematicLevel schematic; private BlockPos anchor; public SchematicRenderer() { changed = false; } - public void display(SchematicWorld world) { + public void display(SchematicLevel world) { this.anchor = world.anchor; this.schematic = world; this.active = true; @@ -54,20 +53,17 @@ public class SchematicRenderer { changed = true; } - public void tick() { - if (!active) - return; - Minecraft mc = Minecraft.getInstance(); - if (mc.level == null || mc.player == null || !changed) - return; - - redraw(); - changed = false; - } - public void render(PoseStack ms, SuperRenderTypeBuffer buffers) { if (!active) return; + + Minecraft mc = Minecraft.getInstance(); + if (mc.level == null || mc.player == null) + return; + if (changed) + redraw(); + changed = false; + bufferCache.forEach((layer, buffer) -> { buffer.renderInto(ms, buffers.getBuffer(layer)); }); @@ -85,14 +81,15 @@ public class SchematicRenderer { } protected SuperByteBuffer drawLayer(RenderType layer) { - BlockRenderDispatcher dispatcher = ModelUtil.VANILLA_RENDERER; + BlockRenderDispatcher dispatcher = Minecraft.getInstance() + .getBlockRenderer(); ModelBlockRenderer renderer = dispatcher.getModelRenderer(); ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get(); PoseStack poseStack = objects.poseStack; RandomSource random = objects.random; BlockPos.MutableBlockPos mutableBlockPos = objects.mutableBlockPos; - SchematicWorld renderWorld = schematic; + SchematicLevel renderWorld = schematic; BoundingBox bounds = renderWorld.getBounds(); ShadedBlockSbbBuilder sbbBuilder = objects.sbbBuilder; @@ -137,7 +134,7 @@ public class SchematicRenderer { public final PoseStack poseStack = new PoseStack(); public final RandomSource random = RandomSource.createNewThreadLocalInstance(); public final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); - public final ShadedBlockSbbBuilder sbbBuilder = new ShadedBlockSbbBuilder(); + public final ShadedBlockSbbBuilder sbbBuilder = ShadedBlockSbbBuilder.create(); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java index f4e7399108..0735a2f9c6 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java @@ -3,12 +3,12 @@ package com.simibubi.create.content.schematics.client; import static java.lang.Math.abs; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; import net.minecraft.world.level.block.Mirror; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java b/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java index 86e222bf0a..e5274628c5 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java @@ -9,8 +9,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllKeys; import com.simibubi.create.content.schematics.client.tools.ToolType; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; @@ -19,7 +18,7 @@ import net.minecraft.network.chat.Component; public class ToolSelectionScreen extends Screen { - public final String scrollToCycle = Lang.translateDirect("gui.toolmenu.cycle") + public final String scrollToCycle = CreateLang.translateDirect("gui.toolmenu.cycle") .getString(); public final String holdToFocus = "gui.toolmenu.focusKey"; @@ -34,7 +33,7 @@ public class ToolSelectionScreen extends Screen { protected int h; public ToolSelectionScreen(List tools, Consumer callback) { - super(Components.literal("Tool Selection")); + super(Component.literal("Tool Selection")); this.minecraft = Minecraft.getInstance(); this.tools = tools; this.callback = callback; @@ -76,7 +75,7 @@ public class ToolSelectionScreen extends Screen { RenderSystem.enableBlend(); RenderSystem.setShaderColor(1, 1, 1, focused ? 7 / 8f : 1 / 2f); - graphics.blit(gray.location, x - 15, y, gray.startX, gray.startY, w, h, gray.width, gray.height); + graphics.blit(gray.location, x - 15, y, gray.getStartX(), gray.getStartY(), w, h, gray.getWidth(), gray.getHeight()); float toolTipAlpha = yOffset / 10; List toolTip = tools.get(selection) @@ -85,7 +84,7 @@ public class ToolSelectionScreen extends Screen { if (toolTipAlpha > 0.25f) { RenderSystem.setShaderColor(.7f, .7f, .8f, toolTipAlpha); - graphics.blit(gray.location, x - 15, y + 33, gray.startX, gray.startY, w, h + 22, gray.width, gray.height); + graphics.blit(gray.location, x - 15, y + 33, gray.getStartX(), gray.getStartY(), w, h + 22, gray.getWidth(), gray.getHeight()); RenderSystem.setShaderColor(1, 1, 1, 1); if (toolTip.size() > 0) @@ -104,14 +103,14 @@ public class ToolSelectionScreen extends Screen { int width = minecraft.getWindow() .getGuiScaledWidth(); if (!focused) - graphics.drawCenteredString(minecraft.font, Lang.translateDirect(holdToFocus, keyName), width / 2, + graphics.drawCenteredString(minecraft.font, CreateLang.translateDirect(holdToFocus, keyName), width / 2, y - 10, 0xCCDDFF); else graphics.drawCenteredString(minecraft.font, scrollToCycle, width / 2, y - 10, 0xCCDDFF); } else { x += 65; } - + for (int i = 0; i < tools.size(); i++) { RenderSystem.enableBlend(); @@ -138,6 +137,7 @@ public class ToolSelectionScreen extends Screen { matrixStack.popPose(); } + RenderSystem.setShaderColor(1, 1, 1, 1); RenderSystem.disableBlend(); matrixStack.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java index 25797736fe..ec42b72c50 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java @@ -3,11 +3,11 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllKeys; import com.simibubi.create.content.schematics.client.SchematicTransformation; -import com.simibubi.create.foundation.outliner.AABBOutline; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.SuperRenderTypeBuffer; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.outliner.AABBOutline; import net.minecraft.core.BlockPos; import net.minecraft.nbt.NbtUtils; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java index 14f80ea94e..3efe2dd2f5 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.foundation.outliner.AABBOutline; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.render.SuperRenderTypeBuffer; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.outliner.AABBOutline; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.AxisDirection; @@ -67,7 +67,7 @@ public class FlipTool extends PlacementToolBase { .inflate(1 - directionVec.x, 1 - directionVec.y, 1 - directionVec.z); bounds = bounds.move(directionVec.scale(.5f) .multiply(boundsSize)); - + outline.setBounds(bounds); AllSpecialTextures tex = AllSpecialTextures.CHECKERED; outline.getParams() @@ -76,7 +76,7 @@ public class FlipTool extends PlacementToolBase { .colored(0xdddddd) .withFaceTextures(tex, tex); outline.render(ms, buffer, Vec3.ZERO, AnimationTickHolder.getPartialTicks()); - + super.renderOnSchematic(ms, buffer); } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java index 4afb551aae..d25aa8131d 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import net.createmod.catnip.render.SuperRenderTypeBuffer; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.gui.overlay.ForgeGui; @@ -11,12 +11,12 @@ public interface ISchematicTool { public void init(); public void updateSelection(); - + public boolean handleRightClick(); public boolean handleMouseWheel(double delta); - + public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera); public void renderOverlay(ForgeGui gui, GuiGraphics graphics, float partialTicks, int width, int height); public void renderOnSchematic(PoseStack ms, SuperRenderTypeBuffer buffer); - + } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java index 0fe9cf930c..4961935dc1 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.schematics.client.tools; import com.simibubi.create.content.schematics.client.SchematicTransformation; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.Direction.Axis; import net.minecraft.world.phys.Vec3; @@ -30,7 +30,7 @@ public class MoveTool extends PlacementToolBase { vec = VecHelper.rotate(vec, transformation.getRotationTarget(), Axis.Y); transformation.move((int) vec.x, 0, (int) vec.z); schematicHandler.markDirty(); - + return true; } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java index 06e79b29e9..ec78a86c0b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import net.createmod.catnip.render.SuperRenderTypeBuffer; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.gui.overlay.ForgeGui; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java index d9de64f7df..045e046db1 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java @@ -1,10 +1,10 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.outliner.LineOutline; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.render.SuperRenderTypeBuffer; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.outliner.LineOutline; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java index 05f2c5aa92..753d7a690f 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java @@ -9,13 +9,13 @@ import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.CreateClient; import com.simibubi.create.content.schematics.client.SchematicHandler; import com.simibubi.create.content.schematics.client.SchematicTransformation; -import com.simibubi.create.foundation.outliner.AABBOutline; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.render.SuperRenderTypeBuffer; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.AABBOutline; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.player.LocalPlayer; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/ToolType.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/ToolType.java index 703ba4df61..e8d92d9255 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/ToolType.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/ToolType.java @@ -5,8 +5,9 @@ import java.util.Collections; import java.util.List; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.Lang; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -32,7 +33,7 @@ public enum ToolType { } public MutableComponent getDisplayName() { - return Lang.translateDirect("schematic.tool." + Lang.asId(name())); + return CreateLang.translateDirect("schematic.tool." + Lang.asId(name())); } public AllIcons getIcon() { @@ -48,7 +49,7 @@ public enum ToolType { } public List getDescription() { - return Lang.translatedOptions("schematic.tool." + Lang.asId(name()) + ".description", "0", "1", "2", "3"); + return CreateLang.translatedOptions("schematic.tool." + Lang.asId(name()) + ".description", "0", "1", "2", "3"); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockEntityItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockEntityItemRequirement.java deleted file mode 100644 index 3e2c9a2a55..0000000000 --- a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockEntityItemRequirement.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.simibubi.create.content.schematics.requirement; - -import net.minecraft.world.level.block.state.BlockState; - -public interface ISpecialBlockEntityItemRequirement { - - public ItemRequirement getRequiredItems(BlockState state); - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockItemRequirement.java deleted file mode 100644 index f55d451215..0000000000 --- a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockItemRequirement.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.simibubi.create.content.schematics.requirement; - -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -public interface ISpecialBlockItemRequirement { - - public ItemRequirement getRequiredItems(BlockState state, BlockEntity blockEntity); - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialEntityItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialEntityItemRequirement.java deleted file mode 100644 index 3095009078..0000000000 --- a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialEntityItemRequirement.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.content.schematics.requirement; - -public interface ISpecialEntityItemRequirement { - - public ItemRequirement getRequiredItems(); - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java index bc6555898f..472e880fac 100644 --- a/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java +++ b/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java @@ -6,11 +6,16 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.schematic.requirement.SchematicRequirementRegistries; +import com.simibubi.create.api.schematic.requirement.SpecialBlockEntityItemRequirement; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; +import com.simibubi.create.api.schematic.requirement.SpecialEntityItemRequirement; import com.simibubi.create.compat.framedblocks.FramedBlocksInSchematics; import com.simibubi.create.foundation.data.recipe.Mods; -import com.simibubi.create.foundation.utility.NBTProcessors; -import net.minecraft.core.Registry; +import net.createmod.catnip.nbt.NBTProcessors; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.decoration.ItemFrame; @@ -30,6 +35,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.SlabType; + import net.minecraftforge.registries.ForgeRegistries; public class ItemRequirement { @@ -60,22 +66,30 @@ public class ItemRequirement { .collect(Collectors.toList())); } - public static ItemRequirement of(BlockState state, BlockEntity be) { + public static ItemRequirement of(BlockState state, @Nullable BlockEntity be) { Block block = state.getBlock(); ItemRequirement requirement; - if (block instanceof ISpecialBlockItemRequirement specialBlock) { + SchematicRequirementRegistries.BlockRequirement blockRequirement = SchematicRequirementRegistries.BLOCKS.get(block); + if (blockRequirement != null) { + requirement = blockRequirement.getRequiredItems(state, be); + } else if (block instanceof SpecialBlockItemRequirement specialBlock) { requirement = specialBlock.getRequiredItems(state, be); } else { requirement = defaultOf(state, be); } - if (be instanceof ISpecialBlockEntityItemRequirement specialBE) - requirement = requirement.union(specialBE.getRequiredItems(state)); - - if (com.simibubi.create.compat.Mods.FRAMEDBLOCKS.contains(block)) - requirement = requirement.union(FramedBlocksInSchematics.getRequiredItems(state, be)); - + if (be != null) { + SchematicRequirementRegistries.BlockEntityRequirement beRequirement = SchematicRequirementRegistries.BLOCK_ENTITIES.get(be.getType()); + if (beRequirement != null) { + requirement = requirement.union(beRequirement.getRequiredItems(be, state)); + } else if (be instanceof SpecialBlockEntityItemRequirement specialBE) { + requirement = requirement.union(specialBE.getRequiredItems(state)); + } else if (com.simibubi.create.compat.Mods.FRAMEDBLOCKS.contains(block)) { + requirement = requirement.union(FramedBlocksInSchematics.getRequiredItems(state, be)); + } + } + return requirement; } @@ -119,8 +133,12 @@ public class ItemRequirement { } public static ItemRequirement of(Entity entity) { - if (entity instanceof ISpecialEntityItemRequirement specialEntity) + SchematicRequirementRegistries.EntityRequirement requirement = SchematicRequirementRegistries.ENTITIES.get(entity.getType()); + if (requirement != null) { + return requirement.getRequiredItems(entity); + } else if (entity instanceof SpecialEntityItemRequirement specialEntity) { return specialEntity.getRequiredItems(); + } if (entity instanceof ItemFrame itemFrame) { ItemStack frame = new ItemStack(Items.ITEM_FRAME); diff --git a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlockEntity.java b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlockEntity.java index 92eb5f38f0..d4267d725d 100644 --- a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlockEntity.java @@ -4,8 +4,8 @@ import java.util.List; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.IInteractionChecker; -import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -56,7 +56,7 @@ public class SchematicTableBlockEntity extends SmartBlockEntity implements MenuP protected void read(CompoundTag compound, boolean clientPacket) { inventory.deserializeNBT(compound.getCompound("Inventory")); super.read(compound, clientPacket); - + if (!clientPacket) return; if (compound.contains("Uploading")) { @@ -74,14 +74,14 @@ public class SchematicTableBlockEntity extends SmartBlockEntity implements MenuP protected void write(CompoundTag compound, boolean clientPacket) { compound.put("Inventory", inventory.serializeNBT()); super.write(compound, clientPacket); - + if (clientPacket && isUploading) { compound.putBoolean("Uploading", true); compound.putString("Schematic", uploadingSchematic); compound.putFloat("Progress", uploadingProgress); } } - + @Override public void tick() { // Update Client block entity @@ -113,7 +113,7 @@ public class SchematicTableBlockEntity extends SmartBlockEntity implements MenuP @Override public Component getDisplayName() { - return Lang.translateDirect("gui.schematicTable.title"); + return CreateLang.translateDirect("gui.schematicTable.title"); } @Override diff --git a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableMenu.java b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableMenu.java index ea6841b835..3f4c6f5b3a 100644 --- a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableMenu.java +++ b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableMenu.java @@ -68,7 +68,7 @@ public class SchematicTableMenu extends MenuBase { @Override protected void addSlots() { - inputSlot = new SlotItemHandler(contentHolder.inventory, 0, 21, 57) { + inputSlot = new SlotItemHandler(contentHolder.inventory, 0, 21, 59) { @Override public boolean mayPlace(ItemStack stack) { return AllItems.EMPTY_SCHEMATIC.isIn(stack) || AllItems.SCHEMATIC_AND_QUILL.isIn(stack) @@ -76,7 +76,7 @@ public class SchematicTableMenu extends MenuBase { } }; - outputSlot = new SlotItemHandler(contentHolder.inventory, 1, 166, 57) { + outputSlot = new SlotItemHandler(contentHolder.inventory, 1, 166, 59) { @Override public boolean mayPlace(ItemStack stack) { return false; @@ -89,12 +89,12 @@ public class SchematicTableMenu extends MenuBase { // player Slots for (int row = 0; row < 3; ++row) { for (int col = 0; col < 9; ++col) { - this.addSlot(new Slot(player.getInventory(), col + row * 9 + 9, 38 + col * 18, 105 + row * 18)); + this.addSlot(new Slot(player.getInventory(), col + row * 9 + 9, 38 + col * 18, 107 + row * 18)); } } for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) { - this.addSlot(new Slot(player.getInventory(), hotbarSlot, 38 + hotbarSlot * 18, 163)); + this.addSlot(new Slot(player.getInventory(), hotbarSlot, 38 + hotbarSlot * 18, 165)); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableScreen.java b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableScreen.java index 9dfbc7df09..3bbf83a61d 100644 --- a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableScreen.java @@ -13,18 +13,18 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.schematics.client.ClientSchematicLoader; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.Util; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; @@ -32,12 +32,12 @@ import net.minecraft.world.item.ItemStack; public class SchematicTableScreen extends AbstractSimiContainerScreen { - private final Component uploading = Lang.translateDirect("gui.schematicTable.uploading"); - private final Component finished = Lang.translateDirect("gui.schematicTable.finished"); - private final Component refresh = Lang.translateDirect("gui.schematicTable.refresh"); - private final Component folder = Lang.translateDirect("gui.schematicTable.open_folder"); - private final Component noSchematics = Lang.translateDirect("gui.schematicTable.noSchematics"); - private final Component availableSchematicsTitle = Lang.translateDirect("gui.schematicTable.availableSchematics"); + private final Component uploading = CreateLang.translateDirect("gui.schematicTable.uploading"); + private final Component finished = CreateLang.translateDirect("gui.schematicTable.finished"); + private final Component refresh = CreateLang.translateDirect("gui.schematicTable.refresh"); + private final Component folder = CreateLang.translateDirect("gui.schematicTable.open_folder"); + private final Component noSchematics = CreateLang.translateDirect("gui.schematicTable.noSchematics"); + private final Component availableSchematicsTitle = CreateLang.translateDirect("gui.schematicTable.availableSchematics"); protected AllGuiTextures background; @@ -56,14 +56,14 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen extraAreas = Collections.emptyList(); public SchematicTableScreen(SchematicTableMenu menu, Inventory playerInventory, - Component title) { + Component title) { super(menu, playerInventory, title); background = AllGuiTextures.SCHEMATIC_TABLE; } @Override protected void init() { - setWindowSize(background.width, background.height + 4 + AllGuiTextures.PLAYER_INVENTORY.height); + setWindowSize(background.getWidth(), background.getHeight() + 4 + AllGuiTextures.PLAYER_INVENTORY.getHeight()); setWindowOffset(-11, 8); super.init(); @@ -71,10 +71,10 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen availableSchematics = CreateClient.SCHEMATIC_SENDER.getAvailableSchematics(); int x = leftPos; - int y = topPos; + int y = topPos + 2; - schematicsLabel = new Label(x + 49, y + 26, Components.immutableEmpty()).withShadow(); - schematicsLabel.text = Components.immutableEmpty(); + schematicsLabel = new Label(x + 51, y + 26, CommonComponents.EMPTY).withShadow(); + schematicsLabel.text = CommonComponents.EMPTY; if (!availableSchematics.isEmpty()) { schematicsArea = new SelectionScrollInput(x + 45, y + 21, 139, 18).forOptions(availableSchematics) @@ -95,14 +95,14 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen { Util.getPlatform() .openFile(Paths.get("schematics/") .toFile()); }); folderButton.setToolTip(folder); - refreshButton = new IconButton(x + 207, y + 21, AllIcons.I_REFRESH); + refreshButton = new IconButton(x + 206, y + 21, AllIcons.I_REFRESH); refreshButton.withCallback(() -> { ClientSchematicLoader schematicSender = CreateClient.SCHEMATIC_SENDER; schematicSender.refresh(); @@ -118,7 +118,7 @@ public class SchematicTableScreen extends AbstractSimiContainerScreenat(x + background.width, y + background.height - 40, -200) + .at(x + background.getWidth(), y + background.getHeight() - 40, -200) .scale(3) .render(graphics); - int width = (int) (SCHEMATIC_TABLE_PROGRESS.width + int width = (int) (SCHEMATIC_TABLE_PROGRESS.getWidth() * Mth.lerp(partialTicks, lastChasingProgress, chasingProgress)); - int height = SCHEMATIC_TABLE_PROGRESS.height; - graphics.blit(SCHEMATIC_TABLE_PROGRESS.location, x + 70, y + 57, SCHEMATIC_TABLE_PROGRESS.startX, - SCHEMATIC_TABLE_PROGRESS.startY, width, height); + int height = SCHEMATIC_TABLE_PROGRESS.getHeight(); + graphics.blit(SCHEMATIC_TABLE_PROGRESS.location, x + 70, y + 59, SCHEMATIC_TABLE_PROGRESS.getStartX(), + SCHEMATIC_TABLE_PROGRESS.getStartY(), width, height); } @Override @@ -189,7 +190,11 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen 0) { diff --git a/src/main/java/com/simibubi/create/content/trains/CubeParticleData.java b/src/main/java/com/simibubi/create/content/trains/CubeParticleData.java index e17553e1a2..18794ed624 100644 --- a/src/main/java/com/simibubi/create/content/trains/CubeParticleData.java +++ b/src/main/java/com/simibubi/create/content/trains/CubeParticleData.java @@ -13,22 +13,23 @@ import net.minecraft.client.particle.ParticleProvider; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; import net.minecraft.network.FriendlyByteBuf; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class CubeParticleData implements ParticleOptions, ICustomParticleData { - public static final Codec CODEC = RecordCodecBuilder.create(i -> + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - Codec.FLOAT.fieldOf("r").forGetter(p -> p.r), - Codec.FLOAT.fieldOf("g").forGetter(p -> p.g), - Codec.FLOAT.fieldOf("b").forGetter(p -> p.b), - Codec.FLOAT.fieldOf("scale").forGetter(p -> p.scale), - Codec.INT.fieldOf("avgAge").forGetter(p -> p.avgAge), - Codec.BOOL.fieldOf("hot").forGetter(p -> p.hot)) - .apply(i, CubeParticleData::new)); + Codec.FLOAT.fieldOf("r").forGetter(p -> p.r), + Codec.FLOAT.fieldOf("g").forGetter(p -> p.g), + Codec.FLOAT.fieldOf("b").forGetter(p -> p.b), + Codec.FLOAT.fieldOf("scale").forGetter(p -> p.scale), + Codec.INT.fieldOf("avgAge").forGetter(p -> p.avgAge), + Codec.BOOL.fieldOf("hot").forGetter(p -> p.hot)) + .apply(i, CubeParticleData::new)); - public static final ParticleOptions.Deserializer DESERIALIZER = new ParticleOptions.Deserializer() { + public static final ParticleOptions.Deserializer DESERIALIZER = new ParticleOptions.Deserializer<>() { @Override public CubeParticleData fromCommand(ParticleType type, StringReader reader) throws CommandSyntaxException { reader.expect(' '); diff --git a/src/main/java/com/simibubi/create/content/trains/RailwaySavedData.java b/src/main/java/com/simibubi/create/content/trains/RailwaySavedData.java index 3a3ee63a66..78feb99bae 100644 --- a/src/main/java/com/simibubi/create/content/trains/RailwaySavedData.java +++ b/src/main/java/com/simibubi/create/content/trains/RailwaySavedData.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.trains; +import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -11,13 +12,17 @@ import com.simibubi.create.content.trains.graph.EdgePointType; import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.content.trains.signal.SignalBoundary; import com.simibubi.create.content.trains.signal.SignalEdgeGroup; -import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.SavedDataUtil; + +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.saveddata.SavedData; +import org.jetbrains.annotations.NotNull; + public class RailwaySavedData extends SavedData { private Map trackNetworks = new HashMap<>(); @@ -79,6 +84,11 @@ public class RailwaySavedData extends SavedData { return sd; } + @Override + public void save(@NotNull File file) { + SavedDataUtil.saveWithDatOld(this, file); + } + public Map getTrackNetworks() { return trackNetworks; } diff --git a/src/main/java/com/simibubi/create/content/trains/TrainHUD.java b/src/main/java/com/simibubi/create/content/trains/TrainHUD.java index ce4feb1090..f3f37b2308 100644 --- a/src/main/java/com/simibubi/create/content/trains/TrainHUD.java +++ b/src/main/java/com/simibubi/create/content/trains/TrainHUD.java @@ -8,13 +8,13 @@ import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.ControlsUtil; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.placement.PlacementClient; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; @@ -135,11 +135,11 @@ public class TrainHUD { AllGuiTextures.TRAIN_HUD_FRAME.render(graphics, -2, 1); AllGuiTextures.TRAIN_HUD_SPEED_BG.render(graphics, 0, 0); - int w = (int) (AllGuiTextures.TRAIN_HUD_SPEED.width * displayedSpeed.getValue(partialTicks)); - int h = AllGuiTextures.TRAIN_HUD_SPEED.height; + int w = (int) (AllGuiTextures.TRAIN_HUD_SPEED.getWidth() * displayedSpeed.getValue(partialTicks)); + int h = AllGuiTextures.TRAIN_HUD_SPEED.getHeight(); - graphics.blit(AllGuiTextures.TRAIN_HUD_SPEED.location, 0, 0, 0, AllGuiTextures.TRAIN_HUD_SPEED.startX, - AllGuiTextures.TRAIN_HUD_SPEED.startY, w, h, 256, 256); + graphics.blit(AllGuiTextures.TRAIN_HUD_SPEED.location, 0, 0, 0, AllGuiTextures.TRAIN_HUD_SPEED.getStartX(), + AllGuiTextures.TRAIN_HUD_SPEED.getStartY(), w, h, 256, 256); int promptSize = (int) displayedPromptSize.getValue(partialTicks); if (promptSize > 1) { @@ -149,8 +149,8 @@ public class TrainHUD { AllGuiTextures.TRAIN_PROMPT_L.render(graphics, -3, 0); AllGuiTextures.TRAIN_PROMPT_R.render(graphics, promptSize, 0); - graphics.blit(AllGuiTextures.TRAIN_PROMPT.location, 0, 0, 0, AllGuiTextures.TRAIN_PROMPT.startX + (128 - promptSize / 2f), - AllGuiTextures.TRAIN_PROMPT.startY, promptSize, AllGuiTextures.TRAIN_PROMPT.height, 256, 256); + graphics.blit(AllGuiTextures.TRAIN_PROMPT.location, 0, 0, 0, AllGuiTextures.TRAIN_PROMPT.getStartX() + (128 - promptSize / 2f), + AllGuiTextures.TRAIN_PROMPT.getStartY(), promptSize, AllGuiTextures.TRAIN_PROMPT.getHeight(), 256, 256); poseStack.popPose(); @@ -168,12 +168,12 @@ public class TrainHUD { AllGuiTextures.TRAIN_HUD_DIRECTION.render(graphics, 77, -20); - w = (int) (AllGuiTextures.TRAIN_HUD_THROTTLE.width * (1 - displayedThrottle.getValue(partialTicks))); - int invW = AllGuiTextures.TRAIN_HUD_THROTTLE.width - w; - graphics.blit(AllGuiTextures.TRAIN_HUD_THROTTLE.location, invW, 0, 0, AllGuiTextures.TRAIN_HUD_THROTTLE.startX + invW, - AllGuiTextures.TRAIN_HUD_THROTTLE.startY, w, h, 256, 256); + w = (int) (AllGuiTextures.TRAIN_HUD_THROTTLE.getWidth() * (1 - displayedThrottle.getValue(partialTicks))); + int invW = AllGuiTextures.TRAIN_HUD_THROTTLE.getWidth() - w; + graphics.blit(AllGuiTextures.TRAIN_HUD_THROTTLE.location, invW, 0, 0, AllGuiTextures.TRAIN_HUD_THROTTLE.getStartX() + invW, + AllGuiTextures.TRAIN_HUD_THROTTLE.getStartY(), w, h, 256, 256); AllGuiTextures.TRAIN_HUD_THROTTLE_POINTER.render(graphics, - Math.max(1, AllGuiTextures.TRAIN_HUD_THROTTLE.width - w) - 3, -2); + Math.max(1, AllGuiTextures.TRAIN_HUD_THROTTLE.getWidth() - w) - 3, -2); // Direction @@ -204,7 +204,7 @@ public class TrainHUD { poseStack.translate(91, -9, 0); poseStack.scale(0.925f, 0.925f, 1); - PlacementHelpers.textured(poseStack, 0, 0, 1, snappedAngle); + PlacementClient.textured(poseStack, 0, 0, 1, snappedAngle); poseStack.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlock.java b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlock.java index 81a34571dd..25cdfafd5e 100644 --- a/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlock.java @@ -16,8 +16,8 @@ import com.google.common.collect.ImmutableSet; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBogeyStyles; import com.simibubi.create.AllItems; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.equipment.wrench.IWrenchable; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.CarriageBogey; @@ -26,10 +26,10 @@ import com.simibubi.create.content.trains.graph.TrackEdge; import com.simibubi.create.content.trains.track.TrackMaterial; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -52,9 +52,10 @@ import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.registries.ForgeRegistries; -public abstract class AbstractBogeyBlock extends Block implements IBE, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable { +public abstract class AbstractBogeyBlock extends Block implements IBE, ProperWaterloggedBlock, SpecialBlockItemRequirement, IWrenchable { public static final EnumProperty AXIS = BlockStateProperties.HORIZONTAL_AXIS; static final List BOGEYS = new ArrayList<>(); public BogeySizes.BogeySize size; @@ -202,7 +203,7 @@ public abstract class AbstractBogeyBlock ext return InteractionResult.FAIL; bogeyBlockEntity.setBogeyData(oldData); } - player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style") + player.displayClientMessage(CreateLang.translateDirect("bogey.style.updated_style") .append(": ").append(style.displayName), true); } else { CompoundTag oldData = sbbe.getBogeyData(); @@ -210,7 +211,7 @@ public abstract class AbstractBogeyBlock ext if (!(level.getBlockEntity(pos) instanceof AbstractBogeyBlockEntity bogeyBlockEntity)) return InteractionResult.FAIL; bogeyBlockEntity.setBogeyData(oldData); - player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style_and_size") + player.displayClientMessage(CreateLang.translateDirect("bogey.style.updated_style_and_size") .append(": ").append(style.displayName), true); } @@ -237,7 +238,7 @@ public abstract class AbstractBogeyBlock ext public BlockState getRotatedBlockState(BlockState state, Direction targetedFace) { Block block = state.getBlock(); List bogeyCycle = getBogeyBlockCycle(); - int indexOf = bogeyCycle.indexOf(RegisteredObjects.getKeyOrThrow(block)); + int indexOf = bogeyCycle.indexOf(CatnipServices.REGISTRIES.getKeyOrThrow(block)); if (indexOf == -1) return state; int index = (indexOf + 1) % bogeyCycle.size(); diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlockEntity.java index 146a04e2e2..b24fde4a2c 100644 --- a/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlockEntity.java @@ -6,9 +6,9 @@ import org.jetbrains.annotations.NotNull; import com.simibubi.create.AllBogeyStyles; import com.simibubi.create.foundation.blockEntity.CachedRenderBBBlockEntity; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.animation.LerpedFloat; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/BogeyBlockEntityVisual.java b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyBlockEntityVisual.java index e3bd7191be..8da8259387 100644 --- a/src/main/java/com/simibubi/create/content/trains/bogey/BogeyBlockEntityVisual.java +++ b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyBlockEntityVisual.java @@ -45,6 +45,8 @@ public class BogeyBlockEntityVisual extends AbstractBlockEntityVisual soundEvent, ParticleOptions contactParticle, ParticleOptions smokeParticle, CompoundTag defaultData, Map>> sizes, - Map> sizeRenderers) { + Map>> sizeRenderers) { this.id = id; this.cycleGroup = cycleGroup; @@ -55,7 +55,8 @@ public class BogeyStyle { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { this.sizeRenderers = new HashMap<>(); - sizeRenderers.forEach((k, v) -> this.sizeRenderers.put(k, v.get())); + sizeRenderers.forEach((k, v) -> this.sizeRenderers.put(k, v.get() + .get())); }); } @@ -112,13 +113,14 @@ public class BogeyStyle { protected final ResourceLocation cycleGroup; protected final Map>> sizes = new HashMap<>(); - protected Component displayName = Lang.translateDirect("bogey.style.invalid"); + protected Component displayName = CreateLang.translateDirect("bogey.style.invalid"); protected Supplier soundEvent = AllSoundEvents.TRAIN2::getMainEvent; protected ParticleOptions contactParticle = ParticleTypes.CRIT; protected ParticleOptions smokeParticle = ParticleTypes.POOF; protected CompoundTag defaultData = new CompoundTag(); - protected final Map> sizeRenderers = new HashMap<>(); + protected final Map>> sizeRenderers = + new HashMap<>(); public Builder(ResourceLocation id, ResourceLocation cycleGroup) { this.id = id; @@ -151,7 +153,7 @@ public class BogeyStyle { } public Builder size(BogeySizes.BogeySize size, Supplier> block, - Supplier renderer) { + Supplier> renderer) { this.sizes.put(size, block); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { this.sizeRenderers.put(size, renderer); diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlock.java b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlock.java index b4bceecfae..e8dad70394 100644 --- a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlock.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.trains.bogey; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBogeyStyles; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.api.schematic.requirement.SpecialBlockItemRequirement; import com.simibubi.create.content.trains.track.TrackMaterial; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; @@ -18,7 +18,7 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; public class StandardBogeyBlock extends AbstractBogeyBlock - implements IBE, ProperWaterloggedBlock, ISpecialBlockItemRequirement { + implements IBE, ProperWaterloggedBlock, SpecialBlockItemRequirement { public StandardBogeyBlock(Properties props, BogeySizes.BogeySize size) { super(props, size); diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyRenderer.java b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyRenderer.java index ec1cabbacd..0103b190b0 100644 --- a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyRenderer.java @@ -4,16 +4,18 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; import net.minecraft.world.level.block.Blocks; public class StandardBogeyRenderer implements BogeyRenderer { @@ -21,7 +23,7 @@ public class StandardBogeyRenderer implements BogeyRenderer { public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) { VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped()); - SuperByteBuffer shaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState() + SuperByteBuffer shaft = CachedBuffers.block(AllBlocks.SHAFT.getDefaultState() .setValue(ShaftBlock.AXIS, Direction.Axis.Z)); for (int i : Iterate.zeroAndOne) { shaft.translate(-.5f, .25f, i * -1) @@ -41,13 +43,13 @@ public class StandardBogeyRenderer implements BogeyRenderer { VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped()); - CachedBufferer.partial(AllPartialModels.BOGEY_FRAME, Blocks.AIR.defaultBlockState()) + CachedBuffers.partial(AllPartialModels.BOGEY_FRAME, Blocks.AIR.defaultBlockState()) .scale(1 - 1 / 512f) .light(light) .overlay(overlay) .renderInto(poseStack, buffer); - SuperByteBuffer wheels = CachedBufferer.partial(AllPartialModels.SMALL_BOGEY_WHEELS, Blocks.AIR.defaultBlockState()); + SuperByteBuffer wheels = CachedBuffers.partial(AllPartialModels.SMALL_BOGEY_WHEELS, Blocks.AIR.defaultBlockState()); for (int side : Iterate.positiveAndNegative) { wheels.translate(0, 12 / 16f, side) .rotateXDegrees(wheelAngle) @@ -59,13 +61,16 @@ public class StandardBogeyRenderer implements BogeyRenderer { } public static class Large extends StandardBogeyRenderer { + public static final float BELT_RADIUS_PX = 5f; + public static final float BELT_RADIUS_IN_UV_SPACE = BELT_RADIUS_PX / 16f; + @Override public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) { super.render(bogeyData, wheelAngle, partialTick, poseStack, bufferSource, light, overlay, inContraption); VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped()); - SuperByteBuffer secondaryShaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState() + SuperByteBuffer secondaryShaft = CachedBuffers.block(AllBlocks.SHAFT.getDefaultState() .setValue(ShaftBlock.AXIS, Direction.Axis.X)); for (int i : Iterate.zeroAndOne) { secondaryShaft.translate(-.5f, .25f, .5f + i * -2) @@ -77,26 +82,42 @@ public class StandardBogeyRenderer implements BogeyRenderer { .renderInto(poseStack, buffer); } - CachedBufferer.partial(AllPartialModels.BOGEY_DRIVE, Blocks.AIR.defaultBlockState()) + CachedBuffers.partial(AllPartialModels.BOGEY_DRIVE, Blocks.AIR.defaultBlockState()) .scale(1 - 1 / 512f) .light(light) .overlay(overlay) .renderInto(poseStack, buffer); - CachedBufferer.partial(AllPartialModels.BOGEY_PISTON, Blocks.AIR.defaultBlockState()) + float spriteSize = AllSpriteShifts.BOGEY_BELT.getTarget() + .getV1() + - AllSpriteShifts.BOGEY_BELT.getTarget() + .getV0(); + + float scroll = BELT_RADIUS_IN_UV_SPACE * Mth.DEG_TO_RAD * wheelAngle; + scroll = scroll - Mth.floor(scroll); + scroll = scroll * spriteSize * 0.5f; + + CachedBuffers.partial(AllPartialModels.BOGEY_DRIVE_BELT, Blocks.AIR.defaultBlockState()) + .scale(1 - 1 / 512f) + .light(light) + .overlay(overlay) + .shiftUVScrolling(AllSpriteShifts.BOGEY_BELT, scroll) + .renderInto(poseStack, buffer); + + CachedBuffers.partial(AllPartialModels.BOGEY_PISTON, Blocks.AIR.defaultBlockState()) .translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle))) .light(light) .overlay(overlay) .renderInto(poseStack, buffer); - CachedBufferer.partial(AllPartialModels.LARGE_BOGEY_WHEELS, Blocks.AIR.defaultBlockState()) + CachedBuffers.partial(AllPartialModels.LARGE_BOGEY_WHEELS, Blocks.AIR.defaultBlockState()) .translate(0, 1, 0) .rotateXDegrees(wheelAngle) .light(light) .overlay(overlay) .renderInto(poseStack, buffer); - CachedBufferer.partial(AllPartialModels.BOGEY_PIN, Blocks.AIR.defaultBlockState()) + CachedBuffers.partial(AllPartialModels.BOGEY_PIN, Blocks.AIR.defaultBlockState()) .translate(0, 1, 0) .rotateXDegrees(wheelAngle) .translate(0, 1 / 4f, 0) diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyVisual.java b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyVisual.java index 0bb70cd1d1..fac4075f3e 100644 --- a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyVisual.java +++ b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyVisual.java @@ -5,19 +5,20 @@ import java.util.function.Consumer; import org.jetbrains.annotations.Nullable; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; -import com.simibubi.create.foundation.render.VirtualRenderHelper; -import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.content.processing.burner.ScrollTransformedInstance; +import com.simibubi.create.foundation.render.AllInstanceTypes; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.Models; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; public class StandardBogeyVisual implements BogeyVisual { private final TransformedInstance shaft1; @@ -25,8 +26,8 @@ public class StandardBogeyVisual implements BogeyVisual { public StandardBogeyVisual(VisualizationContext ctx, float partialTick, boolean inContraption) { var shaftInstancer = ctx.instancerProvider() - .instancer(InstanceTypes.TRANSFORMED, VirtualRenderHelper.blockModel(AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, Direction.Axis.Z))); + .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.SHAFT)); + shaft1 = shaftInstancer.createInstance(); shaft2 = shaftInstancer.createInstance(); } @@ -36,13 +37,15 @@ public class StandardBogeyVisual implements BogeyVisual { shaft1.setTransform(poseStack) .translate(-.5f, .25f, 0) .center() - .rotateZDegrees(wheelAngle) + .rotateTo(Direction.UP, Direction.SOUTH) + .rotateYDegrees(wheelAngle) .uncenter() .setChanged(); shaft2.setTransform(poseStack) .translate(-.5f, .25f, -1) .center() - .rotateZDegrees(wheelAngle) + .rotateTo(Direction.UP, Direction.SOUTH) + .rotateYDegrees(wheelAngle) .uncenter() .setChanged(); } @@ -140,6 +143,7 @@ public class StandardBogeyVisual implements BogeyVisual { private final TransformedInstance secondaryShaft1; private final TransformedInstance secondaryShaft2; private final TransformedInstance drive; + private final ScrollTransformedInstance belt; private final TransformedInstance piston; private final TransformedInstance wheels; private final TransformedInstance pin; @@ -147,13 +151,15 @@ public class StandardBogeyVisual implements BogeyVisual { public Large(VisualizationContext ctx, float partialTick, boolean inContraption) { super(ctx, partialTick, inContraption); var secondaryShaftInstancer = ctx.instancerProvider() - .instancer(InstanceTypes.TRANSFORMED, VirtualRenderHelper.blockModel(AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, Direction.Axis.X))); + .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.SHAFT)); secondaryShaft1 = secondaryShaftInstancer.createInstance(); secondaryShaft2 = secondaryShaftInstancer.createInstance(); drive = ctx.instancerProvider() .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.BOGEY_DRIVE)) .createInstance(); + belt = ctx.instancerProvider() + .instancer(AllInstanceTypes.SCROLLING_TRANSFORMED, Models.partial(AllPartialModels.BOGEY_DRIVE_BELT)) + .createInstance(); piston = ctx.instancerProvider() .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.BOGEY_PISTON)) .createInstance(); @@ -163,6 +169,8 @@ public class StandardBogeyVisual implements BogeyVisual { pin = ctx.instancerProvider() .instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.BOGEY_PIN)) .createInstance(); + + belt.setSpriteShift(AllSpriteShifts.BOGEY_BELT); } @Override @@ -171,18 +179,24 @@ public class StandardBogeyVisual implements BogeyVisual { secondaryShaft1.setTransform(poseStack) .translate(-.5f, .25f, .5f) .center() - .rotateXDegrees(wheelAngle) + .rotateTo(Direction.UP, Direction.EAST) + .rotateYDegrees(wheelAngle) .uncenter() .setChanged(); secondaryShaft2.setTransform(poseStack) .translate(-.5f, .25f, -1.5f) .center() - .rotateXDegrees(wheelAngle) + .rotateTo(Direction.UP, Direction.EAST) + .rotateYDegrees(wheelAngle) .uncenter() .setChanged(); drive.setTransform(poseStack) .scale(1 - 1/512f) .setChanged(); + belt.offset(0, StandardBogeyRenderer.Large.BELT_RADIUS_IN_UV_SPACE * Mth.DEG_TO_RAD * wheelAngle) + .setTransform(poseStack) + .scale(1 - 1/512f) + .setChanged(); piston.setTransform(poseStack) .translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle))) .setChanged(); @@ -205,6 +219,7 @@ public class StandardBogeyVisual implements BogeyVisual { secondaryShaft2.setZeroTransform().setChanged(); wheels.setZeroTransform().setChanged(); drive.setZeroTransform().setChanged(); + belt.setZeroTransform().setChanged(); piston.setZeroTransform().setChanged(); pin.setZeroTransform().setChanged(); } @@ -216,6 +231,7 @@ public class StandardBogeyVisual implements BogeyVisual { secondaryShaft2.light(packedLight).setChanged(); wheels.light(packedLight).setChanged(); drive.light(packedLight).setChanged(); + belt.light(packedLight).setChanged(); piston.light(packedLight).setChanged(); pin.light(packedLight).setChanged(); } @@ -227,6 +243,7 @@ public class StandardBogeyVisual implements BogeyVisual { consumer.accept(secondaryShaft2); consumer.accept(wheels); consumer.accept(drive); + consumer.accept(belt); consumer.accept(piston); consumer.accept(pin); } @@ -238,6 +255,7 @@ public class StandardBogeyVisual implements BogeyVisual { secondaryShaft2.delete(); wheels.delete(); drive.delete(); + belt.delete(); piston.delete(); pin.delete(); } diff --git a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlock.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlock.java index 4cb8d49d44..6d062884c7 100644 --- a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlock.java @@ -14,12 +14,11 @@ import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.placement.IPlacementHelper; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.placement.PlacementOffset; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; @@ -118,7 +117,7 @@ public class FlapDisplayBlock extends HorizontalKineticBlock @Override public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult ray) { + BlockHitResult ray) { if (player.isShiftKeyDown()) return InteractionResult.PASS; @@ -140,8 +139,8 @@ public class FlapDisplayBlock extends HorizontalKineticBlock double yCoord = ray.getLocation() .add(Vec3.atLowerCornerOf(ray.getDirection() - .getOpposite() - .getNormal()) + .getOpposite() + .getNormal()) .scale(.125f)).y; int lineIndex = flapBE.getLineIndexAt(yCoord); @@ -179,10 +178,11 @@ public class FlapDisplayBlock extends HorizontalKineticBlock if (AllBlocks.CLIPBOARD.isIn(heldItem)) { List entries = ClipboardEntry.getLastViewedEntries(heldItem); int line = lineIndex; - for (int i = 0; i < entries.size(); i++) { - for (String string : entries.get(i).text.getString() - .split("\n")) - flapBE.applyTextManually(line++, Component.Serializer.toJson(Components.literal(string))); + for (ClipboardEntry entry : entries) { + for (String string : entry.text.getString() + .split("\n")) { + flapBE.applyTextManually(line++, Component.Serializer.toJson(Component.literal(string))); + } } return InteractionResult.SUCCESS; } @@ -229,7 +229,8 @@ public class FlapDisplayBlock extends HorizontalKineticBlock for (Direction connection : Iterate.directionsInAxis(Axis.Y)) { boolean connect = true; - Move: for (Direction movement : Iterate.directionsInAxis(axis)) { + Move: + for (Direction movement : Iterate.directionsInAxis(axis)) { currentPos.set(pos); for (int i = 0; i < 1000; i++) { if (!level.isLoaded(currentPos)) @@ -279,12 +280,12 @@ public class FlapDisplayBlock extends HorizontalKineticBlock @Override public BlockState updateShape(BlockState state, Direction pDirection, BlockState pNeighborState, - LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { return updatedShapeInner(state, pDirection, pNeighborState, pLevel, pCurrentPos); } private BlockState updatedShapeInner(BlockState state, Direction pDirection, BlockState pNeighborState, - LevelAccessor pLevel, BlockPos pCurrentPos) { + LevelAccessor pLevel, BlockPos pCurrentPos) { if (state.getValue(BlockStateProperties.WATERLOGGED)) pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); if (!canConnect(state, pNeighborState)) @@ -352,7 +353,7 @@ public class FlapDisplayBlock extends HorizontalKineticBlock @Override public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, - BlockHitResult ray) { + BlockHitResult ray) { List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), state.getValue(FlapDisplayBlock.HORIZONTAL_FACING) .getAxis(), @@ -361,8 +362,8 @@ public class FlapDisplayBlock extends HorizontalKineticBlock return directions.isEmpty() ? PlacementOffset.fail() : PlacementOffset.success(pos.relative(directions.get(0)), s -> AllBlocks.DISPLAY_BOARD.get() - .updateColumn(world, pos.relative(directions.get(0)), - s.setValue(HORIZONTAL_FACING, state.getValue(FlapDisplayBlock.HORIZONTAL_FACING)), true)); + .updateColumn(world, pos.relative(directions.get(0)), + s.setValue(HORIZONTAL_FACING, state.getValue(FlapDisplayBlock.HORIZONTAL_FACING)), true)); } } diff --git a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlockEntity.java index 235cff63cf..4bb169b3a8 100644 --- a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlockEntity.java @@ -8,16 +8,16 @@ import com.google.gson.JsonElement; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.DyeHelper; import com.simibubi.create.foundation.utility.DynamicComponent; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -150,7 +150,7 @@ public class FlapDisplayBlockEntity extends KineticBlockEntity { FlapDisplaySection flapDisplaySection = sections.get(0); if (rawComponentText == null) { manualLines[lineIndex] = false; - flapDisplaySection.setText(Components.immutableEmpty()); + flapDisplaySection.setText(CommonComponents.EMPTY); notifyUpdate(); return; } @@ -318,13 +318,14 @@ public class FlapDisplayBlockEntity extends KineticBlockEntity { } @Override - public void addBehaviours(List behaviours) {} + public void addBehaviours(List behaviours) { + } public int getLineColor(int line) { DyeColor color = colour[line]; return color == null ? 0xFF_D3C6BA : DyeHelper.getDyeColors(color) - .getFirst() | 0xFF_000000; + .getFirst() | 0xFF_000000; } public boolean isLineGlowing(int line) { diff --git a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayLayout.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayLayout.java index 24188f4693..63d73b3238 100644 --- a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayLayout.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayLayout.java @@ -5,8 +5,7 @@ import java.util.List; import org.apache.commons.lang3.mutable.MutableInt; -import com.simibubi.create.foundation.utility.NBTHelper; - +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; diff --git a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayRenderer.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayRenderer.java index d79d46fdf7..65c289c582 100644 --- a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayRenderer.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.trains.display; import java.util.List; +import net.createmod.catnip.animation.AnimationTickHolder; import org.joml.Matrix4f; import com.mojang.blaze3d.font.GlyphInfo; @@ -10,12 +11,11 @@ import com.mojang.blaze3d.vertex.PoseStack.Pose; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.render.SuperByteBuffer; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.font.FontSet; @@ -229,7 +229,7 @@ public class FlapDisplayRenderer extends KineticBlockEntityRenderer Lang.translateDirect("flap_display.cycles." + key) + return LOADED_FLAP_CYCLES.computeIfAbsent(key, k -> CreateLang.translateDirect("flap_display.cycles." + key) .getString() .split(";")); } diff --git a/src/main/java/com/simibubi/create/content/trains/display/GlobalTrainDisplayData.java b/src/main/java/com/simibubi/create/content/trains/display/GlobalTrainDisplayData.java index dd8c622c07..baa05e1375 100644 --- a/src/main/java/com/simibubi/create/content/trains/display/GlobalTrainDisplayData.java +++ b/src/main/java/com/simibubi/create/content/trains/display/GlobalTrainDisplayData.java @@ -9,6 +9,8 @@ import java.util.Map; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; +import net.createmod.catnip.data.Glob; + import net.minecraft.network.chat.MutableComponent; public class GlobalTrainDisplayData { @@ -30,7 +32,7 @@ public class GlobalTrainDisplayData { } public static List prepare(String filter, int maxLines) { - String regex = filter.isBlank() ? filter : "\\Q" + filter.replace("*", "\\E.*\\Q") + "\\E"; + String regex = Glob.toRegexPattern(filter, ""); return statusByDestination.entrySet() .stream() .filter(e -> e.getKey() diff --git a/src/main/java/com/simibubi/create/content/trains/entity/ArrivalSoundQueue.java b/src/main/java/com/simibubi/create/content/trains/entity/ArrivalSoundQueue.java index 6c89d7581e..9659edf2d4 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/ArrivalSoundQueue.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/ArrivalSoundQueue.java @@ -12,9 +12,9 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock; import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.data.Pair; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; diff --git a/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java b/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java index cd11a6a3d1..3f0c36b22e 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -26,12 +27,12 @@ import com.simibubi.create.content.trains.graph.DimensionPalette; import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -45,6 +46,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -99,6 +101,14 @@ public class Carriage { return entities.size() > 1; } + public List> getPresentDimensions() { + return entities.keySet().stream().distinct().toList(); + } + + public Optional getPositionInDimension(ResourceKey dimension) { + return Optional.ofNullable(entities.get(dimension)).map(carriage -> BlockPos.containing(carriage.positionAnchor)); + } + public void setContraption(Level level, CarriageContraption contraption) { this.storage = null; CarriageContraptionEntity entity = CarriageContraptionEntity.create(level, contraption); @@ -638,7 +648,7 @@ public class Carriage { public void read(CompoundTag tag) { cutoff = tag.getFloat("Cutoff"); discardTicks = tag.getInt("DiscardTicks"); - storage.read(tag, null, false); + storage.read(tag, false, null); if (tag.contains("Pivot")) pivot = TrackNodeLocation.read(tag.getCompound("Pivot"), null); if (positionAnchor != null) diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageBogey.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageBogey.java index 937f238e52..9d3447e737 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageBogey.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageBogey.java @@ -13,14 +13,14 @@ import com.simibubi.create.content.trains.bogey.BogeySizes.BogeySize; import com.simibubi.create.content.trains.bogey.BogeyStyle; import com.simibubi.create.content.trains.graph.DimensionPalette; import com.simibubi.create.content.trains.graph.TrackGraph; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.core.Direction.Axis; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -178,7 +178,7 @@ public class CarriageBogey { public CompoundTag write(DimensionPalette dimensions) { CompoundTag tag = new CompoundTag(); - tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type) + tag.putString("Type", CatnipServices.REGISTRIES.getKeyOrThrow((Block) type) .toString()); tag.put("Points", points.serializeEach(tp -> tp.write(dimensions))); tag.putBoolean("UpsideDown", upsideDown); diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java index ab566a6f80..32b525c417 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java @@ -7,25 +7,25 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import com.simibubi.create.api.contraption.train.TrainConductorHandler; - import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.AllContraptionTypes; +import com.simibubi.create.api.behaviour.interaction.ConductorBlockInteractionBehavior; +import com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour; +import com.simibubi.create.api.contraption.ContraptionType; import com.simibubi.create.content.contraptions.AssemblyException; import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.contraptions.ContraptionType; import com.simibubi.create.content.contraptions.MountedStorageManager; import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; import com.simibubi.create.content.contraptions.minecart.TrainCargoManager; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -39,11 +39,6 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.AABB; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.templates.FluidTank; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class CarriageContraption extends Contraption { @@ -67,8 +62,12 @@ public class CarriageContraption extends Contraption { public int portalCutoffMin; public int portalCutoffMax; - static final IItemHandlerModifiable fallbackItems = new ItemStackHandler(); - static final IFluidHandler fallbackFluids = new FluidTank(0); + static final MountedStorageManager fallbackStorage; + + static { + fallbackStorage = new MountedStorageManager(); + fallbackStorage.initialize(); + } public CarriageContraption() { conductorSeats = new HashMap<>(); @@ -99,9 +98,9 @@ public class CarriageContraption extends Contraption { if (bogeys == 0) return false; if (bogeys > 2) - throw new AssemblyException(Lang.translateDirect("train_assembly.too_many_bogeys", bogeys)); + throw new AssemblyException(CreateLang.translateDirect("train_assembly.too_many_bogeys", bogeys)); if (sidewaysControls) - throw new AssemblyException(Lang.translateDirect("train_assembly.sideways_controls")); + throw new AssemblyException(CreateLang.translateDirect("train_assembly.sideways_controls")); for (BlockPos blazePos : assembledBlockConductors) for (Direction direction : Iterate.directionsInAxis(assemblyDirection.getAxis())) @@ -123,7 +122,8 @@ public class CarriageContraption extends Contraption { StructureBlockInfo info = blocks.get(controlsPos); if (!AllBlocks.TRAIN_CONTROLS.has(info.state())) return false; - return info.state().getValue(ControlsBlock.FACING) == direction.getOpposite(); + return info.state() + .getValue(ControlsBlock.FACING) == direction.getOpposite(); } public void swapStorageAfterAssembly(CarriageContraptionEntity cce) { @@ -166,8 +166,10 @@ public class CarriageContraption extends Contraption { captureBE ? world.getBlockEntity(pos) : null); } - if (TrainConductorHandler.CONDUCTOR_HANDLERS.stream().anyMatch(handler -> handler.isValidConductor(blockState))) + MovingInteractionBehaviour behaviour = MovingInteractionBehaviour.REGISTRY.get(blockState); + if (behaviour instanceof ConductorBlockInteractionBehavior conductor && conductor.isValidConductor(blockState)) { assembledBlockConductors.add(toLocalPos(pos)); + } if (AllBlocks.TRAIN_CONTROLS.has(blockState)) { Direction facing = blockState.getValue(ControlsBlock.FACING); @@ -227,17 +229,12 @@ public class CarriageContraption extends Contraption { return false; } - @Override - protected MountedStorageManager getStorageForSpawnPacket() { - return storageProxy; - } - @Override public ContraptionType getType() { - return ContraptionType.CARRIAGE; + return AllContraptionTypes.CARRIAGE.get(); } - public Direction getAssemblyDirection() { + public Direction getAssemblyDirection() { return assemblyDirection; } @@ -320,25 +317,16 @@ public class CarriageContraption extends Contraption { } @Override - public IItemHandlerModifiable getSharedInventory() { - return storageProxy == null ? fallbackItems : storageProxy.getItems(); + public MountedStorageManager getStorage() { + return storageProxy == null ? fallbackStorage : storageProxy; } @Override - public IFluidHandler getSharedFluidTanks() { - return storageProxy == null ? fallbackFluids : storageProxy.getFluids(); - } - - public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) { - storage.updateContainedFluid(localPos, containedFluid); - } - - @Override - public void tickStorage(AbstractContraptionEntity entity) { - if (entity.level().isClientSide) - storage.entityTick(entity); - else if (storageProxy != null) - storageProxy.entityTick(entity); + public void writeStorage(CompoundTag nbt, boolean spawnPacket) { + if (!spawnPacket) + return; + if (storageProxy != null) + storageProxy.write(nbt, spawnPacket); } } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java index 0c5d75e258..e224a8a8eb 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java @@ -14,10 +14,10 @@ import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllPackets; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.contraptions.ContraptionBlockChangedPacket; import com.simibubi.create.content.contraptions.OrientedContraptionEntity; import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.trains.CubeParticleData; import com.simibubi.create.content.trains.TrainHUDUpdatePacket; @@ -25,18 +25,18 @@ import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEnt import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection; import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.content.trains.station.GlobalStation; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.syncher.EntityDataAccessor; @@ -50,6 +50,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.network.PacketDistributor; @@ -90,7 +91,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { firstPositionUpdate = true; arrivalSoundTicks = Integer.MIN_VALUE; derailParticleOffset = VecHelper.offsetRandomly(Vec3.ZERO, world.random, 1.5f) - .multiply(1, .25f, 1); + .multiply(1, .25f, 1); } @Override @@ -157,7 +158,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { } public boolean isLocalCoordWithin(BlockPos localPos, int min, int max) { - if (!(getContraption()instanceof CarriageContraption cc)) + if (!(getContraption() instanceof CarriageContraption cc)) return false; Direction facing = cc.getAssemblyDirection(); Axis axis = facing.getClockWise() @@ -389,7 +390,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { } @Override - protected void handleStallInformation(double x, double y, double z, float angle) {} + protected void handleStallInformation(double x, double y, double z, float angle) { + } Vec3 derailParticleOffset; @@ -532,7 +534,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { @Override public Component getDisplayName() { if (carriage == null) - return Lang.translateDirect("train"); + return CreateLang.translateDirect("train"); return carriage.train.name; } @@ -591,8 +593,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { boolean spaceDown = heldControls.contains(4); GlobalStation currentStation = carriage.train.getCurrentStation(); if (currentStation != null && spaceDown) { - sendPrompt(player, Lang.translateDirect("train.arrived_at", - Components.literal(currentStation.name).withStyle(s -> s.withColor(0x704630))), false); + sendPrompt(player, CreateLang.translateDirect("train.arrived_at", + Component.literal(currentStation.name).withStyle(s -> s.withColor(0x704630))), false); return true; } @@ -603,8 +605,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { if (currentStation != null && targetSpeed != 0) { stationMessage = false; - sendPrompt(player, Lang.translateDirect("train.departing_from", - Components.literal(currentStation.name).withStyle(s -> s.withColor(0x704630))), false); + sendPrompt(player, CreateLang.translateDirect("train.departing_from", + Component.literal(currentStation.name).withStyle(s -> s.withColor(0x704630))), false); } if (currentStation == null) { @@ -617,8 +619,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { double f = (nav.distanceToDestination / navDistanceTotal); int progress = (int) (Mth.clamp(1 - ((1 - f) * (1 - f)), 0, 1) * 30); boolean arrived = progress == 0; - MutableComponent whiteComponent = Components.literal(Strings.repeat("|", progress)); - MutableComponent greenComponent = Components.literal(Strings.repeat("|", 30 - progress)); + MutableComponent whiteComponent = Component.literal(Strings.repeat("|", progress)); + MutableComponent greenComponent = Component.literal(Strings.repeat("|", 30 - progress)); int fromColor = 0x00_FFC244; int toColor = 0x00_529915; @@ -683,15 +685,15 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { boolean stationMessage = false; private void displayApproachStationMessage(Player player, GlobalStation station) { - sendPrompt(player, Lang.translateDirect("contraption.controls.approach_station", - Components.keybind("key.jump"), station.name), false); + sendPrompt(player, CreateLang.translateDirect("contraption.controls.approach_station", + Component.keybind("key.jump"), station.name), false); stationMessage = true; } private void cleanUpApproachStationMessage(Player player) { if (!stationMessage) return; - player.displayClientMessage(Components.immutableEmpty(), true); + player.displayClientMessage(CommonComponents.EMPTY, true); stationMessage = false; } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionVisual.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionVisual.java index 28ef06cb2e..bc48d9b084 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionVisual.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionVisual.java @@ -6,19 +6,18 @@ import org.joml.Vector3f; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.contraptions.render.ContraptionVisual; import com.simibubi.create.content.trains.bogey.BogeyVisual; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.transform.TransformStack; +import dev.engine_room.flywheel.lib.util.RecyclingPoseStack; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; import net.minecraft.nbt.CompoundTag; public class CarriageContraptionVisual extends ContraptionVisual { - private final PoseStack poseStack = new PoseStack(); + private final PoseStack poseStack = new RecyclingPoseStack(); - @Nullable - private Carriage carriage; @Nullable private Couple<@Nullable VisualizedBogey> bogeys; private Couple bogeyHidden = Couple.create(() -> false); @@ -26,17 +25,8 @@ public class CarriageContraptionVisual extends ContraptionVisual VisualizedBogey.of(visualizationContext, bogey, pt)); - } - - super.init(pt); + animate(partialTick); } public void setBogeyVisibility(boolean first, boolean visible) { @@ -46,19 +36,37 @@ public class CarriageContraptionVisual extends ContraptionVisual VisualizedBogey.of(visualizationContext, bogey, pt)); + updateLight(pt); + return true; + } + + return false; + } + + private void animate(float partialTick) { + if (!checkCarriage(partialTick)) { return; } - float partialTick = ctx.partialTick(); - float viewYRot = entity.getViewYRot(partialTick); float viewXRot = entity.getViewXRot(partialTick); - int bogeySpacing = carriage.bogeySpacing; + int bogeySpacing = entity.getCarriage().bogeySpacing; poseStack.pushPose(); diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageCouplingRenderer.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageCouplingRenderer.java index e3273d8d4a..2299495cbd 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageCouplingRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageCouplingRenderer.java @@ -7,10 +7,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllPartialModels; import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; @@ -71,7 +71,7 @@ public class CarriageCouplingRenderer { { ms.pushPose(); ms.translate(anchor.x - camera.x, anchor.y - camera.y, anchor.z - camera.z); - CachedBufferer.partial(AllPartialModels.TRAIN_COUPLING_HEAD, air) + CachedBuffers.partial(AllPartialModels.TRAIN_COUPLING_HEAD, air) .rotateYDegrees(-yRot) .rotateXDegrees(xRot) .light(lightCoords) @@ -83,7 +83,7 @@ public class CarriageCouplingRenderer { int couplingSegments = (int) Math.round(couplingDistance * 4); double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments; for (int j = 0; j < couplingSegments; j++) { - CachedBufferer.partial(AllPartialModels.TRAIN_COUPLING_CABLE, air) + CachedBuffers.partial(AllPartialModels.TRAIN_COUPLING_CABLE, air) .rotateYDegrees(-yRot + 180) .rotateXDegrees(-xRot) .translate(0, 0, margin + 2 / 16f) @@ -101,7 +101,7 @@ public class CarriageCouplingRenderer { .add(anchor2) .subtract(camera); ms.translate(translation.x, translation.y, translation.z); - CachedBufferer.partial(AllPartialModels.TRAIN_COUPLING_HEAD, air) + CachedBuffers.partial(AllPartialModels.TRAIN_COUPLING_HEAD, air) .rotateYDegrees(-yRot + 180) .rotateXDegrees(-xRot) .light(lightCoords2) diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageParticles.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageParticles.java index 3b3f864af5..ae91071c10 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageParticles.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageParticles.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.trains.entity; import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.client.Minecraft; import net.minecraft.core.Direction.Axis; import net.minecraft.util.RandomSource; diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageSounds.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSounds.java index de30b39d72..ee2a60d950 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageSounds.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSounds.java @@ -3,10 +3,10 @@ package com.simibubi.create.content.trains.entity; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents.SoundEntry; import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; import net.minecraft.client.resources.sounds.SoundInstance; diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncData.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncData.java index 86ac13d11c..af6beea214 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncData.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncData.java @@ -18,12 +18,12 @@ import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector; import com.simibubi.create.content.trains.graph.TrackEdge; import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.content.trains.graph.TrackNode; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.ServerSpeedProvider; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; @@ -127,7 +127,7 @@ public class CarriageSyncData { for (boolean first : Iterate.trueAndFalse) { if (!first && !carriage.isOnTwoBogeys()) break; - + CarriageBogey bogey = carriage.bogeys.get(first); for (boolean firstPoint : Iterate.trueAndFalse) { TravellingPoint point = bogey.points.get(firstPoint); @@ -228,14 +228,14 @@ public class CarriageSyncData { public void approach(CarriageContraptionEntity entity, Carriage carriage, float partialIn) { DimensionalCarriageEntity dce = carriage.getDimensional(entity.level()); - + int updateInterval = entity.getType() .updateInterval(); if (ticksSince >= updateInterval * 2) partialIn /= ticksSince - updateInterval * 2 + 1; partialIn *= ServerSpeedProvider.get(); final float partial = partialIn; - + ticksSince++; if (fallbackLocations != null && fallbackPointSnapshot != null) { @@ -304,11 +304,11 @@ public class CarriageSyncData { TrackNode initialNode1 = forward ? current.node1 : current.node2; TrackNode initialNode2 = forward ? current.node2 : current.node1; - + Map connectionsFromInitial = graph.getConnectionsFrom(initialNode1); if (connectionsFromInitial == null) return -1; - + TrackEdge initialEdge = connectionsFromInitial.get(initialNode2); if (initialEdge == null) return -1; // graph changed diff --git a/src/main/java/com/simibubi/create/content/trains/entity/Navigation.java b/src/main/java/com/simibubi/create/content/trains/entity/Navigation.java index ea9185978b..f83ed05513 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/Navigation.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Navigation.java @@ -35,11 +35,11 @@ import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.content.trains.track.BezierConnection; import com.simibubi.create.content.trains.track.TrackMaterial; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.util.Mth; @@ -265,7 +265,7 @@ public class Navigation { if (targetDistance < 10) { double maxApproachSpeed = topSpeed * ((targetDistance) / 10); double speedRelativeToStation = train.speed * speedMod; - + if (speedRelativeToStation > maxApproachSpeed) { train.speed += (maxApproachSpeed - Math.abs(train.speed)) * .5f * speedMod; return; @@ -749,7 +749,7 @@ public class Navigation { if (station.canApproachFrom(newNode) && stationTest.test(newDistance, newDistance + newPenalty, reachedVia, Pair.of(Couple.create(node2, newNode), newEdge), station)) { hasDestination = true; - continue; + break; } if (!isOwnStation) newPenalty += Train.Penalties.STATION; diff --git a/src/main/java/com/simibubi/create/content/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/trains/entity/Train.java index 0b09271442..0b0fc3c9b9 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Train.java @@ -20,10 +20,9 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableObject; -import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.api.behaviour.movement.MovementBehaviour; import com.simibubi.create.content.logistics.filter.FilterItemStack; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity; import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; @@ -46,14 +45,14 @@ import com.simibubi.create.content.trains.signal.SignalEdgeGroup; import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.content.trains.station.StationBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -70,6 +69,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.Level.ExplosionInteraction; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -131,6 +131,7 @@ public class Train { public float accumulatedSteamRelease; int tickOffset; + int ticksSinceLastMailTransfer; double[] stress; // advancements @@ -146,7 +147,7 @@ public class Train { this.carriageSpacing = carriageSpacing; this.icon = TrainIconType.getDefault(); this.stress = new double[carriageSpacing.size()]; - this.name = Lang.translateDirect("train.unnamed"); + this.name = CreateLang.translateDirect("train.unnamed"); this.status = new TrainStatus(this); this.doubleEnded = doubleEnded; @@ -217,7 +218,7 @@ public class Train { if (shouldActivate) break; - IItemHandlerModifiable inv = carriage.storage.getItems(); + IItemHandlerModifiable inv = carriage.storage.getAllItems(); if (inv != null) { for (int slot = 0; slot < inv.getSlots(); slot++) { if (shouldActivate) @@ -269,6 +270,15 @@ public class Train { return; } + GlobalStation currentStation = getCurrentStation(); + if (currentStation != null) { + ticksSinceLastMailTransfer++; + if (ticksSinceLastMailTransfer > 20) { + currentStation.runMailTransfer(); + ticksSinceLastMailTransfer = 0; + } + } + updateConductors(); runtime.tick(level); navigation.tick(level); @@ -421,7 +431,7 @@ public class Train { } else if (speed != 0) status.trackOK(); - updateNavigationTarget(distance); + updateNavigationTarget(level, distance); } public IEdgePointListener frontSignalListener() { @@ -477,7 +487,7 @@ public class Train { c.forEachPresentEntity(cce -> cce.getContraption() .getActors() .forEach(pair -> { - MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.getKey().state()); + MovementBehaviour behaviour = MovementBehaviour.REGISTRY.get(pair.getKey().state()); if (behaviour != null) behaviour.cancelStall(pair.getValue()); })); @@ -508,7 +518,7 @@ public class Train { }; } - private void updateNavigationTarget(double distance) { + private void updateNavigationTarget(Level level, double distance) { if (navigation.destination == null) return; @@ -542,7 +552,7 @@ public class Train { return; if (!navigatingManually && fullRefresh) { - DiscoveredPath preferredPath = runtime.startCurrentInstruction(); + DiscoveredPath preferredPath = runtime.startCurrentInstruction(level); if (preferredPath != null){ navigation.startNavigation(preferredPath); } @@ -762,8 +772,10 @@ public class Train { if (currentStation != null) { currentStation.cancelReservation(this); BlockPos blockEntityPos = currentStation.getBlockEntityPos(); - if (level.getBlockEntity(blockEntityPos) instanceof StationBlockEntity sbe) + if (level.getBlockEntity(blockEntityPos) instanceof StationBlockEntity sbe) { sbe.lastDisassembledTrainName = name.copy(); + sbe.lastDisassembledMapColorIndex = mapColorIndex; + } } Create.RAILWAYS.removeTrain(id); @@ -917,6 +929,8 @@ public class Train { setCurrentStation(station); reservedSignalBlocks.clear(); runtime.destinationReached(); + station.runMailTransfer(); + ticksSinceLastMailTransfer = 0; } public void setCurrentStation(GlobalStation station) { @@ -1253,4 +1267,19 @@ public class Train { return distance; } + public List> getPresentDimensions() { + return carriages.stream() + .flatMap((Carriage carriage) -> carriage.getPresentDimensions().stream()) + .distinct() + .toList(); + } + + public Optional getPositionInDimension(ResourceKey dimension) { + return carriages.stream() + .map(carriage -> carriage.getPositionInDimension(dimension)) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + } + } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java index 2153b1cc42..e2f442fdb7 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java @@ -8,9 +8,9 @@ import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.content.trains.graph.TrackGraphLocation; import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.content.trains.graph.TrackNodeLocation; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.math.VecHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.util.Mth; @@ -118,4 +118,4 @@ public class TrainMigration { return trainMigration; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TrainPacket.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainPacket.java index 1598c53790..ddbbf9adfd 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/TrainPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainPacket.java @@ -8,10 +8,10 @@ import java.util.UUID; import com.simibubi.create.CreateClient; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -93,7 +93,7 @@ public class TrainPacket extends SimplePacketBase { continue; } CarriageBogey bogey = carriage.bogeys.get(first); - buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow((Block) bogey.type)); + buffer.writeResourceLocation(CatnipServices.REGISTRIES.getKeyOrThrow((Block) bogey.type)); buffer.writeBoolean(bogey.upsideDown); buffer.writeNbt(bogey.bogeyData); } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocationPacket.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocationPacket.java index 8f92ec2cb5..40d7cca6e9 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocationPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocationPacket.java @@ -7,10 +7,10 @@ import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.ContraptionRelocationPacket; import com.simibubi.create.content.trains.track.BezierTrackPointLocation; import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.math.VecHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; @@ -96,7 +96,7 @@ public class TrainRelocationPacket extends SimplePacketBase { } if (TrainRelocator.relocate(train, sender.level(), pos, hoveredBezier, direction, lookAngle, false)) { - sender.displayClientMessage(Lang.translateDirect("train.relocate.success") + sender.displayClientMessage(CreateLang.translateDirect("train.relocate.success") .withStyle(ChatFormatting.GREEN), true); train.carriages.forEach(c -> c.forEachPresentEntity(e -> { e.nonDamageTicks = 10; diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocator.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocator.java index 2cf8fdb794..d3b6d2fce3 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocator.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocator.java @@ -15,7 +15,6 @@ import org.apache.commons.lang3.mutable.MutableInt; import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.ContraptionHandlerClient; import com.simibubi.create.content.trains.entity.TravellingPoint.IEdgePointListener; @@ -32,10 +31,11 @@ import com.simibubi.create.content.trains.track.ITrackBlock; import com.simibubi.create.content.trains.track.TrackBlockOutline; import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -50,6 +50,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.InputEvent; @@ -85,7 +86,7 @@ public class TrainRelocator { if (!player.position() .closerThan(relocatingOrigin, 24) || player.isShiftKeyDown()) { relocatingTrain = null; - player.displayClientMessage(Lang.translateDirect("train.relocate.abort") + player.displayClientMessage(CreateLang.translateDirect("train.relocate.abort") .withStyle(ChatFormatting.RED), true); return; } @@ -122,7 +123,7 @@ public class TrainRelocator { for (int i = 0; i < toVisualise.size() - 1; i++) { Vec3 vec1 = toVisualise.get(i).add(offset); Vec3 vec2 = toVisualise.get(i + 1).add(offset); - CreateClient.OUTLINER.showLine(Pair.of(relocating, i), vec1.add(0, -.925f, 0), vec2.add(0, -.925f, 0)) + Outliner.getInstance().showLine(Pair.of(relocating, i), vec1.add(0, -.925f, 0), vec2.add(0, -.925f, 0)) .colored(lastHoveredResult || i != toVisualise.size() - 2 ? 0x95CD41 : 0xEA5C2B) .disableLineNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); @@ -270,7 +271,7 @@ public class TrainRelocator { @OnlyIn(Dist.CLIENT) public static void visualise(Train train, int i, Vec3 v1, Vec3 v2, boolean valid) { - CreateClient.OUTLINER.showLine(Pair.of(train, i), v1.add(0, -.825f, 0), v2.add(0, -.825f, 0)) + Outliner.getInstance().showLine(Pair.of(train, i), v1.add(0, -.825f, 0), v2.add(0, -.825f, 0)) .colored(valid ? 0x95CD41 : 0xEA5C2B) .disableLineNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); @@ -299,14 +300,14 @@ public class TrainRelocator { if (entity instanceof AbstractContraptionEntity ce && Math.abs(ce.getPosition(0) .subtract(ce.getPosition(1)) .lengthSqr()) > 1 / 1024d) { - player.displayClientMessage(Lang.translateDirect("train.cannot_relocate_moving") + player.displayClientMessage(CreateLang.translateDirect("train.cannot_relocate_moving") .withStyle(ChatFormatting.RED), true); relocatingTrain = null; return; } if (!AllItems.WRENCH.isIn(player.getMainHandItem())) { - player.displayClientMessage(Lang.translateDirect("train.relocate.abort") + player.displayClientMessage(CreateLang.translateDirect("train.relocate.abort") .withStyle(ChatFormatting.RED), true); relocatingTrain = null; return; @@ -314,19 +315,19 @@ public class TrainRelocator { if (!player.position() .closerThan(relocatingOrigin, 24)) { - player.displayClientMessage(Lang.translateDirect("train.relocate.too_far") + player.displayClientMessage(CreateLang.translateDirect("train.relocate.too_far") .withStyle(ChatFormatting.RED), true); return; } Boolean success = relocateClient(relocating, true); if (success == null) - player.displayClientMessage(Lang.translateDirect("train.relocate", relocating.name), true); + player.displayClientMessage(CreateLang.translateDirect("train.relocate", relocating.name), true); else if (success.booleanValue()) - player.displayClientMessage(Lang.translateDirect("train.relocate.valid") + player.displayClientMessage(CreateLang.translateDirect("train.relocate.valid") .withStyle(ChatFormatting.GREEN), true); else - player.displayClientMessage(Lang.translateDirect("train.relocate.invalid") + player.displayClientMessage(CreateLang.translateDirect("train.relocate.invalid") .withStyle(ChatFormatting.RED), true); return; } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TrainStatus.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainStatus.java index 8a68292a98..e0ff8995a6 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/TrainStatus.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainStatus.java @@ -1,13 +1,17 @@ package com.simibubi.create.content.trains.entity; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Stream; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.google.common.collect.Streams; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; @@ -20,7 +24,7 @@ public class TrainStatus { public boolean track; public boolean conductor; - List queued = new ArrayList<>(); + List queued = new ArrayList<>(); public TrainStatus(Train train) { this.train = train; @@ -40,6 +44,13 @@ public class TrainStatus { navigation = true; } + public void failedPackageNoTarget(String address) { + if (navigation) + return; + displayInformation("no_package_target", false, address); + navigation = true; + } + public void successfulNavigation() { if (!navigation) return; @@ -101,7 +112,26 @@ public class TrainStatus { } public void crash() { - displayInformation("collision", false); + Component component = + Component.literal(" - ").withStyle(ChatFormatting.GRAY) + .append( + CreateLang.translateDirect("train.status.collision").withStyle(st -> st.withColor(0xFFD3B4)) + ); + List> presentDimensions = train.getPresentDimensions(); + Stream locationComponents = presentDimensions.stream().map(key -> + { + return Component.literal(" - ").withStyle(ChatFormatting.GRAY) + .append( + CreateLang.translateDirect( + "train.status.collision.where", + key.location(), + train.getPositionInDimension(key).get().toShortString() + ).withStyle(style -> style.withColor(0xFFD3B4)) + ); + } + ); + addMessage(new StatusMessage(Streams.concat(Stream.of(component), locationComponents).toArray(Component[]::new))); + } public void successfulMigration() { @@ -122,17 +152,23 @@ public class TrainStatus { if (owner == null) return; if (owner instanceof Player player) { - player.displayClientMessage(Lang.translateDirect("train.status", train.name) + player.displayClientMessage(CreateLang.translateDirect("train.status", train.name) .withStyle(ChatFormatting.GOLD), false); - queued.forEach(c -> player.displayClientMessage(c, false)); + queued.forEach(message -> message.displayToPlayer(player)); } queued.clear(); } public void displayInformation(String key, boolean itsAGoodThing, Object... args) { - queued.add(Components.literal(" - ").withStyle(ChatFormatting.GRAY) - .append(Lang.translateDirect("train.status." + key, args) - .withStyle(st -> st.withColor(itsAGoodThing ? 0xD5ECC2 : 0xFFD3B4)))); + MutableComponent component = Component.literal(" - ").withStyle(ChatFormatting.GRAY) + .append(CreateLang.translateDirect("train.status." + key, args) + .withStyle(st -> st.withColor(itsAGoodThing ? 0xD5ECC2 : 0xFFD3B4))); + addMessage(new StatusMessage(component)); + } + + public void addMessage(StatusMessage message) { + queued.add(message); + if (queued.size() > 3) queued.remove(0); } @@ -142,4 +178,11 @@ public class TrainStatus { conductor = false; } + public record StatusMessage(Component... messages) { + public void displayToPlayer(Player player) { + Arrays.stream(messages).forEach(messages -> player.displayClientMessage(messages, false)); + } + + }; + } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TravellingPoint.java b/src/main/java/com/simibubi/create/content/trains/entity/TravellingPoint.java index ca786c05f5..73cca1b6d4 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/TravellingPoint.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TravellingPoint.java @@ -24,9 +24,9 @@ import com.simibubi.create.content.trains.graph.TrackGraphLocation; import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.content.trains.signal.TrackEdgePoint; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/DimensionPalette.java b/src/main/java/com/simibubi/create/content/trains/graph/DimensionPalette.java index 2f8ae4b187..8d4b4b6b0f 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/DimensionPalette.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/DimensionPalette.java @@ -3,8 +3,7 @@ package com.simibubi.create.content.trains.graph; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.foundation.utility.NBTHelper; - +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/DiscoveredPath.java b/src/main/java/com/simibubi/create/content/trains/graph/DiscoveredPath.java index 2e9be4fe3a..77dafc7735 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/DiscoveredPath.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/DiscoveredPath.java @@ -3,7 +3,8 @@ package com.simibubi.create.content.trains.graph; import java.util.List; import com.simibubi.create.content.trains.station.GlobalStation; -import com.simibubi.create.foundation.utility.Couple; + +import net.createmod.catnip.data.Couple; public class DiscoveredPath { public List> path; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/EdgeData.java b/src/main/java/com/simibubi/create/content/trains/graph/EdgeData.java index 221d0ece52..e8223d281c 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/EdgeData.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/EdgeData.java @@ -13,9 +13,9 @@ import com.simibubi.create.Create; import com.simibubi.create.content.trains.signal.SignalBoundary; import com.simibubi.create.content.trains.signal.SignalEdgeGroup; import com.simibubi.create.content.trains.signal.TrackEdgePoint; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/EdgePointManager.java b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointManager.java index fafe1109fa..ce559457a4 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/EdgePointManager.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointManager.java @@ -2,8 +2,9 @@ package com.simibubi.create.content.trains.graph; import com.simibubi.create.Create; import com.simibubi.create.content.trains.signal.TrackEdgePoint; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; + +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; public class EdgePointManager { diff --git a/src/main/java/com/simibubi/create/content/trains/graph/EdgePointStorage.java b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointStorage.java index b4ff98c617..9b26f4a25f 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/EdgePointStorage.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointStorage.java @@ -8,8 +8,8 @@ import java.util.UUID; import com.simibubi.create.Create; import com.simibubi.create.content.trains.signal.TrackEdgePoint; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackEdge.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdge.java index 997b21f3ec..1208163396 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackEdge.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdge.java @@ -9,8 +9,8 @@ import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.simibubi.create.content.trains.track.BezierConnection; import com.simibubi.create.content.trains.track.TrackMaterial; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackEdgeIntersection.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdgeIntersection.java index 954df2a81d..ec9059dd01 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackEdgeIntersection.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdgeIntersection.java @@ -2,8 +2,7 @@ package com.simibubi.create.content.trains.graph; import java.util.UUID; -import com.simibubi.create.foundation.utility.Couple; - +import net.createmod.catnip.data.Couple; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraph.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraph.java index f72159062c..2ac8ec3cb7 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraph.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraph.java @@ -5,7 +5,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -25,12 +24,12 @@ import com.simibubi.create.content.trains.signal.SignalEdgeGroup; import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.content.trains.track.BezierConnection; import com.simibubi.create.content.trains.track.TrackMaterial; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.theme.Color; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; @@ -168,9 +167,7 @@ public class TrackGraph { return false; Map trains = Create.RAILWAYS.trains; - for (Iterator iterator = trains.keySet() - .iterator(); iterator.hasNext();) { - UUID uuid = iterator.next(); + for (UUID uuid : trains.keySet()) { Train train = trains.get(uuid); if (train.graph != this) continue; @@ -266,9 +263,7 @@ public class TrackGraph { toOther.invalidateBounds(); Map trains = Create.RAILWAYS.trains; - for (Iterator iterator = trains.keySet() - .iterator(); iterator.hasNext();) { - UUID uuid = iterator.next(); + for (UUID uuid : trains.keySet()) { Train train = trains.get(uuid); if (train.graph != this) continue; @@ -277,7 +272,7 @@ public class TrackGraph { } public Set findDisconnectedGraphs(@Nullable LevelAccessor level, - @Nullable Map> splitSubGraphs) { + @Nullable Map> splitSubGraphs) { Set dicovered = new HashSet<>(); Set vertices = new HashSet<>(nodes.keySet()); List frontier = new ArrayList<>(); @@ -356,9 +351,7 @@ public class TrackGraph { } if (level != null) - for (Iterator iterator = trains.keySet() - .iterator(); iterator.hasNext();) { - UUID uuid = iterator.next(); + for (UUID uuid : trains.keySet()) { Train train = trains.get(uuid); if (train.graph != this) continue; @@ -391,7 +384,7 @@ public class TrackGraph { } public void connectNodes(LevelAccessor reader, DiscoveredLocation location, DiscoveredLocation location2, - @Nullable BezierConnection turn) { + @Nullable BezierConnection turn) { TrackNode node1 = nodes.get(location); TrackNode node2 = nodes.get(location2); @@ -415,6 +408,10 @@ public class TrackGraph { if (edge == otherEdge) continue; + if (otherEdge.isInterDimensional() || edge.isInterDimensional()) + continue; + if (node1.location.dimension != otherNode1.location.dimension) + continue; if (!bezier && !otherEdge.isTurn()) continue; if (otherEdge.isTurn() && otherEdge.turn.isPrimary()) diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphHelper.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphHelper.java index a29a6f29d0..6edac3aed1 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphHelper.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphHelper.java @@ -12,8 +12,8 @@ import com.simibubi.create.content.trains.track.BezierConnection; import com.simibubi.create.content.trains.track.BezierTrackPointLocation; import com.simibubi.create.content.trains.track.ITrackBlock; import com.simibubi.create.content.trains.track.TrackBlockEntity; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.world.level.Level; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphLocation.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphLocation.java index edf6ff213a..a43223735f 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphLocation.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphLocation.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.trains.graph; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; public class TrackGraphLocation { - + public TrackGraph graph; public Couple edge; public double position; - -} \ No newline at end of file + +} diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSync.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSync.java index b9ac69f6a3..f4f11aee46 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSync.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSync.java @@ -14,9 +14,9 @@ import com.simibubi.create.Create; import com.simibubi.create.content.trains.signal.EdgeGroupColor; import com.simibubi.create.content.trains.signal.SignalEdgeGroupPacket; import com.simibubi.create.content.trains.signal.TrackEdgePoint; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.network.PacketDistributor; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSyncPacket.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSyncPacket.java index f3b04b13f0..2d9eb74f20 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSyncPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSyncPacket.java @@ -13,10 +13,10 @@ import com.simibubi.create.content.trains.GlobalRailwayManager; import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.content.trains.track.BezierConnection; import com.simibubi.create.content.trains.track.TrackMaterial; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.phys.Vec3; @@ -172,7 +172,7 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { @Override protected void handle(GlobalRailwayManager manager, TrackGraph graph) { manager.version++; - + if (packetDeletesGraph) { manager.removeGraph(graph); return; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphVisualizer.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphVisualizer.java index 3083ba5a5f..214c83b47e 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphVisualizer.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphVisualizer.java @@ -9,15 +9,14 @@ import org.lwjgl.glfw.GLFW; import com.simibubi.create.AllKeys; import com.simibubi.create.Create; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.trains.signal.SignalBoundary; import com.simibubi.create.content.trains.signal.SignalEdgeGroup; import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.content.trains.track.BezierConnection; -import com.simibubi.create.foundation.outliner.Outliner; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.AABB; @@ -36,7 +35,7 @@ public class TrackGraphVisualizer { return; Vec3 camera = cameraEntity.getEyePosition(); - Outliner outliner = CreateClient.OUTLINER; + Outliner outliner = Outliner.getInstance(); Map allGroups = Create.RAILWAYS.sided(null).signalEdgeGroups; float width = 1 / 8f; @@ -239,7 +238,7 @@ public class TrackGraphVisualizer { Vec3 yOffset = new Vec3(0, 3 / 16f, 0); Vec3 v1 = location.add(yOffset); Vec3 v2 = v1.add(node.normal.scale(3 / 16f)); - CreateClient.OUTLINER.showLine(Integer.valueOf(node.netId), v1, v2) + Outliner.getInstance().showLine(Integer.valueOf(node.netId), v1, v2) .colored(Color.mixColors(Color.WHITE, graph.color, 1)) .lineWidth(1 / 8f); @@ -255,7 +254,7 @@ public class TrackGraphVisualizer { if (!edge.node1.location.dimension.equals(edge.node2.location.dimension)) { v1 = location.add(yOffset); v2 = v1.add(node.normal.scale(3 / 16f)); - CreateClient.OUTLINER.showLine(Integer.valueOf(node.netId), v1, v2) + Outliner.getInstance().showLine(Integer.valueOf(node.netId), v1, v2) .colored(Color.mixColors(Color.WHITE, graph.color, 1)) .lineWidth(1 / 4f); continue; @@ -268,15 +267,15 @@ public class TrackGraphVisualizer { if (extended) { Vec3 materialPos = edge.getPosition(graph, 0.5) .add(0, 1, 0); - CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos, + Outliner.getInstance().showItem(Pair.of(edge, edge.edgeData), materialPos, edge.getTrackMaterial() .asStack()); - CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25) + Outliner.getInstance().showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25) .move(0, -0.5, 0)) .lineWidth(1 / 16f) .colored(graph.color); } - CreateClient.OUTLINER.showLine(edge, edge.getPosition(graph, 0) + Outliner.getInstance().showLine(edge, edge.getPosition(graph, 0) .add(yOffset), edge.getPosition(graph, 1) .add(yOffset)) @@ -290,9 +289,9 @@ public class TrackGraphVisualizer { if (extended) { Vec3 materialPos = edge.getPosition(graph, 0.5) .add(0, 1, 0); - CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos, edge.getTrackMaterial() + Outliner.getInstance().showItem(Pair.of(edge, edge.edgeData), materialPos, edge.getTrackMaterial() .asStack()); - CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25) + Outliner.getInstance().showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25) .move(0, -0.5, 0)) .lineWidth(1 / 16f) .colored(graph.color); @@ -300,7 +299,7 @@ public class TrackGraphVisualizer { for (int i = 0; i <= turn.getSegmentCount(); i++) { Vec3 current = edge.getPosition(graph, i * 1f / turn.getSegmentCount()); if (previous != null) - CreateClient.OUTLINER + Outliner.getInstance() .showLine(Pair.of(edge, previous), previous.add(yOffset), current.add(yOffset)) .colored(graph.color) .lineWidth(1 / 16f); diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackNodeLocation.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackNodeLocation.java index aa0a4690ea..1e453dca97 100644 --- a/src/main/java/com/simibubi/create/content/trains/graph/TrackNodeLocation.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackNodeLocation.java @@ -7,8 +7,8 @@ import java.util.Set; import com.simibubi.create.content.trains.track.BezierConnection; import com.simibubi.create.content.trains.track.TrackMaterial; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; import net.minecraft.nbt.CompoundTag; @@ -174,7 +174,7 @@ public class TrackNodeLocation extends Vec3i { this.normal = normal; return this; } - + public DiscoveredLocation withYOffset(int yOffsetPixels) { this.yOffsetPixels = yOffsetPixels; return this; diff --git a/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlockEntity.java index 8d1322d80f..c2869670e2 100644 --- a/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlockEntity.java @@ -5,7 +5,7 @@ import java.util.List; import javax.annotation.Nullable; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; import com.simibubi.create.content.trains.graph.EdgePointType; @@ -14,17 +14,19 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.transform.TransformStack; import net.minecraft.core.BlockPos; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; -public class TrackObserverBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { +public class TrackObserverBlockEntity extends SmartBlockEntity implements TransformableBlockEntity { public TrackTargetingBehaviour edgePoint; @@ -38,7 +40,7 @@ public class TrackObserverBlockEntity extends SmartBlockEntity implements ITrans public void addBehaviours(List behaviours) { behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.OBSERVER)); behaviours.add(filtering = createFilter().withCallback(this::onFilterChanged)); - filtering.setLabel(Lang.translateDirect("logistics.train_observer.cargo_filter")); + filtering.setLabel(CreateLang.translateDirect("logistics.train_observer.cargo_filter")); } private void onFilterChanged(ItemStack newFilter) { @@ -89,21 +91,21 @@ public class TrackObserverBlockEntity extends SmartBlockEntity implements ITrans } @Override - public void transform(StructureTransform transform) { - edgePoint.transform(transform); + public void transform(BlockEntity be, StructureTransform transform) { + edgePoint.transform(be, transform); } public FilteringBehaviour createFilter() { return new FilteringBehaviour(this, new ValueBoxTransform() { @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { TransformStack.of(ms) .rotateXDegrees(90); } @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { return new Vec3(0.5, 15.5 / 16d, 0.5); } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/DestinationSuggestions.java b/src/main/java/com/simibubi/create/content/trains/schedule/DestinationSuggestions.java index bbcbf0f63f..a0a12818af 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/DestinationSuggestions.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/DestinationSuggestions.java @@ -5,8 +5,8 @@ import java.util.List; import com.mojang.brigadier.context.StringRange; import com.mojang.brigadier.suggestion.Suggestion; -import com.simibubi.create.foundation.utility.IntAttached; +import net.createmod.catnip.data.IntAttached; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.components.CommandSuggestions; @@ -26,8 +26,8 @@ public class DestinationSuggestions extends CommandSuggestions { private int yOffset; public DestinationSuggestions(Minecraft pMinecraft, Screen pScreen, EditBox pInput, Font pFont, - List> viableStations, int yOffset) { - super(pMinecraft, pScreen, pInput, pFont, true, true, 0, 7, false, 0xee_303030); + List> viableStations, boolean anchorToBottom, int yOffset) { + super(pMinecraft, pScreen, pInput, pFont, true, true, 0, 7, anchorToBottom, 0xee_303030); this.textBox = pInput; this.font = pFont; this.viableStations = viableStations; @@ -47,7 +47,15 @@ public class DestinationSuggestions extends CommandSuggestions { @Override public void updateCommandInfo() { - String value = this.textBox.getValue(); + String trimmed = textBox.getValue() + .substring(0, textBox.getCursorPosition()); + + if (!textBox.getHighlighted() + .isBlank()) + trimmed = trimmed.replace(textBox.getHighlighted(), ""); + + final String value = trimmed; + if (value.equals(previous)) return; if (!active) { @@ -63,7 +71,7 @@ public class DestinationSuggestions extends CommandSuggestions { .startsWith(value.toLowerCase())) .sorted((ia1, ia2) -> Integer.compare(ia1.getFirst(), ia2.getFirst())) .map(IntAttached::getValue) - .map(s -> new Suggestion(new StringRange(0, s.length()), s)) + .map(s -> new Suggestion(new StringRange(0, 1000), s)) .toList(); showSuggestions(false); @@ -82,4 +90,8 @@ public class DestinationSuggestions extends CommandSuggestions { suggestions = new CommandSuggestions.SuggestionsList(x, 72 + yOffset, width, currentSuggestions, false); } + public boolean isEmpty() { + return viableStations.isEmpty(); + } + } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/IScheduleInput.java b/src/main/java/com/simibubi/create/content/trains/schedule/IScheduleInput.java index 00da4a1044..9345f2ad85 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/IScheduleInput.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/IScheduleInput.java @@ -6,9 +6,8 @@ import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Pair; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -33,8 +32,8 @@ public interface IScheduleInput { public default List getTitleAs(String type) { ResourceLocation id = getId(); - return ImmutableList - .of(Components.translatable(id.getNamespace() + ".schedule." + type + "." + id.getPath())); + return ImmutableList + .of(Component.translatable(id.getNamespace() + ".schedule." + type + "." + id.getPath())); } public default ItemStack getSecondLineIcon() { diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/Schedule.java b/src/main/java/com/simibubi/create/content/trains/schedule/Schedule.java index b23680b57f..e859d94197 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/Schedule.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/Schedule.java @@ -17,12 +17,13 @@ import com.simibubi.create.content.trains.schedule.condition.StationUnloadedCond import com.simibubi.create.content.trains.schedule.condition.TimeOfDayCondition; import com.simibubi.create.content.trains.schedule.destination.ChangeThrottleInstruction; import com.simibubi.create.content.trains.schedule.destination.ChangeTitleInstruction; +import com.simibubi.create.content.trains.schedule.destination.DeliverPackagesInstruction; import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction; +import com.simibubi.create.content.trains.schedule.destination.FetchPackagesInstruction; import com.simibubi.create.content.trains.schedule.destination.ScheduleInstruction; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; @@ -38,6 +39,8 @@ public class Schedule { static { registerInstruction("destination", DestinationInstruction::new); + registerInstruction("package_delivery", DeliverPackagesInstruction::new); + registerInstruction("package_retrieval", FetchPackagesInstruction::new); registerInstruction("rename", ChangeTitleInstruction::new); registerInstruction("throttle", ChangeThrottleInstruction::new); registerCondition("delay", ScheduledDelay::new); @@ -64,7 +67,7 @@ public class Schedule { return list.stream() .map(Pair::getFirst) .map(rl -> rl.getNamespace() + ".schedule." + langSection + rl.getPath()) - .map(Components::translatable) + .map(key -> Component.translatable(key)) .toList(); } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEntry.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEntry.java index 44e7cf2d83..83239e8236 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEntry.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEntry.java @@ -5,8 +5,8 @@ import java.util.List; import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition; import com.simibubi.create.content.trains.schedule.destination.ScheduleInstruction; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; @@ -46,4 +46,4 @@ public class ScheduleEntry { return entry; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItem.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItem.java index 516ad6d345..7ee1313da6 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItem.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItem.java @@ -10,10 +10,10 @@ import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.recipe.ItemCopyingRecipe.SupportsItemCopying; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; @@ -33,11 +33,12 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.network.NetworkHooks; -public class ScheduleItem extends Item implements MenuProvider { +public class ScheduleItem extends Item implements MenuProvider, SupportsItemCopying { public ScheduleItem(Properties pProperties) { super(pProperties); @@ -65,7 +66,7 @@ public class ScheduleItem extends Item implements MenuProvider { } public InteractionResult handScheduleTo(ItemStack pStack, Player pPlayer, LivingEntity pInteractionTarget, - InteractionHand pUsedHand) { + InteractionHand pUsedHand) { InteractionResult pass = InteractionResult.PASS; Schedule schedule = getSchedule(pStack); @@ -74,12 +75,11 @@ public class ScheduleItem extends Item implements MenuProvider { if (pInteractionTarget == null) return pass; Entity rootVehicle = pInteractionTarget.getRootVehicle(); - if (!(rootVehicle instanceof CarriageContraptionEntity)) + if (!(rootVehicle instanceof CarriageContraptionEntity entity)) return pass; if (pPlayer.level().isClientSide) return InteractionResult.SUCCESS; - CarriageContraptionEntity entity = (CarriageContraptionEntity) rootVehicle; Contraption contraption = entity.getContraption(); if (contraption instanceof CarriageContraption cc) { @@ -95,27 +95,27 @@ public class ScheduleItem extends Item implements MenuProvider { .get(seatIndex); Couple directions = cc.conductorSeats.get(seatPos); if (directions == null) { - pPlayer.displayClientMessage(Lang.translateDirect("schedule.non_controlling_seat"), true); + pPlayer.displayClientMessage(CreateLang.translateDirect("schedule.non_controlling_seat"), true); AllSoundEvents.DENY.playOnServer(pPlayer.level(), pPlayer.blockPosition(), 1, 1); return InteractionResult.SUCCESS; } if (train.runtime.getSchedule() != null) { AllSoundEvents.DENY.playOnServer(pPlayer.level(), pPlayer.blockPosition(), 1, 1); - pPlayer.displayClientMessage(Lang.translateDirect("schedule.remove_with_empty_hand"), true); + pPlayer.displayClientMessage(CreateLang.translateDirect("schedule.remove_with_empty_hand"), true); return InteractionResult.SUCCESS; } if (schedule.entries.isEmpty()) { AllSoundEvents.DENY.playOnServer(pPlayer.level(), pPlayer.blockPosition(), 1, 1); - pPlayer.displayClientMessage(Lang.translateDirect("schedule.no_stops"), true); + pPlayer.displayClientMessage(CreateLang.translateDirect("schedule.no_stops"), true); return InteractionResult.SUCCESS; } train.runtime.setSchedule(schedule, false); AllAdvancements.CONDUCTOR.awardTo(pPlayer); AllSoundEvents.CONFIRM.playOnServer(pPlayer.level(), pPlayer.blockPosition(), 1, 1); - pPlayer.displayClientMessage(Lang.translateDirect("schedule.applied_to_train") + pPlayer.displayClientMessage(CreateLang.translateDirect("schedule.applied_to_train") .withStyle(ChatFormatting.GREEN), true); pStack.shrink(1); pPlayer.setItemInHand(pUsedHand, pStack.isEmpty() ? ItemStack.EMPTY : pStack); @@ -131,8 +131,8 @@ public class ScheduleItem extends Item implements MenuProvider { if (schedule == null || schedule.entries.isEmpty()) return; - MutableComponent caret = Components.literal("> ").withStyle(ChatFormatting.GRAY); - MutableComponent arrow = Components.literal("-> ").withStyle(ChatFormatting.GRAY); + MutableComponent caret = Component.literal("> ").withStyle(ChatFormatting.GRAY); + MutableComponent arrow = Component.literal("-> ").withStyle(ChatFormatting.GRAY); List entries = schedule.entries; for (int i = 0; i < entries.size(); i++) { @@ -143,7 +143,7 @@ public class ScheduleItem extends Item implements MenuProvider { ChatFormatting format = current ? ChatFormatting.YELLOW : ChatFormatting.GOLD; MutableComponent prefix = current ? arrow : caret; tooltip.add(prefix.copy() - .append(Components.literal(destination.getFilter()).withStyle(format))); + .append(Component.literal(destination.getFilter()).withStyle(format))); } } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItemEntityInteraction.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItemEntityInteraction.java index f4a048b1ca..ab1ff200c0 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItemEntityInteraction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItemEntityInteraction.java @@ -6,9 +6,9 @@ import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.trains.entity.CarriageContraption; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.Train; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -16,6 +16,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; + import net.minecraftforge.event.entity.player.PlayerInteractEvent.EntityInteractSpecific; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -33,7 +34,7 @@ public class ScheduleItemEntityInteraction { return; Entity rootVehicle = entity.getRootVehicle(); - if (!(rootVehicle instanceof CarriageContraptionEntity)) + if (!(rootVehicle instanceof CarriageContraptionEntity cce)) return; if (!(entity instanceof LivingEntity living)) return; @@ -42,7 +43,7 @@ public class ScheduleItemEntityInteraction { return; ItemStack itemStack = event.getItemStack(); - if (itemStack.getItem()instanceof ScheduleItem si) { + if (itemStack.getItem() instanceof ScheduleItem si) { InteractionResult result = si.handScheduleTo(itemStack, player, living, event.getHand()); if (result.consumesAction()) { player.getCooldowns() @@ -56,7 +57,6 @@ public class ScheduleItemEntityInteraction { if (event.getHand() == InteractionHand.OFF_HAND) return; - CarriageContraptionEntity cce = (CarriageContraptionEntity) rootVehicle; Contraption contraption = cce.getContraption(); if (!(contraption instanceof CarriageContraption cc)) return; @@ -83,7 +83,7 @@ public class ScheduleItemEntityInteraction { if (onServer) { train.runtime.paused = false; AllSoundEvents.CONFIRM.playOnServer(player.level(), player.blockPosition(), 1, 1); - player.displayClientMessage(Lang.translateDirect("schedule.continued"), true); + player.displayClientMessage(CreateLang.translateDirect("schedule.continued"), true); } player.getCooldowns() @@ -97,7 +97,7 @@ public class ScheduleItemEntityInteraction { if (!itemInHand.isEmpty()) { if (onServer) { AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); - player.displayClientMessage(Lang.translateDirect("schedule.remove_with_empty_hand"), true); + player.displayClientMessage(CreateLang.translateDirect("schedule.remove_with_empty_hand"), true); } event.setCancellationResult(InteractionResult.SUCCESS); event.setCanceled(true); @@ -107,7 +107,7 @@ public class ScheduleItemEntityInteraction { if (onServer) { AllSoundEvents.playItemPickup(player); player.displayClientMessage( - Lang.translateDirect( + CreateLang.translateDirect( train.runtime.isAutoSchedule ? "schedule.auto_removed_from_train" : "schedule.removed_from_train"), true); diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleRuntime.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleRuntime.java index 11d808fd0d..840e194b04 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleRuntime.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleRuntime.java @@ -4,26 +4,24 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; -import java.util.regex.PatternSyntaxException; import com.simibubi.create.AllItems; import com.simibubi.create.content.trains.display.GlobalTrainDisplayData.TrainDeparturePrediction; import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.graph.DiscoveredPath; -import com.simibubi.create.content.trains.graph.EdgePointType; import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition; import com.simibubi.create.content.trains.schedule.condition.ScheduledDelay; -import com.simibubi.create.content.trains.schedule.destination.ChangeThrottleInstruction; import com.simibubi.create.content.trains.schedule.destination.ChangeTitleInstruction; import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction; import com.simibubi.create.content.trains.schedule.destination.ScheduleInstruction; import com.simibubi.create.content.trains.station.GlobalStation; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; @@ -38,8 +36,8 @@ public class ScheduleRuntime { PRE_TRANSIT, IN_TRANSIT, POST_TRANSIT } - Train train; - Schedule schedule; + public Train train; + public Schedule schedule; public boolean isAutoSchedule; public boolean paused; @@ -47,27 +45,33 @@ public class ScheduleRuntime { public int currentEntry; public State state; - static final int INTERVAL = 40; - int cooldown; - List conditionProgress; - List conditionContext; - String currentTitle; + public List conditionProgress; + public List conditionContext; + public String currentTitle; - int ticksInTransit; - List predictionTicks; + public int ticksInTransit; + public List predictionTicks; public boolean displayLinkUpdateRequested; + private static final int INTERVAL = 40; + private int cooldown; + public ScheduleRuntime(Train train) { this.train = train; reset(); } + public void startCooldown() { + cooldown = INTERVAL; + } + public void destinationReached() { if (state != State.IN_TRANSIT) return; state = State.POST_TRANSIT; conditionProgress.clear(); + conditionContext.clear(); displayLinkUpdateRequested = true; for (Carriage carriage : train.carriages) carriage.storage.resetIdleCargoTracker(); @@ -124,7 +128,7 @@ public class ScheduleRuntime { return; } - DiscoveredPath nextPath = startCurrentInstruction(); + DiscoveredPath nextPath = startCurrentInstruction(level); if (nextPath == null) return; @@ -141,7 +145,15 @@ public class ScheduleRuntime { } public void tickConditions(Level level) { - List> conditions = schedule.entries.get(currentEntry).conditions; + ScheduleEntry entry = schedule.entries.get(currentEntry); + List> conditions = entry.conditions; + + if (!entry.instruction.supportsConditions()) { + state = State.PRE_TRANSIT; + currentEntry++; + return; + } + for (int i = 0; i < conditions.size(); i++) { List list = conditions.get(i); int progress = conditionProgress.get(i); @@ -169,58 +181,10 @@ public class ScheduleRuntime { carriage.storage.tickIdleCargoTracker(); } - public DiscoveredPath startCurrentInstruction() { + public DiscoveredPath startCurrentInstruction(Level level) { ScheduleEntry entry = schedule.entries.get(currentEntry); ScheduleInstruction instruction = entry.instruction; - - if (instruction instanceof DestinationInstruction destination) { - String regex = destination.getFilterForRegex(); - boolean anyMatch = false; - ArrayList validStations = new ArrayList<>(); - - if (!train.hasForwardConductor() && !train.hasBackwardConductor()) { - train.status.missingConductor(); - cooldown = INTERVAL; - return null; - } - - try { - for (GlobalStation globalStation : train.graph.getPoints(EdgePointType.STATION)) { - if (!globalStation.name.matches(regex)) - continue; - anyMatch = true; - validStations.add(globalStation); - } - } catch (PatternSyntaxException ignored) {} - - DiscoveredPath best = train.navigation.findPathTo(validStations, Double.MAX_VALUE); - if (best == null) { - if (anyMatch) - train.status.failedNavigation(); - else - train.status.failedNavigationNoTarget(destination.getFilter()); - cooldown = INTERVAL; - return null; - } - - return best; - } - - if (instruction instanceof ChangeTitleInstruction title) { - currentTitle = title.getScheduleTitle(); - state = State.PRE_TRANSIT; - currentEntry++; - return null; - } - - if (instruction instanceof ChangeThrottleInstruction throttle) { - train.throttle = throttle.getThrottle(); - state = State.PRE_TRANSIT; - currentEntry++; - return null; - } - - return null; + return instruction.start(this, level); } public void setSchedule(Schedule schedule, boolean auto) { @@ -323,7 +287,7 @@ public class ScheduleRuntime { } private int predictForEntry(int index, String currentTitle, int accumulatedTime, - Collection predictions) { + Collection predictions) { ScheduleEntry entry = schedule.entries.get(index); if (!(entry.instruction instanceof DestinationInstruction filter)) return accumulatedTime; @@ -362,7 +326,8 @@ public class ScheduleRuntime { } ScheduleEntry scheduleEntry = schedule.entries.get(index); - Columns: for (List list : scheduleEntry.conditions) { + Columns: + for (List list : scheduleEntry.conditions) { int total = 0; for (ScheduleWaitCondition condition : list) { if (!(condition instanceof ScheduledDelay wait)) @@ -381,8 +346,9 @@ public class ScheduleRuntime { int size = schedule.entries.size(); if (index >= size) { - if (!schedule.cyclic) - return new TrainDeparturePrediction(train, time, Components.literal(" "), destination); + if (!schedule.cyclic) { + return new TrainDeparturePrediction(train, time, CommonComponents.space(), destination); + } index %= size; } @@ -400,7 +366,7 @@ public class ScheduleRuntime { } } - return new TrainDeparturePrediction(train, time, Components.literal(text), destination); + return new TrainDeparturePrediction(train, time, Component.literal(text), destination); } public CompoundTag write() { @@ -459,12 +425,12 @@ public class ScheduleRuntime { public MutableComponent getWaitingStatus(Level level) { List> conditions = schedule.entries.get(currentEntry).conditions; if (conditions.isEmpty() || conditionProgress.isEmpty() || conditionContext.isEmpty()) - return Components.empty(); + return Component.empty(); List list = conditions.get(0); int progress = conditionProgress.get(0); if (progress >= list.size()) - return Components.empty(); + return Component.empty(); CompoundTag tag = conditionContext.get(0); ScheduleWaitCondition condition = list.get(progress); diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleScreen.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleScreen.java index 0db102a3d5..7c36a93813 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleScreen.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleScreen.java @@ -11,12 +11,8 @@ import java.util.function.Consumer; import javax.annotation.Nullable; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; - import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.platform.InputConstants; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllPackets; import com.simibubi.create.Create; @@ -32,8 +28,7 @@ import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.ModularGuiLine; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.ScreenWithStencils; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.menu.GhostItemSubmitPacket; import com.simibubi.create.foundation.gui.widget.IconButton; @@ -41,31 +36,33 @@ import com.simibubi.create.foundation.gui.widget.Indicator; import com.simibubi.create.foundation.gui.widget.Indicator.State; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.IntAttached; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.gui.UIRenderHelper; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.renderer.Rect2i; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.phys.Vec3; -public class ScheduleScreen extends AbstractSimiContainerScreen { +public class ScheduleScreen extends AbstractSimiContainerScreen implements ScreenWithStencils { private static final int CARD_HEADER = 22; private static final int CARD_WIDTH = 195; @@ -109,54 +106,64 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { @Override protected void init() { AllGuiTextures bg = AllGuiTextures.SCHEDULE; - setWindowSize(bg.width, bg.height); + setWindowSize(bg.getWidth(), bg.getHeight()); super.init(); clearWidgets(); - confirmButton = new IconButton(leftPos + bg.width - 42, topPos + bg.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(leftPos + bg.getWidth() - 42, topPos + bg.getHeight() - 30, AllIcons.I_CONFIRM); confirmButton.withCallback(() -> minecraft.player.closeContainer()); addRenderableWidget(confirmButton); - cyclicIndicator = new Indicator(leftPos + 21, topPos + 196, Components.immutableEmpty()); + cyclicIndicator = new Indicator(leftPos + 21, topPos + 196, CommonComponents.EMPTY); cyclicIndicator.state = schedule.cyclic ? State.ON : State.OFF; - addRenderableWidget(cyclicIndicator); - cyclicButton = new IconButton(leftPos + 21, topPos + 202, AllIcons.I_REFRESH); + List tip = new ArrayList<>(); + tip.add(CreateLang.translateDirect("schedule.loop")); + tip.add(CreateLang.translateDirect("gui.schematicannon.optionDisabled") + .withStyle(ChatFormatting.RED)); + tip.add(CreateLang.translateDirect("schedule.loop1") + .withStyle(ChatFormatting.GRAY)); + tip.add(CreateLang.translateDirect("schedule.loop2") + .withStyle(ChatFormatting.GRAY)); + + List tipEnabled = new ArrayList<>(tip); + tipEnabled.set(1, CreateLang.translateDirect("gui.schematicannon.optionEnabled") + .withStyle(ChatFormatting.DARK_GREEN)); + + cyclicButton = new IconButton(leftPos + 21, topPos + 196, AllIcons.I_REFRESH); cyclicButton.withCallback(() -> { schedule.cyclic = !schedule.cyclic; - cyclicIndicator.state = schedule.cyclic ? State.ON : State.OFF; + cyclicButton.green = schedule.cyclic; + cyclicButton.getToolTip().clear(); + cyclicButton.getToolTip().addAll(schedule.cyclic ? tipEnabled : tip); }); - - List tip = cyclicButton.getToolTip(); - tip.add(Lang.translateDirect("schedule.loop")); - tip.add(Lang.translateDirect("schedule.loop1") - .withStyle(ChatFormatting.GRAY)); - tip.add(Lang.translateDirect("schedule.loop2") - .withStyle(ChatFormatting.GRAY)); + cyclicButton.green = schedule.cyclic; + cyclicButton.getToolTip().clear(); + cyclicButton.getToolTip().addAll(schedule.cyclic ? tipEnabled : tip); addRenderableWidget(cyclicButton); - resetProgress = new IconButton(leftPos + 45, topPos + 202, AllIcons.I_PRIORITY_VERY_HIGH); + resetProgress = new IconButton(leftPos + 45, topPos + 196, AllIcons.I_PRIORITY_VERY_HIGH); resetProgress.withCallback(() -> { schedule.savedProgress = 0; resetProgress.active = false; }); resetProgress.active = schedule.savedProgress > 0 && !schedule.entries.isEmpty(); - resetProgress.setToolTip(Lang.translateDirect("schedule.reset")); + resetProgress.setToolTip(CreateLang.translateDirect("schedule.reset")); addRenderableWidget(resetProgress); - skipProgress = new IconButton(leftPos + 63, topPos + 202, AllIcons.I_PRIORITY_LOW); + skipProgress = new IconButton(leftPos + 63, topPos + 196, AllIcons.I_PRIORITY_LOW); skipProgress.withCallback(() -> { schedule.savedProgress++; schedule.savedProgress %= schedule.entries.size(); resetProgress.active = schedule.savedProgress > 0; }); skipProgress.active = schedule.entries.size() > 1; - skipProgress.setToolTip(Lang.translateDirect("schedule.skip")); + skipProgress.setToolTip(CreateLang.translateDirect("schedule.skip")); addRenderableWidget(skipProgress); stopEditing(); - extraAreas = ImmutableList.of(new Rect2i(leftPos + bg.width, topPos + bg.height - 56, 48, 48)); + extraAreas = ImmutableList.of(new Rect2i(leftPos + bg.getWidth(), topPos + bg.getHeight() - 56, 48, 48)); horizontalScrolls.clear(); for (int i = 0; i < schedule.entries.size(); i++) horizontalScrolls.add(LerpedFloat.linear() @@ -172,7 +179,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { resetProgress.visible = false; scrollInput = new SelectionScrollInput(leftPos + 56, topPos + 65, 143, 16); - scrollInputLabel = new Label(leftPos + 59, topPos + 69, Components.immutableEmpty()).withShadow(); + scrollInputLabel = new Label(leftPos + 59, topPos + 69, CommonComponents.EMPTY).withShadow(); editorConfirm = new IconButton(leftPos + 56 + 168, topPos + 65 + 22, AllIcons.I_CONFIRM); if (allowDeletion) editorDelete = new IconButton(leftPos + 56 - 45, topPos + 65 + 22, AllIcons.I_TRASH); @@ -182,7 +189,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { for (int i = 0; i < field.slotsTargeted(); i++) { ItemStack item = field.getItem(i); menu.ghostInventory.setStackInSlot(i, item); - AllPackets.getChannel().sendToServer(new GhostItemSubmitPacket(item, i)); + AllPackets.getChannel() + .sendToServer(new GhostItemSubmitPacket(item, i)); } if (field instanceof ScheduleInstruction instruction) { @@ -195,7 +203,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { editingDestination = instruction; updateEditorSubwidgets(editingDestination); scrollInput.forOptions(Schedule.getTypeOptions(Schedule.INSTRUCTION_TYPES)) - .titled(Lang.translateDirect("schedule.instruction_type")) + .titled(CreateLang.translateDirect("schedule.instruction_type")) .writingTo(scrollInputLabel) .calling(index -> { ScheduleInstruction newlyCreated = Schedule.INSTRUCTION_TYPES.get(index) @@ -220,7 +228,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { editingCondition = cond; updateEditorSubwidgets(editingCondition); scrollInput.forOptions(Schedule.getTypeOptions(Schedule.CONDITION_TYPES)) - .titled(Lang.translateDirect("schedule.condition_type")) + .titled(CreateLang.translateDirect("schedule.condition_type")) .writingTo(scrollInputLabel) .calling(index -> { ScheduleWaitCondition newlyCreated = Schedule.CONDITION_TYPES.get(index) @@ -267,7 +275,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { IScheduleInput editing = editingCondition == null ? editingDestination : editingCondition; for (int i = 0; i < editing.slotsTargeted(); i++) { editing.setItem(i, menu.ghostInventory.getStackInSlot(i)); - AllPackets.getChannel().sendToServer(new GhostItemSubmitPacket(ItemStack.EMPTY, i)); + AllPackets.getChannel() + .sendToServer(new GhostItemSubmitPacket(ItemStack.EMPTY, i)); } editorSubWidgets.saveValues(editing.getData()); @@ -299,7 +308,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { if (!(e instanceof EditBox destinationBox)) return; destinationSuggestions = new DestinationSuggestions(this.minecraft, this, destinationBox, this.font, - getViableStations(field), topPos + 33); + getViableStations(field), false, topPos + 33); destinationSuggestions.setAllowSuggestions(true); destinationSuggestions.updateCommandInfo(); destinationBox.setResponder(this::onDestinationEdited); @@ -318,7 +327,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { String filter = destination.getFilterForRegex(); if (filter.isBlank()) continue; - Graphs: for (Iterator iterator = viableGraphs.iterator(); iterator.hasNext();) { + Graphs: + for (Iterator iterator = viableGraphs.iterator(); iterator.hasNext(); ) { TrackGraph trackGraph = iterator.next(); for (GlobalStation station : trackGraph.getPoints(EdgePointType.STATION)) { if (station.name.matches(filter)) @@ -379,7 +389,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { PoseStack matrixStack = graphics.pose(); UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer); - UIRenderHelper.drawStretched(graphics, leftPos + 33, topPos + 16, 3, 173, 200, AllGuiTextures.SCHEDULE_STRIP_DARK); + UIRenderHelper.drawStretched(graphics, leftPos + 33, topPos + 16, 3, 173, 200, + AllGuiTextures.SCHEDULE_STRIP_DARK); int yOffset = 25; List entries = schedule.entries; @@ -401,8 +412,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { matrixStack.pushPose(); matrixStack.translate(0, scrollOffset, 0); if (i == 0 || entries.size() == 0) - UIRenderHelper.drawStretched(graphics, leftPos + 33, topPos + 16, 3, 10, - -100, AllGuiTextures.SCHEDULE_STRIP_LIGHT); + UIRenderHelper.drawStretched(graphics, leftPos + 33, topPos + 16, 3, 10, -100, + AllGuiTextures.SCHEDULE_STRIP_LIGHT); if (i == entries.size()) { if (i > 0) @@ -476,7 +487,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { } public int renderScheduleEntry(GuiGraphics graphics, ScheduleEntry entry, int yOffset, int mouseX, int mouseY, - float partialTicks) { + float partialTicks) { int zLevel = -100; AllGuiTextures light = AllGuiTextures.SCHEDULE_CARD_LIGHT; @@ -511,8 +522,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { if (i < schedule.entries.size() - 1) AllGuiTextures.SCHEDULE_CARD_MOVE_DOWN.render(graphics, cardWidth, cardHeader); - UIRenderHelper.drawStretched(graphics, 8, 0, 3, cardHeight + 10, zLevel, - AllGuiTextures.SCHEDULE_STRIP_LIGHT); + UIRenderHelper.drawStretched(graphics, 8, 0, 3, cardHeight + 10, zLevel, AllGuiTextures.SCHEDULE_STRIP_LIGHT); (supportsConditions ? AllGuiTextures.SCHEDULE_STRIP_TRAVEL : AllGuiTextures.SCHEDULE_STRIP_ACTION) .render(graphics, 4, 6); @@ -528,8 +538,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { return cardHeight; } - public void renderScheduleConditions(GuiGraphics graphics, ScheduleEntry entry, int yOffset, int mouseX, - int mouseY, float partialTicks, int cardHeight, int entryIndex) { + public void renderScheduleConditions(GuiGraphics graphics, ScheduleEntry entry, int yOffset, int mouseX, int mouseY, + float partialTicks, int cardHeight, int entryIndex) { int cardWidth = CARD_WIDTH; int cardHeader = CARD_HEADER; @@ -546,8 +556,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { int maxWidth = getConditionColumnWidth(list); for (int i = 0; i < list.size(); i++) { ScheduleWaitCondition scheduleWaitCondition = list.get(i); - Math.max(maxWidth, renderInput(graphics, scheduleWaitCondition.getSummary(), xOffset, 29 + i * 18, - i != 0, maxWidth)); + Math.max(maxWidth, + renderInput(graphics, scheduleWaitCondition.getSummary(), xOffset, 29 + i * 18, i != 0, maxWidth)); scheduleWaitCondition.renderSpecialIcon(graphics, xOffset + 4, 29 + i * 18); } @@ -599,7 +609,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { } protected int renderInput(GuiGraphics graphics, Pair pair, int x, int y, boolean clean, - int minSize) { + int minSize) { ItemStack stack = pair.getFirst(); Component text = pair.getSecond(); boolean hasItem = !stack.isEmpty(); @@ -635,16 +645,16 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { return fieldSize; } - private Component clickToEdit = Lang.translateDirect("gui.schedule.lmb_edit") + private Component clickToEdit = CreateLang.translateDirect("gui.schedule.lmb_edit") .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC); - private Component rClickToDelete = Lang.translateDirect("gui.schedule.rmb_remove") + private Component rClickToDelete = CreateLang.translateDirect("gui.schedule.rmb_remove") .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC); public boolean action(@Nullable GuiGraphics graphics, double mouseX, double mouseY, int click) { if (editingCondition != null || editingDestination != null) return false; - Component empty = Components.immutableEmpty(); + Component empty = CommonComponents.EMPTY; int mx = (int) mouseX; int my = (int) mouseY; @@ -688,8 +698,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { if (x > 180 && x <= 192) { if (y > 0 && y <= 14) { - renderActionTooltip(graphics, ImmutableList.of(Lang.translateDirect("gui.schedule.remove_entry")), - mx, my); + renderActionTooltip(graphics, + ImmutableList.of(CreateLang.translateDirect("gui.schedule.remove_entry")), mx, my); if (click == 0) { entries.remove(entry); init(); @@ -697,8 +707,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { return true; } if (y > cardHeight - 14) { - renderActionTooltip(graphics, ImmutableList.of(Lang.translateDirect("gui.schedule.duplicate")), mx, - my); + renderActionTooltip(graphics, + ImmutableList.of(CreateLang.translateDirect("gui.schedule.duplicate")), mx, my); if (click == 0) { entries.add(entries.indexOf(entry), entry.clone()); init(); @@ -709,8 +719,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { if (x > 194) { if (y > 7 && y <= 20 && i > 0) { - renderActionTooltip(graphics, ImmutableList.of(Lang.translateDirect("gui.schedule.move_up")), mx, - my); + renderActionTooltip(graphics, ImmutableList.of(CreateLang.translateDirect("gui.schedule.move_up")), + mx, my); if (click == 0) { entries.remove(entry); entries.add(i - 1, entry); @@ -719,8 +729,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { return true; } if (y > 20 && y <= 33 && i < entries.size() - 1) { - renderActionTooltip(graphics, ImmutableList.of(Lang.translateDirect("gui.schedule.move_down")), mx, - my); + renderActionTooltip(graphics, + ImmutableList.of(CreateLang.translateDirect("gui.schedule.move_down")), mx, my); if (click == 0) { entries.remove(entry); entries.add(i + 1, entry); @@ -769,7 +779,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { if (row < conditions.size() && row >= 0) { boolean canRemove = conditions.size() > 1 || columns.size() > 1; List components = new ArrayList<>(); - components.add(Lang.translateDirect("schedule.condition_type") + components.add(CreateLang.translateDirect("schedule.condition_type") .withStyle(ChatFormatting.GRAY)); ScheduleWaitCondition condition = conditions.get(row); components.addAll(condition.getTitleAs("condition")); @@ -797,7 +807,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { } if (y > 18 * conditions.size() && y <= 18 * conditions.size() + 10 && x >= w / 2 - 5 && x < w / 2 + 5) { - renderActionTooltip(graphics, ImmutableList.of(Lang.translateDirect("gui.schedule.add_condition")), mx, my); + renderActionTooltip(graphics, + ImmutableList.of(CreateLang.translateDirect("gui.schedule.add_condition")), mx, my); if (click == 0) startEditing(new ScheduledDelay(), confirmed -> { if (confirmed) @@ -812,8 +823,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { if (x < 0 || x > 15 || y > 20) return false; - renderActionTooltip(graphics, ImmutableList.of(Lang.translateDirect("gui.schedule.alternative_condition")), - mx, my); + renderActionTooltip(graphics, + ImmutableList.of(CreateLang.translateDirect("gui.schedule.alternative_condition")), mx, my); if (click == 0) startEditing(new ScheduledDelay(), confirmed -> { if (!confirmed) @@ -828,7 +839,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { if (x < 18 || x > 33 || y > 14) return false; - renderActionTooltip(graphics, ImmutableList.of(Lang.translateDirect("gui.schedule.add_entry")), mx, my); + renderActionTooltip(graphics, ImmutableList.of(CreateLang.translateDirect("gui.schedule.add_entry")), mx, my); if (click == 0) startEditing(new DestinationInstruction(), confirmed -> { if (!confirmed) @@ -857,33 +868,6 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { return Math.max((text == null ? 0 : font.width(text)) + (hasItem ? 20 : 0) + 16, minSize); } - protected void startStencil(GuiGraphics graphics, float x, float y, float w, float h) { - RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); - - GL11.glDisable(GL11.GL_STENCIL_TEST); - RenderSystem.stencilMask(~0); - RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX); - GL11.glEnable(GL11.GL_STENCIL_TEST); - RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP); - RenderSystem.stencilMask(0xFF); - RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF); - - PoseStack matrixStack = graphics.pose(); - matrixStack.pushPose(); - matrixStack.translate(x, y, 0); - matrixStack.scale(w, h, 1); - graphics.fillGradient(0, 0, 1, 1, -100, 0xff000000, 0xff000000); - matrixStack.popPose(); - - GL11.glEnable(GL11.GL_STENCIL_TEST); - RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); - RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF); - } - - protected void endStencil() { - GL11.glDisable(GL11.GL_STENCIL_TEST); - } - @Override public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { if (destinationSuggestions != null @@ -1001,8 +985,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { super.renderForeground(graphics, mouseX, mouseY, partialTicks); GuiGameElement.of(menu.contentHolder).at(leftPos + AllGuiTextures.SCHEDULE.width, topPos + AllGuiTextures.SCHEDULE.height - 56, - -200) + .GuiRenderBuilder>at(leftPos + AllGuiTextures.SCHEDULE.getWidth(), + topPos + AllGuiTextures.SCHEDULE.getHeight() - 56, -200) .scale(3) .render(graphics); action(graphics, mouseX, mouseY, -1); @@ -1019,8 +1003,15 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { for (int i = 0; i < Math.max(1, rendered.slotsTargeted()); i++) { List secondLineTooltip = rendered.getSecondLineTooltip(i); - if (secondLineTooltip == null || (hoveredSlot != menu.getSlot(36 + i) || !hoveredSlot.getItem() - .isEmpty())) + if (secondLineTooltip == null) + continue; + Slot slot = menu.getSlot(36 + i); + if (slot == null || !slot.getItem() + .isEmpty()) + continue; + if (mouseX < leftPos + slot.x || mouseX > leftPos + slot.x + 18) + continue; + if (mouseY < topPos + slot.y || mouseY > topPos + slot.y + 18) continue; renderActionTooltip(graphics, secondLineTooltip, mouseX, mouseY); } @@ -1030,7 +1021,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { protected void renderBg(GuiGraphics graphics, float pPartialTick, int pMouseX, int pMouseY) { AllGuiTextures.SCHEDULE.render(graphics, leftPos, topPos); FormattedCharSequence formattedcharsequence = title.getVisualOrderText(); - int center = leftPos + (AllGuiTextures.SCHEDULE.width - 8) / 2; + int center = leftPos + (AllGuiTextures.SCHEDULE.getWidth() - 8) / 2; graphics.drawString(font, formattedcharsequence, (float) (center - font.width(formattedcharsequence) / 2), (float) topPos + 4, 0x505050, false); renderSchedule(graphics, pMouseX, pMouseY, pPartialTick); @@ -1043,10 +1034,10 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { AllGuiTextures.PLAYER_INVENTORY.render(graphics, leftPos + 38, topPos + 122); graphics.drawString(font, playerInventoryTitle, leftPos + 46, topPos + 128, 0x505050, false); - formattedcharsequence = editingCondition == null ? Lang.translateDirect("schedule.instruction.editor") + formattedcharsequence = editingCondition == null ? CreateLang.translateDirect("schedule.instruction.editor") .getVisualOrderText() - : Lang.translateDirect("schedule.condition.editor") - .getVisualOrderText(); + : CreateLang.translateDirect("schedule.condition.editor") + .getVisualOrderText(); graphics.drawString(font, formattedcharsequence, (float) (center - font.width(formattedcharsequence) / 2), (float) topPos + 44, 0x505050, false); @@ -1078,7 +1069,8 @@ public class ScheduleScreen extends AbstractSimiContainerScreen { @Override public void removed() { super.removed(); - AllPackets.getChannel().sendToServer(new ScheduleEditPacket(schedule)); + AllPackets.getChannel() + .sendToServer(new ScheduleEditPacket(schedule)); } @Override diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/CargoThresholdCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/CargoThresholdCondition.java index d14a0e196f..f655066b8a 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/CargoThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/CargoThresholdCondition.java @@ -7,10 +7,10 @@ import com.google.common.collect.ImmutableList; import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.lang.Lang; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -40,7 +40,7 @@ public abstract class CargoThresholdCondition extends LazyTickedScheduleConditio public static List translatedOptions() { return Arrays.stream(values()) - .map(op -> Lang.translateDirect("schedule.condition.threshold." + Lang.asId(op.name()))) + .map(op -> CreateLang.translateDirect("schedule.condition.threshold." + Lang.asId(op.name()))) .toList(); } } @@ -61,12 +61,12 @@ public abstract class CargoThresholdCondition extends LazyTickedScheduleConditio context.putInt("LastChecked", status); return test(level, train, context); } - + protected void requestStatusToUpdate(int amount, CompoundTag context) { context.putInt("CurrentDisplay", amount); super.requestStatusToUpdate(context); }; - + protected int getLastDisplaySnapshot(CompoundTag context) { if (!context.contains("CurrentDisplay")) return -1; @@ -81,7 +81,7 @@ public abstract class CargoThresholdCondition extends LazyTickedScheduleConditio @Override public Pair getSummary() { - return Pair.of(getIcon(), Components.literal(getOperator().formatted + " " + getThreshold()).append(getUnit())); + return Pair.of(getIcon(), Component.literal(getOperator().formatted + " " + getThreshold()).append(getUnit())); } @Override @@ -108,10 +108,10 @@ public abstract class CargoThresholdCondition extends LazyTickedScheduleConditio @Override public List getSecondLineTooltip(int slot) { - return ImmutableList.of(Lang.translateDirect("schedule.condition.threshold.place_item"), - Lang.translateDirect("schedule.condition.threshold.place_item_2") + return ImmutableList.of(CreateLang.translateDirect("schedule.condition.threshold.place_item"), + CreateLang.translateDirect("schedule.condition.threshold.place_item_2") .withStyle(ChatFormatting.GRAY), - Lang.translateDirect("schedule.condition.threshold.place_item_3") + CreateLang.translateDirect("schedule.condition.threshold.place_item_3") .withStyle(ChatFormatting.GRAY)); } @@ -120,11 +120,13 @@ public abstract class CargoThresholdCondition extends LazyTickedScheduleConditio public void initConfigurationWidgets(ModularGuiLineBuilder builder) { builder.addSelectionScrollInput(0, 24, (i, l) -> { i.forOptions(Ops.translatedOptions()) - .titled(Lang.translateDirect("schedule.condition.threshold.train_holds", "")) - .format(state -> Components.literal(" " + Ops.values()[state].formatted)); + .titled(CreateLang.translateDirect("schedule.condition.threshold.train_holds", "")) + .format(state -> { + return Component.literal(" " + Ops.values()[state].formatted); + }); }, "Operator"); builder.addIntegerTextInput(29, 41, (e, t) -> { }, "Threshold"); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/FluidThresholdCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/FluidThresholdCondition.java index 4432a5c48c..327568c520 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/FluidThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/FluidThresholdCondition.java @@ -8,9 +8,9 @@ import com.simibubi.create.content.logistics.filter.FilterItemStack; import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.Lang; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; @@ -25,12 +25,12 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; public class FluidThresholdCondition extends CargoThresholdCondition { - + private FilterItemStack compareStack = FilterItemStack.empty(); @Override protected Component getUnit() { - return Components.literal("b"); + return Component.literal("b"); } @Override @@ -84,13 +84,13 @@ public class FluidThresholdCondition extends CargoThresholdCondition { @Override public List getTitleAs(String type) { return ImmutableList.of( - Lang.translateDirect("schedule.condition.threshold.train_holds", - Lang.translateDirect("schedule.condition.threshold." + Lang.asId(getOperator().name()))), - Lang.translateDirect("schedule.condition.threshold.x_units_of_item", getThreshold(), - Lang.translateDirect("schedule.condition.threshold.buckets"), - compareStack.isEmpty() ? Lang.translateDirect("schedule.condition.threshold.anything") + CreateLang.translateDirect("schedule.condition.threshold.train_holds", + CreateLang.translateDirect("schedule.condition.threshold." + Lang.asId(getOperator().name()))), + CreateLang.translateDirect("schedule.condition.threshold.x_units_of_item", getThreshold(), + CreateLang.translateDirect("schedule.condition.threshold.buckets"), + compareStack.isEmpty() ? CreateLang.translateDirect("schedule.condition.threshold.anything") : compareStack.isFilterItem() - ? Lang.translateDirect("schedule.condition.threshold.matching_content") + ? CreateLang.translateDirect("schedule.condition.threshold.matching_content") : loadFluid().getDisplayName()) .withStyle(ChatFormatting.DARK_AQUA)); } @@ -115,7 +115,7 @@ public class FluidThresholdCondition extends CargoThresholdCondition { public void initConfigurationWidgets(ModularGuiLineBuilder builder) { super.initConfigurationWidgets(builder); builder.addSelectionScrollInput(71, 50, (i, l) -> { - i.forOptions(ImmutableList.of(Lang.translateDirect("schedule.condition.threshold.buckets"))) + i.forOptions(ImmutableList.of(CreateLang.translateDirect("schedule.condition.threshold.buckets"))) .titled(null); }, "Measure"); } @@ -124,10 +124,10 @@ public class FluidThresholdCondition extends CargoThresholdCondition { public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { int lastDisplaySnapshot = getLastDisplaySnapshot(tag); if (lastDisplaySnapshot == -1) - return Components.empty(); + return Component.empty(); int offset = getOperator() == Ops.LESS ? -1 : getOperator() == Ops.GREATER ? 1 : 0; - return Lang.translateDirect("schedule.condition.threshold.status", lastDisplaySnapshot, - Math.max(0, getThreshold() + offset), Lang.translateDirect("schedule.condition.threshold.buckets")); + return CreateLang.translateDirect("schedule.condition.threshold.status", lastDisplaySnapshot, + Math.max(0, getThreshold() + offset), CreateLang.translateDirect("schedule.condition.threshold.buckets")); } } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/IdleCargoCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/IdleCargoCondition.java index dc7bfcc541..0ed6eef95a 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/IdleCargoCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/IdleCargoCondition.java @@ -3,9 +3,9 @@ package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Train; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -13,25 +13,25 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; public class IdleCargoCondition extends TimedWaitCondition { - + @Override public Pair getSummary() { - return Pair.of(ItemStack.EMPTY, Lang.translateDirect("schedule.condition.idle_short", formatTime(true))); + return Pair.of(ItemStack.EMPTY, CreateLang.translateDirect("schedule.condition.idle_short", formatTime(true))); } @Override public ResourceLocation getId() { return Create.asResource("idle"); } - + @Override public boolean tickCompletion(Level level, Train train, CompoundTag context) { int idleTime = Integer.MAX_VALUE; - for (Carriage carriage : train.carriages) + for (Carriage carriage : train.carriages) idleTime = Math.min(idleTime, carriage.storage.getTicksSinceLastExchange()); context.putInt("Time", idleTime); requestDisplayIfNecessary(context, idleTime); return idleTime > totalWaitTicks(); } - -} \ No newline at end of file + +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java index c39d6316ca..b03c29daf0 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java @@ -8,9 +8,9 @@ import com.simibubi.create.content.logistics.filter.FilterItemStack; import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.Lang; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -23,12 +23,12 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.IItemHandlerModifiable; public class ItemThresholdCondition extends CargoThresholdCondition { - + private FilterItemStack stack = FilterItemStack.empty(); @Override protected Component getUnit() { - return Components.literal(inStacks() ? "\u25A4" : ""); + return Component.literal(inStacks() ? "\u25A4" : ""); } @Override @@ -44,7 +44,7 @@ public class ItemThresholdCondition extends CargoThresholdCondition { int foundItems = 0; for (Carriage carriage : train.carriages) { - IItemHandlerModifiable items = carriage.storage.getItems(); + IItemHandlerModifiable items = carriage.storage.getAllItems(); for (int i = 0; i < items.getSlots(); i++) { ItemStack stackInSlot = items.getStackInSlot(i); if (!stack.test(level, stackInSlot)) @@ -92,14 +92,14 @@ public class ItemThresholdCondition extends CargoThresholdCondition { @Override public List getTitleAs(String type) { return ImmutableList.of( - Lang.translateDirect("schedule.condition.threshold.train_holds", - Lang.translateDirect("schedule.condition.threshold." + Lang.asId(getOperator().name()))), - Lang.translateDirect("schedule.condition.threshold.x_units_of_item", getThreshold(), - Lang.translateDirect("schedule.condition.threshold." + (inStacks() ? "stacks" : "items")), - stack.isEmpty() ? Lang.translateDirect("schedule.condition.threshold.anything") - : stack.isFilterItem() ? Lang.translateDirect("schedule.condition.threshold.matching_content") - : stack.item() - .getHoverName()) + CreateLang.translateDirect("schedule.condition.threshold.train_holds", + CreateLang.translateDirect("schedule.condition.threshold." + Lang.asId(getOperator().name()))), + CreateLang.translateDirect("schedule.condition.threshold.x_units_of_item", getThreshold(), + CreateLang.translateDirect("schedule.condition.threshold." + (inStacks() ? "stacks" : "items")), + stack.isEmpty() ? CreateLang.translateDirect("schedule.condition.threshold.anything") + : stack.isFilterItem() + ? CreateLang.translateDirect("schedule.condition.threshold.matching_content") + : stack.item().getHoverName()) .withStyle(ChatFormatting.DARK_AQUA)); } @@ -117,9 +117,9 @@ public class ItemThresholdCondition extends CargoThresholdCondition { public void initConfigurationWidgets(ModularGuiLineBuilder builder) { super.initConfigurationWidgets(builder); builder.addSelectionScrollInput(71, 50, (i, l) -> { - i.forOptions(ImmutableList.of(Lang.translateDirect("schedule.condition.threshold.items"), - Lang.translateDirect("schedule.condition.threshold.stacks"))) - .titled(Lang.translateDirect("schedule.condition.threshold.item_measure")); + i.forOptions(ImmutableList.of(CreateLang.translateDirect("schedule.condition.threshold.items"), + CreateLang.translateDirect("schedule.condition.threshold.stacks"))) + .titled(CreateLang.translateDirect("schedule.condition.threshold.item_measure")); }, "Measure"); } @@ -127,10 +127,10 @@ public class ItemThresholdCondition extends CargoThresholdCondition { public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { int lastDisplaySnapshot = getLastDisplaySnapshot(tag); if (lastDisplaySnapshot == -1) - return Components.empty(); + return Component.empty(); int offset = getOperator() == Ops.LESS ? -1 : getOperator() == Ops.GREATER ? 1 : 0; - return Lang.translateDirect("schedule.condition.threshold.status", lastDisplaySnapshot, + return CreateLang.translateDirect("schedule.condition.threshold.status", lastDisplaySnapshot, Math.max(0, getThreshold() + offset), - Lang.translateDirect("schedule.condition.threshold." + (inStacks() ? "stacks" : "items"))); + CreateLang.translateDirect("schedule.condition.threshold." + (inStacks() ? "stacks" : "items"))); } } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/PlayerPassengerCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/PlayerPassengerCondition.java index 37cccce411..732ce93caa 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/PlayerPassengerCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/PlayerPassengerCondition.java @@ -7,10 +7,9 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -29,7 +28,7 @@ public class PlayerPassengerCondition extends ScheduleWaitCondition { int target = getTarget(); return Pair.of(AllBlocks.SEATS.get(DyeColor.YELLOW) .asStack(), - Lang.translateDirect("schedule.condition.player_count." + (target == 1 ? "summary" : "summary_plural"), target)); + CreateLang.translateDirect("schedule.condition.player_count." + (target == 1 ? "summary" : "summary_plural"), target)); } @Override @@ -48,23 +47,23 @@ public class PlayerPassengerCondition extends ScheduleWaitCondition { @Override public List getTitleAs(String type) { int target = getTarget(); - return ImmutableList.of(Lang.translateDirect("schedule.condition.player_count.seated", - Lang.translateDirect("schedule.condition.player_count." + (target == 1 ? "summary" : "summary_plural"), - Components.literal("" + target).withStyle(ChatFormatting.DARK_AQUA)))); + return ImmutableList.of(CreateLang.translateDirect("schedule.condition.player_count.seated", + CreateLang.translateDirect("schedule.condition.player_count." + (target == 1 ? "summary" : "summary_plural"), + Component.literal("" + target).withStyle(ChatFormatting.DARK_AQUA)))); } @Override @OnlyIn(Dist.CLIENT) public void initConfigurationWidgets(ModularGuiLineBuilder builder) { builder.addScrollInput(0, 31, (i, l) -> { - i.titled(Lang.translateDirect("schedule.condition.player_count.players")) + i.titled(CreateLang.translateDirect("schedule.condition.player_count.players")) .withShiftStep(5) .withRange(0, 21); }, "Count"); builder.addSelectionScrollInput(36, 85, (i, l) -> { - i.forOptions(Lang.translatedOptions("schedule.condition.player_count", "exactly", "or_above")) - .titled(Lang.translateDirect("schedule.condition.player_count.condition")); + i.forOptions(CreateLang.translatedOptions("schedule.condition.player_count", "exactly", "or_above")) + .titled(CreateLang.translateDirect("schedule.condition.player_count.condition")); }, "Exact"); } @@ -81,7 +80,7 @@ public class PlayerPassengerCondition extends ScheduleWaitCondition { @Override public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { - return Lang.translateDirect("schedule.condition.player_count.status", train.countPlayerPassengers(), getTarget()); + return CreateLang.translateDirect("schedule.condition.player_count.status", train.countPlayerPassengers(), getTarget()); } } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/RedstoneLinkCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/RedstoneLinkCondition.java index 87b07f6e80..f4d48fbad4 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/RedstoneLinkCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/RedstoneLinkCondition.java @@ -8,11 +8,10 @@ import com.simibubi.create.Create; import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -40,27 +39,27 @@ public class RedstoneLinkCondition extends ScheduleWaitCondition { @Override public Pair getSummary() { return Pair.of(AllBlocks.REDSTONE_LINK.asStack(), - lowActivation() ? Lang.translateDirect("schedule.condition.redstone_link_off") - : Lang.translateDirect("schedule.condition.redstone_link_on")); + lowActivation() ? CreateLang.translateDirect("schedule.condition.redstone_link_off") + : CreateLang.translateDirect("schedule.condition.redstone_link_on")); } @Override public List getSecondLineTooltip(int slot) { - return ImmutableList.of(Lang.translateDirect(slot == 0 ? "logistics.firstFrequency" : "logistics.secondFrequency") + return ImmutableList.of(CreateLang.translateDirect(slot == 0 ? "logistics.firstFrequency" : "logistics.secondFrequency") .withStyle(ChatFormatting.RED)); } @Override public List getTitleAs(String type) { return ImmutableList.of( - Lang.translateDirect("schedule.condition.redstone_link.frequency_" + (lowActivation() ? "unpowered" : "powered")), - Components.literal(" #1 ").withStyle(ChatFormatting.GRAY) + CreateLang.translateDirect("schedule.condition.redstone_link.frequency_" + (lowActivation() ? "unpowered" : "powered")), + Component.literal(" #1 ").withStyle(ChatFormatting.GRAY) .append(freq.getFirst() .getStack() .getHoverName() .copy() .withStyle(ChatFormatting.DARK_AQUA)), - Components.literal(" #2 ").withStyle(ChatFormatting.GRAY) + Component.literal(" #2 ").withStyle(ChatFormatting.GRAY) .append(freq.getSecond() .getStack() .getHoverName() @@ -115,14 +114,14 @@ public class RedstoneLinkCondition extends ScheduleWaitCondition { @OnlyIn(Dist.CLIENT) public void initConfigurationWidgets(ModularGuiLineBuilder builder) { builder.addSelectionScrollInput(20, 101, - (i, l) -> i.forOptions(Lang.translatedOptions("schedule.condition.redstone_link", "powered", "unpowered")) - .titled(Lang.translateDirect("schedule.condition.redstone_link.frequency_state")), + (i, l) -> i.forOptions(CreateLang.translatedOptions("schedule.condition.redstone_link", "powered", "unpowered")) + .titled(CreateLang.translateDirect("schedule.condition.redstone_link.frequency_state")), "Inverted"); } @Override public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { - return Lang.translateDirect("schedule.condition.redstone_link.status"); + return CreateLang.translateDirect("schedule.condition.redstone_link.status"); } } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduleWaitCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduleWaitCondition.java index e36d5de68f..f65a23dd19 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduleWaitCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduleWaitCondition.java @@ -6,8 +6,8 @@ import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.schedule.Schedule; import com.simibubi.create.content.trains.schedule.ScheduleDataEntry; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduledDelay.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduledDelay.java index 87de19b400..8d26748e7b 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduledDelay.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduledDelay.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -15,7 +15,7 @@ public class ScheduledDelay extends TimedWaitCondition { @Override public Pair getSummary() { - return Pair.of(ItemStack.EMPTY, Lang.translateDirect("schedule.condition.delay_short", formatTime(true))); + return Pair.of(ItemStack.EMPTY, CreateLang.translateDirect("schedule.condition.delay_short", formatTime(true))); } @Override @@ -23,7 +23,7 @@ public class ScheduledDelay extends TimedWaitCondition { int time = context.getInt("Time"); if (time >= totalWaitTicks()) return true; - + context.putInt("Time", time + 1); requestDisplayIfNecessary(context, time); return false; @@ -34,4 +34,4 @@ public class ScheduledDelay extends TimedWaitCondition { return Create.asResource("delay"); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationPoweredCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationPoweredCondition.java index c4ae0447bd..ad5f469cad 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationPoweredCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationPoweredCondition.java @@ -3,9 +3,9 @@ package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.station.GlobalStation; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -20,9 +20,9 @@ import net.minecraft.world.level.Level; public class StationPoweredCondition extends ScheduleWaitCondition { @Override public Pair getSummary() { - return Pair.of(ItemStack.EMPTY, Lang.translateDirect("schedule.condition.powered")); + return Pair.of(ItemStack.EMPTY, CreateLang.translateDirect("schedule.condition.powered")); } - + @Override public boolean tickCompletion(Level level, Train train, CompoundTag context) { GlobalStation currentStation = train.getCurrentStation(); @@ -52,6 +52,6 @@ public class StationPoweredCondition extends ScheduleWaitCondition { @Override public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { - return Lang.translateDirect("schedule.condition.powered.status"); + return CreateLang.translateDirect("schedule.condition.powered.status"); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationUnloadedCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationUnloadedCondition.java index ec957edd1d..c4d50b90a6 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationUnloadedCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationUnloadedCondition.java @@ -3,9 +3,9 @@ package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.station.GlobalStation; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -19,7 +19,7 @@ import net.minecraft.world.level.Level; public class StationUnloadedCondition extends ScheduleWaitCondition { @Override public Pair getSummary() { - return Pair.of(ItemStack.EMPTY, Lang.translateDirect("schedule.condition.unloaded")); + return Pair.of(ItemStack.EMPTY, CreateLang.translateDirect("schedule.condition.unloaded")); } @Override @@ -51,6 +51,6 @@ public class StationUnloadedCondition extends ScheduleWaitCondition { @Override public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { - return Lang.translateDirect("schedule.condition.unloaded.status"); + return CreateLang.translateDirect("schedule.condition.unloaded.status"); } } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimeOfDayCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimeOfDayCondition.java index cb447af374..4c83a91f53 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimeOfDayCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimeOfDayCondition.java @@ -10,10 +10,9 @@ import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.nbt.CompoundTag; @@ -72,16 +71,16 @@ public class TimeOfDayCondition extends ScheduleWaitCondition { int hour12raw = hour % 12 == 0 ? 12 : hour % 12; String hr12 = doubleDigitHrs ? twoDigits(hour12raw) : ("" + hour12raw); String hr24 = doubleDigitHrs ? twoDigits(hour) : ("" + hour); - return Lang.translateDirect("schedule.condition.time_of_day.digital_format", hr12, hr24, twoDigits(minute), - hour > 11 ? Lang.translateDirect("generic.daytime.pm") : Lang.translateDirect("generic.daytime.am")); + return CreateLang.translateDirect("schedule.condition.time_of_day.digital_format", hr12, hr24, twoDigits(minute), + hour > 11 ? CreateLang.translateDirect("generic.daytime.pm") : CreateLang.translateDirect("generic.daytime.am")); } @Override public List getTitleAs(String type) { - return ImmutableList.of(Lang.translateDirect("schedule.condition.time_of_day.scheduled"), + return ImmutableList.of(CreateLang.translateDirect("schedule.condition.time_of_day.scheduled"), getDigitalDisplay(intData("Hour"), intData("Minute"), false).withStyle(ChatFormatting.DARK_AQUA) - .append(Components.literal(" -> ").withStyle(ChatFormatting.DARK_GRAY)) - .append(Lang + .append(Component.literal(" -> ").withStyle(ChatFormatting.DARK_GRAY)) + .append(CreateLang .translatedOptions("schedule.condition.time_of_day.rotation", "every_24", "every_12", "every_6", "every_4", "every_3", "every_2", "every_1", "every_0_45", "every_0_30", "every_0_15") .get(intData("Rotation")) @@ -129,13 +128,13 @@ public class TimeOfDayCondition extends ScheduleWaitCondition { }, "Minute"); builder.addSelectionScrollInput(52, 62, (i, l) -> { - i.forOptions(Lang.translatedOptions("schedule.condition.time_of_day.rotation", "every_24", "every_12", + i.forOptions(CreateLang.translatedOptions("schedule.condition.time_of_day.rotation", "every_24", "every_12", "every_6", "every_4", "every_3", "every_2", "every_1", "every_0_45", "every_0_30", "every_0_15")) - .titled(Lang.translateDirect("schedule.condition.time_of_day.rotation")); + .titled(CreateLang.translateDirect("schedule.condition.time_of_day.rotation")); }, "Rotation"); hourInput.getValue() - .titled(Lang.translateDirect("generic.daytime.hour")) + .titled(CreateLang.translateDirect("generic.daytime.hour")) .calling(t -> { data.putInt("Hour", t); timeLabel.getValue().text = getDigitalDisplay(t, minuteInput.getValue() @@ -145,7 +144,7 @@ public class TimeOfDayCondition extends ScheduleWaitCondition { .withShiftStep(6); minuteInput.getValue() - .titled(Lang.translateDirect("generic.daytime.minute")) + .titled(CreateLang.translateDirect("generic.daytime.minute")) .calling(t -> { data.putInt("Minute", t); timeLabel.getValue().text = getDigitalDisplay(hourInput.getValue() @@ -183,7 +182,7 @@ public class TimeOfDayCondition extends ScheduleWaitCondition { int departingHour = (departureTime / 1000 + 6) % 24; int departingMinute = (departureTime % 1000) * 60 / 1000; - return Lang.translateDirect("schedule.condition.time_of_day.status") + return CreateLang.translateDirect("schedule.condition.time_of_day.status") .append(getDigitalDisplay(departingHour, departingMinute, false)); } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimedWaitCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimedWaitCondition.java index 996d28352b..15e6efec0b 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimedWaitCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimedWaitCondition.java @@ -5,8 +5,7 @@ import java.util.List; import com.google.common.collect.ImmutableList; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; @@ -36,7 +35,7 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition { } public static List translatedOptions() { - return Lang.translatedOptions(null, TICKS.key, SECONDS.key, MINUTES.key); + return CreateLang.translatedOptions(null, TICKS.key, SECONDS.key, MINUTES.key); } } @@ -58,16 +57,17 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition { } protected Component formatTime(boolean compact) { - if (compact) - return Components.literal(getValue() + getUnit().suffix); - return Components.literal(getValue() + " ").append(Lang.translateDirect(getUnit().key)); + if (compact) { + return Component.literal(getValue() + getUnit().suffix); + } + return Component.literal(getValue() + " ").append(CreateLang.translateDirect(getUnit().key)); } @Override public List getTitleAs(String type) { return ImmutableList.of( - Components.translatable(getId().getNamespace() + ".schedule." + type + "." + getId().getPath()), - Lang.translateDirect("schedule.condition.for_x_time", formatTime(false)) + Component.translatable(getId().getNamespace() + ".schedule." + type + "." + getId().getPath()), + CreateLang.translateDirect("schedule.condition.for_x_time", formatTime(false)) .withStyle(ChatFormatting.DARK_AQUA)); } @@ -78,7 +78,7 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition { @Override public List getSecondLineTooltip(int slot) { - return ImmutableList.of(Lang.translateDirect("generic.duration")); + return ImmutableList.of(CreateLang.translateDirect("generic.duration")); } public int getValue() { @@ -93,7 +93,7 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition { @OnlyIn(Dist.CLIENT) public void initConfigurationWidgets(ModularGuiLineBuilder builder) { builder.addScrollInput(0, 31, (i, l) -> { - i.titled(Lang.translateDirect("generic.duration")) + i.titled(CreateLang.translateDirect("generic.duration")) .withShiftStep(15) .withRange(0, 121); i.lockedTooltipX = -15; @@ -102,7 +102,7 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition { builder.addSelectionScrollInput(36, 85, (i, l) -> { i.forOptions(TimeUnit.translatedOptions()) - .titled(Lang.translateDirect("generic.timeUnit")); + .titled(CreateLang.translateDirect("generic.timeUnit")); }, "TimeUnit"); } @@ -115,8 +115,8 @@ public abstract class TimedWaitCondition extends ScheduleWaitCondition { (int) (showInMinutes ? Math.floor(ticksUntilDeparture / (20 * 60f)) : Math.ceil(ticksUntilDeparture / 100f) * 5); String key = "generic." + (showInMinutes ? num == 1 ? "daytime.minute" : "unit.minutes" : num == 1 ? "daytime.second" : "unit.seconds"); - return Lang.translateDirect("schedule.condition." + getId().getPath() + ".status", - Components.literal(num + " ").append(Lang.translateDirect(key))); + return CreateLang.translateDirect("schedule.condition." + getId().getPath() + ".status", + Component.literal(num + " ").append(CreateLang.translateDirect(key))); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeThrottleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeThrottleInstruction.java index 1fd5a7f708..597c8e1f58 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeThrottleInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeThrottleInstruction.java @@ -2,19 +2,24 @@ package com.simibubi.create.content.trains.schedule.destination; import java.util.List; +import javax.annotation.Nullable; + import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; +import com.simibubi.create.content.trains.graph.DiscoveredPath; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime.State; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -24,14 +29,14 @@ public class ChangeThrottleInstruction extends ScheduleInstruction { super(); data.putInt("Value", 100); } - + @Override public Pair getSummary() { return Pair.of(icon(), formatted()); } private MutableComponent formatted() { - return Components.literal(intData("Value") + "%"); + return Component.literal(intData("Value") + "%"); } @Override @@ -51,7 +56,7 @@ public class ChangeThrottleInstruction extends ScheduleInstruction { @Override public List getTitleAs(String type) { - return ImmutableList.of(Lang + return ImmutableList.of(CreateLang .translateDirect("schedule." + type + "." + getId().getPath() + ".summary", formatted().withStyle(ChatFormatting.WHITE)) .withStyle(ChatFormatting.GOLD)); @@ -63,7 +68,7 @@ public class ChangeThrottleInstruction extends ScheduleInstruction { builder.addScrollInput(0, 50, (si, l) -> { si.withRange(5, 101) .withStepFunction(c -> c.shift ? 25 : 5) - .titled(Lang.translateDirect("schedule.instruction.throttle_edit_box")); + .titled(CreateLang.translateDirect("schedule.instruction.throttle_edit_box")); l.withSuffix("%"); }, "Value"); } @@ -78,9 +83,18 @@ public class ChangeThrottleInstruction extends ScheduleInstruction { @Override public List getSecondLineTooltip(int slot) { - return ImmutableList.of(Lang.translateDirect("schedule.instruction.throttle_edit_box"), - Lang.translateDirect("schedule.instruction.throttle_edit_box_1") + return ImmutableList.of(CreateLang.translateDirect("schedule.instruction.throttle_edit_box"), + CreateLang.translateDirect("schedule.instruction.throttle_edit_box_1") .withStyle(ChatFormatting.GRAY)); } + @Override + @Nullable + public DiscoveredPath start(ScheduleRuntime runtime, Level level) { + runtime.train.throttle = getThrottle(); + runtime.state = State.PRE_TRANSIT; + runtime.currentEntry++; + return null; + } + } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeTitleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeTitleInstruction.java index 2265014f12..a281648ca2 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeTitleInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeTitleInstruction.java @@ -2,23 +2,28 @@ package com.simibubi.create.content.trains.schedule.destination; import java.util.List; +import javax.annotation.Nullable; + import com.google.common.collect.ImmutableList; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.content.trains.graph.DiscoveredPath; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime.State; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; public class ChangeTitleInstruction extends TextScheduleInstruction { @Override public Pair getSummary() { - return Pair.of(icon(), Components.literal(getLabelText())); + return Pair.of(icon(), Component.literal(getLabelText())); } @Override @@ -35,7 +40,7 @@ public class ChangeTitleInstruction extends TextScheduleInstruction { public boolean supportsConditions() { return false; } - + public String getScheduleTitle() { return getLabelText(); } @@ -46,11 +51,20 @@ public class ChangeTitleInstruction extends TextScheduleInstruction { @Override public List getSecondLineTooltip(int slot) { - return ImmutableList.of(Lang.translateDirect("schedule.instruction.name_edit_box"), - Lang.translateDirect("schedule.instruction.name_edit_box_1") + return ImmutableList.of(CreateLang.translateDirect("schedule.instruction.name_edit_box"), + CreateLang.translateDirect("schedule.instruction.name_edit_box_1") .withStyle(ChatFormatting.GRAY), - Lang.translateDirect("schedule.instruction.name_edit_box_2") + CreateLang.translateDirect("schedule.instruction.name_edit_box_2") .withStyle(ChatFormatting.DARK_GRAY)); } + @Override + @Nullable + public DiscoveredPath start(ScheduleRuntime runtime, Level level) { + runtime.currentTitle = getScheduleTitle(); + runtime.state = State.PRE_TRANSIT; + runtime.currentEntry++; + return null; + } + } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/DeliverPackagesInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DeliverPackagesInstruction.java new file mode 100644 index 0000000000..b9ceaedec4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DeliverPackagesInstruction.java @@ -0,0 +1,127 @@ +package com.simibubi.create.content.trains.schedule.destination; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.DiscoveredPath; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime.State; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.station.GlobalStation.GlobalPackagePort; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.data.Pair; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.items.IItemHandlerModifiable; + +public class DeliverPackagesInstruction extends ScheduleInstruction { + + @Override + public Pair getSummary() { + return Pair.of(getSecondLineIcon(), CreateLang.translateDirect("schedule.instruction.package_delivery")); + } + + @Override + public ItemStack getSecondLineIcon() { + return AllBlocks.PACKAGE_POSTBOXES.get(DyeColor.WHITE) + .asStack(); + } + + @Override + public List getTitleAs(String type) { + return ImmutableList.of(CreateLang.translate("schedule.instruction.package_delivery.summary") + .style(ChatFormatting.GOLD) + .component(), + CreateLang.translateDirect("schedule.instruction.package_delivery.summary_1") + .withStyle(ChatFormatting.GRAY), + CreateLang.translateDirect("schedule.instruction.package_delivery.summary_2") + .withStyle(ChatFormatting.GRAY)); + } + + @Override + public ResourceLocation getId() { + return Create.asResource("package_delivery"); + } + + @Override + public boolean supportsConditions() { + return true; + } + + @Override + @Nullable + public DiscoveredPath start(ScheduleRuntime runtime, Level level) { + boolean anyMatch = false; + String firstPackage = null; + ArrayList validStations = new ArrayList<>(); + Train train = runtime.train; + + if (!train.hasForwardConductor() && !train.hasBackwardConductor()) { + train.status.missingConductor(); + runtime.startCooldown(); + return null; + } + + for (Carriage carriage : train.carriages) { + IItemHandlerModifiable carriageInventory = carriage.storage.getAllItems(); + if (carriageInventory == null) + continue; + + // Export to station + for (int slot = 0; slot < carriageInventory.getSlots(); slot++) { + ItemStack stack = carriageInventory.getStackInSlot(slot); + if (!PackageItem.isPackage(stack)) + continue; + if (firstPackage == null) + firstPackage = PackageItem.getAddress(stack); + for (GlobalStation globalStation : train.graph.getPoints(EdgePointType.STATION)) { + for (Entry port : globalStation.connectedPorts.entrySet()) { + if (!PackageItem.matchAddress(stack, port.getValue().address)) + continue; + anyMatch = true; + validStations.add(globalStation); + break; + } + } + } + } + + if (validStations.isEmpty()) { + if (firstPackage != null) { + train.status.failedPackageNoTarget(firstPackage); + runtime.startCooldown(); + } else { + runtime.state = State.PRE_TRANSIT; + runtime.currentEntry++; + } + return null; + } + + DiscoveredPath best = train.navigation.findPathTo(validStations, Double.MAX_VALUE); + if (best == null) { + if (anyMatch) + train.status.failedNavigation(); + runtime.startCooldown(); + return null; + } + + return best; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/DestinationInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DestinationInstruction.java index ada430049d..ec7ed7d40d 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/destination/DestinationInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DestinationInstruction.java @@ -1,21 +1,31 @@ package com.simibubi.create.content.trains.schedule.destination; +import java.util.ArrayList; import java.util.List; +import java.util.regex.PatternSyntaxException; + +import javax.annotation.Nullable; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.DiscoveredPath; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Glob; +import net.createmod.catnip.data.Pair; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.components.EditBox; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -23,7 +33,7 @@ public class DestinationInstruction extends TextScheduleInstruction { @Override public Pair getSummary() { - return Pair.of(AllBlocks.TRACK_STATION.asStack(), Components.literal(getLabelText())); + return Pair.of(AllBlocks.TRACK_STATION.asStack(), Component.literal(getLabelText())); } @Override @@ -44,22 +54,19 @@ public class DestinationInstruction extends TextScheduleInstruction { public String getFilter() { return getLabelText(); } - + public String getFilterForRegex() { - String filter = getFilter(); - if (filter.isBlank()) - return filter; - return "\\Q" + filter.replace("*", "\\E.*\\Q") + "\\E"; + return Glob.toRegexPattern(getFilter(), ""); } @Override public List getSecondLineTooltip(int slot) { - return ImmutableList.of(Lang.translateDirect("schedule.instruction.filter_edit_box"), - Lang.translateDirect("schedule.instruction.filter_edit_box_1") + return ImmutableList.of(CreateLang.translateDirect("schedule.instruction.filter_edit_box"), + CreateLang.translateDirect("schedule.instruction.filter_edit_box_1") .withStyle(ChatFormatting.GRAY), - Lang.translateDirect("schedule.instruction.filter_edit_box_2") + CreateLang.translateDirect("schedule.instruction.filter_edit_box_2") .withStyle(ChatFormatting.DARK_GRAY), - Lang.translateDirect("schedule.instruction.filter_edit_box_3") + CreateLang.translateDirect("schedule.instruction.filter_edit_box_3") .withStyle(ChatFormatting.DARK_GRAY)); } @@ -69,4 +76,40 @@ public class DestinationInstruction extends TextScheduleInstruction { box.setFilter(s -> StringUtils.countMatches(s, '*') <= 3); } -} \ No newline at end of file + @Override + @Nullable + public DiscoveredPath start(ScheduleRuntime runtime, Level level) { + String regex = getFilterForRegex(); + boolean anyMatch = false; + ArrayList validStations = new ArrayList<>(); + Train train = runtime.train; + + if (!train.hasForwardConductor() && !train.hasBackwardConductor()) { + train.status.missingConductor(); + runtime.startCooldown(); + return null; + } + + try { + for (GlobalStation globalStation : train.graph.getPoints(EdgePointType.STATION)) { + if (!globalStation.name.matches(regex)) + continue; + anyMatch = true; + validStations.add(globalStation); + } + } catch (PatternSyntaxException ignored) {} + + DiscoveredPath best = train.navigation.findPathTo(validStations, Double.MAX_VALUE); + if (best == null) { + if (anyMatch) + train.status.failedNavigation(); + else + train.status.failedNavigationNoTarget(getFilter()); + runtime.startCooldown(); + return null; + } + + return best; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/FetchPackagesInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/FetchPackagesInstruction.java new file mode 100644 index 0000000000..86c62bec9a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/FetchPackagesInstruction.java @@ -0,0 +1,165 @@ +package com.simibubi.create.content.trains.schedule.destination; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.regex.PatternSyntaxException; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.box.PackageStyles; +import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlockEntity; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.DiscoveredPath; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime.State; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.station.GlobalStation.GlobalPackagePort; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.data.Glob; +import net.createmod.catnip.data.Pair; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.IItemHandlerModifiable; + +public class FetchPackagesInstruction extends TextScheduleInstruction { + + @Override + public Pair getSummary() { + return Pair.of(getSecondLineIcon(), CreateLang.translateDirect("schedule.instruction.package_retrieval")); + } + + @Override + public List getTitleAs(String type) { + return ImmutableList.of(CreateLang.translate("schedule.instruction.package_retrieval.summary") + .style(ChatFormatting.GOLD) + .component(), CreateLang.translateDirect("generic.in_quotes", Component.literal(getLabelText())), + CreateLang.translateDirect("schedule.instruction.package_retrieval.summary_1") + .withStyle(ChatFormatting.GRAY), + CreateLang.translateDirect("schedule.instruction.package_retrieval.summary_2") + .withStyle(ChatFormatting.GRAY)); + } + + @Override + public ItemStack getSecondLineIcon() { + return PackageStyles.getDefaultBox(); + } + + public String getFilter() { + return getLabelText(); + } + + public String getFilterForRegex() { + if (getFilter().isBlank()) + return Glob.toRegexPattern("*", ""); + return Glob.toRegexPattern(getFilter(), ""); + } + + @Override + public List getSecondLineTooltip(int slot) { + return ImmutableList.of(CreateLang.translateDirect("schedule.instruction.address_filter_edit_box"), + CreateLang.translateDirect("schedule.instruction.address_filter_edit_box_1") + .withStyle(ChatFormatting.GRAY), + CreateLang.translateDirect("schedule.instruction.address_filter_edit_box_2") + .withStyle(ChatFormatting.DARK_GRAY), + CreateLang.translateDirect("schedule.instruction.address_filter_edit_box_3") + .withStyle(ChatFormatting.DARK_GRAY)); + } + + @Override + @OnlyIn(Dist.CLIENT) + protected void modifyEditBox(EditBox box) { + box.setFilter(s -> StringUtils.countMatches(s, '*') <= 3); + } + + @Override + public ResourceLocation getId() { + return Create.asResource("package_retrieval"); + } + + @Override + public boolean supportsConditions() { + return false; + } + + @Override + public DiscoveredPath start(ScheduleRuntime runtime, Level level) { + MinecraftServer server = level.getServer(); + if (server == null) + return null; + + String regex = getFilterForRegex(); + boolean anyMatch = false; + ArrayList validStations = new ArrayList<>(); + Train train = runtime.train; + + if (!train.hasForwardConductor() && !train.hasBackwardConductor()) { + train.status.missingConductor(); + runtime.startCooldown(); + return null; + } + + for (GlobalStation globalStation : train.graph.getPoints(EdgePointType.STATION)) { + ServerLevel dimLevel = server.getLevel(globalStation.blockEntityDimension); + if (dimLevel == null) + continue; + + for (Entry entry : globalStation.connectedPorts.entrySet()) { + GlobalPackagePort port = entry.getValue(); + BlockPos pos = entry.getKey(); + + IItemHandlerModifiable postboxInventory = port.offlineBuffer; + if (dimLevel.isLoaded(pos) && dimLevel.getBlockEntity(pos) instanceof PostboxBlockEntity ppbe) + postboxInventory = ppbe.inventory; + + for (int slot = 0; slot < postboxInventory.getSlots(); slot++) { + ItemStack stack = postboxInventory.getStackInSlot(slot); + if (!PackageItem.isPackage(stack)) + continue; + if (PackageItem.matchAddress(stack, port.address)) + continue; + try { + if (!PackageItem.getAddress(stack) + .matches(regex)) + continue; + anyMatch = true; + validStations.add(globalStation); + } catch (PatternSyntaxException ignored) { + } + } + } + } + + if (validStations.isEmpty()) { + runtime.startCooldown(); + runtime.state = State.PRE_TRANSIT; + runtime.currentEntry++; + return null; + } + + DiscoveredPath best = train.navigation.findPathTo(validStations, Double.MAX_VALUE); + if (best == null) { + if (anyMatch) + train.status.failedNavigation(); + runtime.startCooldown(); + return null; + } + + return best; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/ScheduleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ScheduleInstruction.java index 2dd9571ca7..4a9082da0b 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/destination/ScheduleInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ScheduleInstruction.java @@ -2,18 +2,26 @@ package com.simibubi.create.content.trains.schedule.destination; import java.util.function.Supplier; +import javax.annotation.Nullable; + import com.simibubi.create.Create; +import com.simibubi.create.content.trains.graph.DiscoveredPath; import com.simibubi.create.content.trains.schedule.Schedule; import com.simibubi.create.content.trains.schedule.ScheduleDataEntry; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; public abstract class ScheduleInstruction extends ScheduleDataEntry { public abstract boolean supportsConditions(); + @Nullable + public abstract DiscoveredPath start(ScheduleRuntime runtime, Level level); + public final CompoundTag write() { CompoundTag tag = new CompoundTag(); CompoundTag dataCopy = data.copy(); diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/TextScheduleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/TextScheduleInstruction.java index c18ca2702b..eda4b90b11 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/destination/TextScheduleInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/TextScheduleInstruction.java @@ -4,8 +4,7 @@ import java.util.List; import com.google.common.collect.ImmutableList; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.components.EditBox; @@ -21,8 +20,8 @@ public abstract class TextScheduleInstruction extends ScheduleInstruction { @Override public List getTitleAs(String type) { - return ImmutableList.of(Lang.translateDirect("schedule." + type + "." + getId().getPath() + ".summary") - .withStyle(ChatFormatting.GOLD), Lang.translateDirect("generic.in_quotes", Components.literal(getLabelText()))); + return ImmutableList.of(CreateLang.translateDirect("schedule." + type + "." + getId().getPath() + ".summary") + .withStyle(ChatFormatting.GOLD), CreateLang.translateDirect("generic.in_quotes", Component.literal(getLabelText()))); } @Override diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/hat/TrainHatArmorLayer.java b/src/main/java/com/simibubi/create/content/trains/schedule/hat/TrainHatArmorLayer.java deleted file mode 100644 index dd30e409a2..0000000000 --- a/src/main/java/com/simibubi/create/content/trains/schedule/hat/TrainHatArmorLayer.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.simibubi.create.content.trains.schedule.hat; - -import java.util.ArrayList; -import java.util.List; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllPartialModels; -import com.simibubi.create.content.contraptions.Contraption; -import com.simibubi.create.content.trains.entity.CarriageContraption; -import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.foundation.mixin.accessor.AgeableListModelAccessor; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.Couple; - -import dev.engine_room.flywheel.lib.transform.TransformStack; -import net.minecraft.client.model.AgeableListModel; -import net.minecraft.client.model.EntityModel; -import net.minecraft.client.model.HierarchicalModel; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.model.geom.ModelPart.Cube; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.Sheets; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.client.renderer.entity.LivingEntityRenderer; -import net.minecraft.client.renderer.entity.RenderLayerParent; -import net.minecraft.client.renderer.entity.layers.RenderLayer; -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; - -public class TrainHatArmorLayer> extends RenderLayer { - - public TrainHatArmorLayer(RenderLayerParent renderer) { - super(renderer); - } - - @Override - public void render(PoseStack ms, MultiBufferSource buffer, int light, LivingEntity entity, float limbSwing, float limbSwingAmount, - float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { - if (!shouldRenderOn(entity)) - return; - - M entityModel = getParentModel(); - ms.pushPose(); - - var msr = TransformStack.of(ms); - TrainHatInfo info = TrainHatInfoReloadListener.getHatInfoFor(entity.getType()); - List partsToHead = new ArrayList<>(); - - if (entityModel instanceof AgeableListModel model) { - if (model.young) { - if (model.scaleHead) { - float f = 1.5F / model.babyHeadScale; - ms.scale(f, f, f); - } - ms.translate(0.0D, model.babyYHeadOffset / 16.0F, model.babyZHeadOffset / 16.0F); - } - - ModelPart head = getHeadPart(model); - if (head != null) { - partsToHead.addAll(TrainHatInfo.getAdjustedPart(info, head, "")); - } - } else if (entityModel instanceof HierarchicalModel model) { - partsToHead.addAll(TrainHatInfo.getAdjustedPart(info, model.root(), "head")); - } - - if (!partsToHead.isEmpty()) { - partsToHead.forEach(part -> part.translateAndRotate(ms)); - - ModelPart lastChild = partsToHead.get(partsToHead.size() - 1); - if (!lastChild.isEmpty()) { - Cube cube = lastChild.cubes.get(Mth.clamp(info.cubeIndex(), 0, lastChild.cubes.size() - 1)); - ms.translate(info.offset().x() / 16.0F, (cube.minY - cube.maxY + info.offset().y()) / 16.0F, info.offset().z() / 16.0F); - float max = Math.max(cube.maxX - cube.minX, cube.maxZ - cube.minZ) / 8.0F * info.scale(); - ms.scale(max, max, max); - } - - ms.scale(1, -1, -1); - ms.translate(0, -2.25F / 16.0F, 0); - msr.rotateXDegrees(-8.5F); - BlockState air = Blocks.AIR.defaultBlockState(); - CachedBufferer.partial(AllPartialModels.TRAIN_HAT, air) - .disableDiffuse() - .light(light) - .renderInto(ms, buffer.getBuffer(Sheets.cutoutBlockSheet())); - } - - ms.popPose(); - } - - private boolean shouldRenderOn(LivingEntity entity) { - if (entity == null) - return false; - if (entity.getPersistentData() - .contains("TrainHat")) - return true; - if (!entity.isPassenger()) - return false; - if (entity instanceof Player p) { - ItemStack headItem = p.getItemBySlot(EquipmentSlot.HEAD); - if (!headItem.isEmpty()) - return false; - } - Entity vehicle = entity.getVehicle(); - if (!(vehicle instanceof CarriageContraptionEntity cce)) - return false; - if (!cce.hasSchedule() && !(entity instanceof Player)) - return false; - Contraption contraption = cce.getContraption(); - if (!(contraption instanceof CarriageContraption cc)) - return false; - BlockPos seatOf = cc.getSeatOf(entity.getUUID()); - if (seatOf == null) - return false; - Couple validSides = cc.conductorSeats.get(seatOf); - return validSides != null; - } - - public static void registerOnAll(EntityRenderDispatcher renderManager) { - for (EntityRenderer renderer : renderManager.getSkinMap() - .values()) - registerOn(renderer); - for (EntityRenderer renderer : renderManager.renderers.values()) - registerOn(renderer); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public static void registerOn(EntityRenderer entityRenderer) { - if (!(entityRenderer instanceof LivingEntityRenderer livingRenderer)) - return; - - EntityModel model = livingRenderer.getModel(); - - if (!(model instanceof HierarchicalModel) && !(model instanceof AgeableListModel)) - return; - - livingRenderer.addLayer((TrainHatArmorLayer) new TrainHatArmorLayer<>(livingRenderer)); - } - - private static ModelPart getHeadPart(AgeableListModel model) { - for (ModelPart part : ((AgeableListModelAccessor) model).create$callHeadParts()) - return part; - for (ModelPart part : ((AgeableListModelAccessor) model).create$callBodyParts()) - return part; - return null; - } - -} diff --git a/src/main/java/com/simibubi/create/content/trains/signal/EdgeGroupColor.java b/src/main/java/com/simibubi/create/content/trains/signal/EdgeGroupColor.java index 6d3d4c1f0b..31671675c3 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/EdgeGroupColor.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/EdgeGroupColor.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.trains.signal; -import com.simibubi.create.foundation.utility.Color; +import net.createmod.catnip.theme.Color; public enum EdgeGroupColor { @@ -13,9 +13,7 @@ public enum EdgeGroupColor { CYAN(0x6EDAD9), BROWN(0xA17C58), - WHITE(0xE5E1DC) - - ; + WHITE(0xE5E1DC); private Color color; private int mask; @@ -30,7 +28,7 @@ public enum EdgeGroupColor { return mask; return mask | this.mask; } - + public Color get() { return color; } @@ -38,12 +36,12 @@ public enum EdgeGroupColor { public static EdgeGroupColor getDefault() { return values()[0]; } - + public static EdgeGroupColor findNextAvailable(int mask) { EdgeGroupColor[] values = values(); - for (int i = 0; i < values.length; i++) { + for (EdgeGroupColor value : values) { if ((mask & 1) == 0) - return values[i]; + return value; mask = mask >> 1; } return WHITE; diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalBlock.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlock.java index 4d660eac67..cf76148d16 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/SignalBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlock.java @@ -5,8 +5,9 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -112,10 +113,10 @@ public class SignalBlock extends Block implements IBE, IWrenc if (signal != null) { signal.cycleSignalType(pos); if (player != null) - player.displayClientMessage(Lang.translateDirect("track_signal.mode_change." + signal.getTypeFor(pos) + player.displayClientMessage(CreateLang.translateDirect("track_signal.mode_change." + signal.getTypeFor(pos) .getSerializedName()), true); } else if (player != null) - player.displayClientMessage(Lang.translateDirect("track_signal.cannot_change_mode"), true); + player.displayClientMessage(CreateLang.translateDirect("track_signal.cannot_change_mode"), true); }); return InteractionResult.SUCCESS; } diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlockEntity.java index bfae67e6fa..79b23434c3 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/SignalBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlockEntity.java @@ -4,22 +4,23 @@ import java.util.List; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.trains.graph.EdgePointType; import com.simibubi.create.content.trains.signal.SignalBlock.SignalType; import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; -public class SignalBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { +public class SignalBlockEntity extends SmartBlockEntity implements TransformableBlockEntity { public static enum OverlayState { RENDER, SKIP, DUAL @@ -109,7 +110,7 @@ public class SignalBlockEntity extends SmartBlockEntity implements ITransformabl boundary.updateBlockEntityPower(this); notifyUpdate(); }); - + blockState.getOptionalValue(SignalBlock.TYPE) .ifPresent(stateType -> { SignalType targetType = boundary.getTypeFor(worldPosition); @@ -160,8 +161,8 @@ public class SignalBlockEntity extends SmartBlockEntity implements ITransformabl } @Override - public void transform(StructureTransform transform) { - edgePoint.transform(transform); + public void transform(BlockEntity be, StructureTransform transform) { + edgePoint.transform(be, transform); } } diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalBoundary.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalBoundary.java index c612630789..72469e7b5e 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/SignalBoundary.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalBoundary.java @@ -15,10 +15,10 @@ import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.content.trains.signal.SignalBlock.SignalType; import com.simibubi.create.content.trains.signal.SignalBlockEntity.OverlayState; import com.simibubi.create.content.trains.signal.SignalBlockEntity.SignalState; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroup.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroup.java index 9f38ffb71b..1f6bb55679 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroup.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroup.java @@ -13,8 +13,8 @@ import org.apache.commons.lang3.mutable.MutableInt; import com.google.common.base.Predicates; import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -29,7 +29,7 @@ public class SignalEdgeGroup { public Map intersecting; public Set intersectingResolved; public Set adjacent; - + public boolean fallbackGroup; public SignalEdgeGroup(UUID id) { @@ -40,7 +40,7 @@ public class SignalEdgeGroup { intersectingResolved = new HashSet<>(); color = EdgeGroupColor.getDefault(); } - + public SignalEdgeGroup asFallback() { fallbackGroup = true; return this; diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalPropagator.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalPropagator.java index 33e8b8509c..751d40849c 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/SignalPropagator.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalPropagator.java @@ -20,9 +20,10 @@ import com.simibubi.create.content.trains.graph.TrackGraph; import com.simibubi.create.content.trains.graph.TrackGraphSync; import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.content.trains.graph.TrackNodeLocation; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; + +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; public class SignalPropagator { diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalRenderer.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalRenderer.java index 45ec840e5b..3b62564d6f 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/SignalRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalRenderer.java @@ -8,10 +8,11 @@ import com.simibubi.create.content.trains.track.ITrackBlock; import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.render.CachedBuffers; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; @@ -33,10 +34,11 @@ public class SignalRenderer extends SafeBlockEntityRenderer { float renderTime = AnimationTickHolder.getRenderTime(be.getLevel()); if (signalState.isRedLight(renderTime)) - CachedBufferer.partial(AllPartialModels.SIGNAL_ON, blockState) + CachedBuffers.partial(AllPartialModels.SIGNAL_ON, blockState) + .light(LightTexture.FULL_BLOCK) .renderInto(ms, buffer.getBuffer(RenderType.solid())); else - CachedBufferer.partial(AllPartialModels.SIGNAL_OFF, blockState) + CachedBuffers.partial(AllPartialModels.SIGNAL_OFF, blockState) .light(light) .renderInto(ms, buffer.getBuffer(RenderType.solid())); diff --git a/src/main/java/com/simibubi/create/content/trains/signal/TrackEdgePoint.java b/src/main/java/com/simibubi/create/content/trains/signal/TrackEdgePoint.java index 5b9e1c5e2a..720e759260 100644 --- a/src/main/java/com/simibubi/create/content/trains/signal/TrackEdgePoint.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/TrackEdgePoint.java @@ -11,8 +11,8 @@ import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Couple; +import net.createmod.catnip.data.Couple; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; diff --git a/src/main/java/com/simibubi/create/content/trains/station/AbstractStationScreen.java b/src/main/java/com/simibubi/create/content/trains/station/AbstractStationScreen.java index d97417bd02..238f567689 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/AbstractStationScreen.java +++ b/src/main/java/com/simibubi/create/content/trains/station/AbstractStationScreen.java @@ -9,16 +9,16 @@ import com.simibubi.create.compat.computercraft.ComputerScreen; import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.entity.TrainIconType; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.utility.Components; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.gui.AbstractSimiScreen; +import net.createmod.catnip.gui.element.GuiGameElement; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.world.level.block.state.properties.BlockStateProperties; public abstract class AbstractStationScreen extends AbstractSimiScreen { @@ -43,17 +43,18 @@ public abstract class AbstractStationScreen extends AbstractSimiScreen { @Override protected void init() { if (blockEntity.computerBehaviour.hasAttachedComputer()) - minecraft.setScreen(new ComputerScreen(title, () -> Components.literal(station.name), - this::renderAdditional, this, blockEntity.computerBehaviour::hasAttachedComputer)); + minecraft.setScreen(new ComputerScreen(title, () -> + Component.literal(station.name), + this::renderAdditional, this, blockEntity.computerBehaviour::hasAttachedComputer)); - setWindowSize(background.width, background.height); + setWindowSize(background.getWidth(), background.getHeight()); super.init(); clearWidgets(); int x = guiLeft; int y = guiTop; - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton = new IconButton(x + background.getWidth() - 33, y + background.getHeight() - 24, AllIcons.I_CONFIRM); confirmButton.withCallback(this::onClose); addRenderableWidget(confirmButton); } @@ -83,8 +84,9 @@ public abstract class AbstractStationScreen extends AbstractSimiScreen { super.tick(); if (blockEntity.computerBehaviour.hasAttachedComputer()) - minecraft.setScreen(new ComputerScreen(title, () -> Components.literal(station.name), - this::renderAdditional, this, blockEntity.computerBehaviour::hasAttachedComputer)); + minecraft.setScreen(new ComputerScreen(title, () -> + Component.literal(station.name), + this::renderAdditional, this, blockEntity.computerBehaviour::hasAttachedComputer)); } @Override @@ -101,7 +103,7 @@ public abstract class AbstractStationScreen extends AbstractSimiScreen { ms.pushPose(); var msr = TransformStack.of(ms); msr.pushPose() - .translate(guiLeft + background.width + 4, guiTop + background.height + 4, 100) + .translate(guiLeft + background.getWidth() + 4, guiTop + background.getHeight() + 4, 100) .scale(40) .rotateXDegrees(-22) .rotateYDegrees(63); diff --git a/src/main/java/com/simibubi/create/content/trains/station/AssemblyScreen.java b/src/main/java/com/simibubi/create/content/trains/station/AssemblyScreen.java index c8246bcf17..774afcf9c1 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/AssemblyScreen.java +++ b/src/main/java/com/simibubi/create/content/trains/station/AssemblyScreen.java @@ -13,7 +13,7 @@ import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.ScrollInput; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.model.baked.PartialModel; import net.minecraft.client.gui.GuiGraphics; @@ -38,18 +38,18 @@ public class AssemblyScreen extends AbstractStationScreen { super.init(); int x = guiLeft; int y = guiTop; - int by = y + background.height - 24; + int by = y + background.getHeight() - 24; Renderable widget = renderables.get(0); if (widget instanceof IconButton ib) { ib.setIcon(AllIcons.I_PRIORITY_VERY_LOW); - ib.setToolTip(Lang.translateDirect("station.close")); + ib.setToolTip(CreateLang.translateDirect("station.close")); } iconTypes = TrainIconType.REGISTRY.keySet() .stream() .toList(); - iconTypeScroll = new ScrollInput(x + 4, y + 17, 162, 14).titled(Lang.translateDirect("station.icon_type")); + iconTypeScroll = new ScrollInput(x + 4, y + 17, 162, 14).titled(CreateLang.translateDirect("station.icon_type")); iconTypeScroll.withRange(0, iconTypes.size()); iconTypeScroll.withStepFunction(ctx -> -iconTypeScroll.standardStep() .apply(ctx)); @@ -63,7 +63,7 @@ public class AssemblyScreen extends AbstractStationScreen { toggleAssemblyButton = new WideIconButton(x + 94, by, AllGuiTextures.I_ASSEMBLE_TRAIN); toggleAssemblyButton.active = false; - toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train")); + toggleAssemblyButton.setToolTip(CreateLang.translateDirect("station.assemble_train")); toggleAssemblyButton.withCallback(() -> { AllPackets.getChannel() .sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos())); @@ -71,7 +71,7 @@ public class AssemblyScreen extends AbstractStationScreen { quitAssembly = new IconButton(x + 73, by, AllIcons.I_DISABLE); quitAssembly.active = true; - quitAssembly.setToolTip(Lang.translateDirect("station.cancel")); + quitAssembly.setToolTip(CreateLang.translateDirect("station.cancel")); quitAssembly.withCallback(() -> { AllPackets.getChannel() .sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null)); @@ -105,7 +105,7 @@ public class AssemblyScreen extends AbstractStationScreen { displayedTrain = new WeakReference<>(null); quitAssembly.active = true; iconTypeScroll.active = iconTypeScroll.visible = false; - toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train")); + toggleAssemblyButton.setToolTip(CreateLang.translateDirect("station.assemble_train")); toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN); toggleAssemblyButton.withCallback(() -> { AllPackets.getChannel() @@ -124,36 +124,36 @@ public class AssemblyScreen extends AbstractStationScreen { int x = guiLeft; int y = guiTop; - MutableComponent header = Lang.translateDirect("station.assembly_title"); - graphics.drawString(font, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x0E2233, false); + MutableComponent header = CreateLang.translateDirect("station.assembly_title"); + graphics.drawString(font, header, x + background.getWidth() / 2 - font.width(header) / 2, y + 4, 0x0E2233, false); AssemblyException lastAssemblyException = blockEntity.lastException; if (lastAssemblyException != null) { - MutableComponent text = Lang.translateDirect("station.failed"); + MutableComponent text = CreateLang.translateDirect("station.failed"); graphics.drawString(font, text, x + 97 - font.width(text) / 2, y + 47, 0x775B5B, false); int offset = 0; if (blockEntity.failedCarriageIndex != -1) { - graphics.drawString(font, Lang.translateDirect("station.carriage_number", blockEntity.failedCarriageIndex), x + 30, + graphics.drawString(font, CreateLang.translateDirect("station.carriage_number", blockEntity.failedCarriageIndex), x + 30, y + 67, 0x7A7A7A, false); offset += 10; } graphics.drawWordWrap(font, lastAssemblyException.component, x + 30, y + 67 + offset, 134, 0x775B5B); offset += font.split(lastAssemblyException.component, 134) .size() * 9 + 5; - graphics.drawWordWrap(font, Lang.translateDirect("station.retry"), x + 30, y + 67 + offset, 134, 0x7A7A7A); + graphics.drawWordWrap(font, CreateLang.translateDirect("station.retry"), x + 30, y + 67 + offset, 134, 0x7A7A7A); return; } int bogeyCount = blockEntity.bogeyCount; - MutableComponent text = Lang.translateDirect( + MutableComponent text = CreateLang.translateDirect( bogeyCount == 0 ? "station.no_bogeys" : bogeyCount == 1 ? "station.one_bogey" : "station.more_bogeys", bogeyCount); graphics.drawString(font, text, x + 97 - font.width(text) / 2, y + 47, 0x7A7A7A, false); - graphics.drawWordWrap(font, Lang.translateDirect("station.how_to"), x + 28, y + 62, 134, 0x7A7A7A); - graphics.drawWordWrap(font, Lang.translateDirect("station.how_to_1"), x + 28, y + 94, 134, 0x7A7A7A); - graphics.drawWordWrap(font, Lang.translateDirect("station.how_to_2"), x + 28, y + 117, 138, 0x7A7A7A); + graphics.drawWordWrap(font, CreateLang.translateDirect("station.how_to"), x + 28, y + 62, 134, 0x7A7A7A); + graphics.drawWordWrap(font, CreateLang.translateDirect("station.how_to_1"), x + 28, y + 94, 134, 0x7A7A7A); + graphics.drawWordWrap(font, CreateLang.translateDirect("station.how_to_2"), x + 28, y + 117, 138, 0x7A7A7A); } @Override diff --git a/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java b/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java index bc025316c6..edcbbf6c4a 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java +++ b/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java @@ -1,28 +1,52 @@ package com.simibubi.create.content.trains.station; import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; import javax.annotation.Nullable; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlockEntity; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.graph.DimensionPalette; import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.content.trains.signal.SingleBlockEntityEdgePoint; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerLevel; +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 net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + public class GlobalStation extends SingleBlockEntityEdgePoint { public String name; public WeakReference nearestTrain; public boolean assembling; + public Map connectedPorts; + public GlobalStation() { name = "Track Station"; - nearestTrain = new WeakReference(null); + nearestTrain = new WeakReference<>(null); + connectedPorts = new HashMap<>(); } @Override @@ -38,7 +62,17 @@ public class GlobalStation extends SingleBlockEntityEdgePoint { super.read(nbt, migration, dimensions); name = nbt.getString("Name"); assembling = nbt.getBoolean("Assembling"); - nearestTrain = new WeakReference(null); + nearestTrain = new WeakReference<>(null); + + connectedPorts.clear(); + ListTag portList = nbt.getList("Ports", Tag.TAG_COMPOUND); + NBTHelper.iterateCompoundList(portList, c -> { + GlobalPackagePort port = new GlobalPackagePort(); + port.address = c.getString("Address"); + port.offlineBuffer.deserializeNBT(c.getCompound("OfflineBuffer")); + port.primed = c.getBoolean("Primed"); + connectedPorts.put(NbtUtils.readBlockPos(c.getCompound("Pos")), port); + }); } @Override @@ -55,6 +89,15 @@ public class GlobalStation extends SingleBlockEntityEdgePoint { super.write(nbt, dimensions); nbt.putString("Name", name); nbt.putBoolean("Assembling", assembling); + + nbt.put("Ports", NBTHelper.writeCompoundList(connectedPorts.entrySet(), e -> { + CompoundTag c = new CompoundTag(); + c.putString("Address", e.getValue().address); + c.put("OfflineBuffer", e.getValue().offlineBuffer.serializeNBT()); + c.putBoolean("Primed", e.getValue().primed); + c.put("Pos", NbtUtils.writeBlockPos(e.getKey())); + return c; + })); } @Override @@ -119,4 +162,97 @@ public class GlobalStation extends SingleBlockEntityEdgePoint { return this.nearestTrain.get(); } + // Package Port integration + public static class GlobalPackagePort { + public String address = ""; + public ItemStackHandler offlineBuffer = new ItemStackHandler(18); + public boolean primed = false; + } + + public void runMailTransfer() { + Train train = getPresentTrain(); + if (train == null || connectedPorts.isEmpty()) + return; + Level level = null; + + for (Carriage carriage : train.carriages) { + if (level == null) { + CarriageContraptionEntity entity = carriage.anyAvailableEntity(); + if (entity != null && entity.level() instanceof ServerLevel sl) + level = sl.getServer() + .getLevel(getBlockEntityDimension()); + } + + IItemHandlerModifiable carriageInventory = carriage.storage.getAllItems(); + if (carriageInventory == null) + continue; + + // Import from station + for (Entry entry : connectedPorts.entrySet()) { + GlobalPackagePort port = entry.getValue(); + BlockPos pos = entry.getKey(); + PostboxBlockEntity box = null; + + IItemHandlerModifiable postboxInventory = port.offlineBuffer; + if (level != null && level.isLoaded(pos) + && level.getBlockEntity(pos) instanceof PostboxBlockEntity ppbe) { + postboxInventory = ppbe.inventory; + box = ppbe; + } + + for (int slot = 0; slot < postboxInventory.getSlots(); slot++) { + ItemStack stack = postboxInventory.getStackInSlot(slot); + if (!PackageItem.isPackage(stack)) + continue; + if (PackageItem.matchAddress(stack, port.address)) + continue; + + ItemStack result = ItemHandlerHelper.insertItemStacked(carriageInventory, stack, false); + if (!result.isEmpty()) + continue; + + postboxInventory.setStackInSlot(slot, ItemStack.EMPTY); + Create.RAILWAYS.markTracksDirty(); + if (box != null) + box.spawnParticles(); + } + } + + // Export to station + for (int slot = 0; slot < carriageInventory.getSlots(); slot++) { + ItemStack stack = carriageInventory.getStackInSlot(slot); + if (!PackageItem.isPackage(stack)) + continue; + + for (Entry entry : connectedPorts.entrySet()) { + GlobalPackagePort port = entry.getValue(); + BlockPos pos = entry.getKey(); + PostboxBlockEntity box = null; + + if (!PackageItem.matchAddress(stack, port.address)) + continue; + + IItemHandler postboxInventory = port.offlineBuffer; + if (level != null && level.isLoaded(pos) + && level.getBlockEntity(pos) instanceof PostboxBlockEntity ppbe) { + postboxInventory = ppbe.inventory; + box = ppbe; + } + + ItemStack result = ItemHandlerHelper.insertItemStacked(postboxInventory, stack, false); + if (!result.isEmpty()) + continue; + + Create.RAILWAYS.markTracksDirty(); + carriageInventory.setStackInSlot(slot, ItemStack.EMPTY); + if (box != null) + box.spawnParticles(); + + break; + } + } + + } + } + } diff --git a/src/main/java/com/simibubi/create/content/trains/station/NoShadowFontWrapper.java b/src/main/java/com/simibubi/create/content/trains/station/NoShadowFontWrapper.java index 2e9cb1df32..41704724f1 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/NoShadowFontWrapper.java +++ b/src/main/java/com/simibubi/create/content/trains/station/NoShadowFontWrapper.java @@ -2,17 +2,15 @@ package com.simibubi.create.content.trains.station; import java.util.List; -import com.simibubi.create.foundation.mixin.accessor.FontAccessor; - import org.joml.Matrix4f; +import com.simibubi.create.foundation.mixin.accessor.FontAccessor; + import net.minecraft.client.StringSplitter; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.font.FontSet; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; -import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FormattedCharSequence; public class NoShadowFontWrapper extends Font { diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationBlock.java b/src/main/java/com/simibubi/create/content/trains/station/StationBlock.java index e766fc9223..56833d0f9a 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/StationBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationBlock.java @@ -9,8 +9,8 @@ import com.simibubi.create.content.logistics.depot.SharedDepotBlockMethods; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.gui.ScreenOpener; +import net.createmod.catnip.gui.ScreenOpener; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -67,7 +67,7 @@ public class StationBlock extends Block implements IBE, IWre updateWater(pLevel, pState, pCurrentPos); return pState; } - + @Override public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java index 1bcd2e0c3c..eae80b1e4b 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.trains.station; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -20,13 +21,16 @@ import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.content.contraptions.AssemblyException; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.decoration.slidingDoor.DoorControlBehaviour; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.logistics.depot.DepotBehaviour; +import com.simibubi.create.content.logistics.packagePort.PackagePortBlockEntity; +import com.simibubi.create.content.logistics.packagePort.postbox.PostboxBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity; @@ -46,21 +50,22 @@ import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.content.trains.graph.TrackNodeLocation.DiscoveredLocation; import com.simibubi.create.content.trains.schedule.Schedule; import com.simibubi.create.content.trains.schedule.ScheduleItem; +import com.simibubi.create.content.trains.station.GlobalStation.GlobalPackagePort; import com.simibubi.create.content.trains.track.ITrackBlock; import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.WorldAttached; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.WorldAttached; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; @@ -85,13 +90,14 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.network.PacketDistributor; -public class StationBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { +public class StationBlockEntity extends SmartBlockEntity implements TransformableBlockEntity { public TrackTargetingBehaviour edgePoint; public DoorControlBehaviour doorControls; @@ -114,6 +120,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab boolean flagFlipped; public Component lastDisassembledTrainName; + public int lastDisassembledMapColorIndex; public StationBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -147,6 +154,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab trainPresent = tag.getBoolean("ForceFlag"); if (tag.contains("PrevTrainName")) lastDisassembledTrainName = Component.Serializer.fromJson(tag.getString("PrevTrainName")); + lastDisassembledMapColorIndex = tag.getInt("PrevTrainColor"); if (!clientPacket) return; @@ -173,6 +181,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab if (lastDisassembledTrainName != null) tag.putString("PrevTrainName", Component.Serializer.toJson(lastDisassembledTrainName)); + tag.putInt("PrevTrainColor", lastDisassembledMapColorIndex); super.write(tag, clientPacket); @@ -277,7 +286,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab } public boolean trackClicked(Player player, InteractionHand hand, ITrackBlock track, BlockState state, - BlockPos pos) { + BlockPos pos) { refreshAssemblyInfo(); BoundingBox bb = assemblyAreas.get(level) .get(worldPosition); @@ -285,7 +294,8 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab return false; BlockPos up = BlockPos.containing(track.getUpNormal(level, pos, state)); - BlockPos down = BlockPos.containing(track.getUpNormal(level, pos, state).scale(-1)); + BlockPos down = BlockPos.containing(track.getUpNormal(level, pos, state) + .scale(-1)); int bogeyOffset = pos.distManhattan(edgePoint.getGlobalPosition()) - 1; if (!isValidBogeyOffset(bogeyOffset)) { @@ -302,14 +312,14 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab CompoundTag oldData = oldBE.getBogeyData(); BlockState newBlock = bogey.getNextSize(oldBE); if (newBlock.getBlock() == bogey) - player.displayClientMessage(Lang.translateDirect("bogey.style.no_other_sizes") + player.displayClientMessage(CreateLang.translateDirect("bogey.style.no_other_sizes") .withStyle(ChatFormatting.RED), true); level.setBlock(bogeyPos, newBlock, 3); BlockEntity newEntity = level.getBlockEntity(bogeyPos); if (!(newEntity instanceof AbstractBogeyBlockEntity newBE)) continue; newBE.setBogeyData(oldData); - bogey.playRotateSound(level, bogeyPos); + IWrenchable.playRotateSound(level, bogeyPos); return true; } } @@ -319,11 +329,13 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab ItemStack handItem = player.getItemInHand(hand); if (!player.isCreative() && !AllBlocks.RAILWAY_CASING.isIn(handItem)) { - player.displayClientMessage(Lang.translateDirect("train_assembly.requires_casing"), true); + player.displayClientMessage(CreateLang.translateDirect("train_assembly.requires_casing"), true); return false; } - boolean upsideDown = (player.getViewXRot(1.0F) < 0 && (track.getBogeyAnchor(level, pos, state)).getBlock() instanceof AbstractBogeyBlock bogey && bogey.canBeUpsideDown()); + boolean upsideDown = (player.getViewXRot(1.0F) < 0 + && (track.getBogeyAnchor(level, pos, state)).getBlock() instanceof AbstractBogeyBlock bogey + && bogey.canBeUpsideDown()); BlockPos targetPos = upsideDown ? pos.offset(down) : pos.offset(up); if (level.getBlockState(targetPos) @@ -339,7 +351,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab } bogeyAnchor = ProperWaterloggedBlock.withWater(level, bogeyAnchor, pos); level.setBlock(targetPos, bogeyAnchor, 3); - player.displayClientMessage(Lang.translateDirect("train_assembly.bogey_created"), true); + player.displayClientMessage(CreateLang.translateDirect("train_assembly.bogey_created"), true); SoundType soundtype = bogeyAnchor.getBlock() .getSoundType(state, level, pos, player); level.playSound(null, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, @@ -363,8 +375,9 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab if (!tryEnterAssemblyMode()) return false; - //Check the station wasn't destroyed - if (!(level.getBlockState(worldPosition).getBlock() instanceof StationBlock)) + // Check the station wasn't destroyed + if (!(level.getBlockState(worldPosition) + .getBlock() instanceof StationBlock)) return true; BlockState newState = getBlockState().setValue(StationBlock.ASSEMBLING, true); @@ -379,8 +392,9 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab if (train.navigation.destination != station) continue; - DiscoveredPath preferredPath = train.runtime.startCurrentInstruction(); - train.navigation.startNavigation(preferredPath != null ? preferredPath : train.navigation.findPathTo(station, Double.MAX_VALUE)); + DiscoveredPath preferredPath = train.runtime.startCurrentInstruction(level); + train.navigation.startNavigation( + preferredPath != null ? preferredPath : train.navigation.findPathTo(station, Double.MAX_VALUE)); } } @@ -412,7 +426,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab if (!train.disassemble(getAssemblyDirection(), trackPosition.above())) return false; - dropSchedule(sender); + dropSchedule(sender, train); return true; } @@ -443,21 +457,20 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab return true; } - public void dropSchedule(@Nullable ServerPlayer sender) { + public void dropSchedule(@Nullable ServerPlayer sender, @Nullable Train train) { GlobalStation station = getStation(); if (station == null) return; - - Train train = station.getPresentTrain(); if (train == null) return; ItemStack schedule = train.runtime.returnSchedule(); if (schedule.isEmpty()) return; - if (sender != null && sender.getMainHandItem().isEmpty()) { + if (sender != null && sender.getMainHandItem() + .isEmpty()) { sender.getInventory() - .placeItemBackInInventory(schedule); + .placeItemBackInInventory(schedule); return; } @@ -466,7 +479,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab itemEntity.setDeltaMovement(Vec3.ZERO); getLevel().addFreshEntity(itemEntity); } - + public void updateMapColor(int color) { GlobalStation station = getStation(); if (station == null) @@ -538,14 +551,17 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab } BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos)); - BlockPos upsideDownBogeyOffset = new BlockPos(bogeyOffset.getX(), bogeyOffset.getY()*-1, bogeyOffset.getZ()); + BlockPos upsideDownBogeyOffset = + new BlockPos(bogeyOffset.getX(), bogeyOffset.getY() * -1, bogeyOffset.getZ()); if (bogeyIndex < bogeyLocations.length) { - if (potentialBogeyState.getBlock() instanceof AbstractBogeyBlock bogey && !bogey.isUpsideDown(potentialBogeyState)) { + if (potentialBogeyState.getBlock() instanceof AbstractBogeyBlock bogey + && !bogey.isUpsideDown(potentialBogeyState)) { bogeyTypes[bogeyIndex] = bogey; bogeyLocations[bogeyIndex] = i; upsideDownBogeys[bogeyIndex] = false; bogeyIndex++; - } else if ((potentialBogeyState = level.getBlockState(upsideDownBogeyOffset.offset(currentPos))).getBlock() instanceof AbstractBogeyBlock bogey && bogey.isUpsideDown(potentialBogeyState)) { + } else if ((potentialBogeyState = level.getBlockState(upsideDownBogeyOffset.offset(currentPos))) + .getBlock() instanceof AbstractBogeyBlock bogey && bogey.isUpsideDown(potentialBogeyState)) { bogeyTypes[bogeyIndex] = bogey; bogeyLocations[bogeyIndex] = i; upsideDownBogeys[bogeyIndex] = true; @@ -621,7 +637,8 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab return; if (bogeyLocations[0] != 0) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.frontmost_bogey_at_station")), -1); + exception(new AssemblyException(CreateLang.translateDirect("train_assembly.frontmost_bogey_at_station")), + -1); return; } @@ -654,7 +671,8 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab break; if (loc - iPrevious < 3) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.bogeys_too_close", i, i + 1)), -1); + exception( + new AssemblyException(CreateLang.translateDirect("train_assembly.bogeys_too_close", i, i + 1)), -1); return; } @@ -730,7 +748,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab } if (points.size() == 0) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.no_bogeys")), -1); + exception(new AssemblyException(CreateLang.translateDirect("train_assembly.no_bogeys")), -1); return; } @@ -745,16 +763,19 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab spacing.add(bogeyLocations[bogeyIndex] - bogeyLocations[bogeyIndex - 1]); CarriageContraption contraption = new CarriageContraption(assemblyDirection); BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset); - BlockPos upsideDownBogeyPosOffset = trackPosition.offset(new BlockPos(bogeyOffset.getX(), bogeyOffset.getY() * -1, bogeyOffset.getZ())); + BlockPos upsideDownBogeyPosOffset = + trackPosition.offset(new BlockPos(bogeyOffset.getX(), bogeyOffset.getY() * -1, bogeyOffset.getZ())); try { int offset = bogeyLocations[bogeyIndex] + 1; - boolean success = contraption.assemble(level, upsideDownBogeys[bogeyIndex] ? upsideDownBogeyPosOffset.relative(assemblyDirection, offset) : bogeyPosOffset.relative(assemblyDirection, offset)); + boolean success = contraption.assemble(level, + upsideDownBogeys[bogeyIndex] ? upsideDownBogeyPosOffset.relative(assemblyDirection, offset) + : bogeyPosOffset.relative(assemblyDirection, offset)); atLeastOneForwardControls |= contraption.hasForwardControls(); contraption.setSoundQueueOffset(offset); if (!success) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.nothing_attached", bogeyIndex + 1)), - -1); + exception(new AssemblyException( + CreateLang.translateDirect("train_assembly.nothing_attached", bogeyIndex + 1)), -1); return; } } catch (AssemblyException e) { @@ -765,29 +786,32 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab AbstractBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex]; boolean firstBogeyIsUpsideDown = upsideDownBogeys[bogeyIndex]; BlockPos firstBogeyPos = contraption.anchor; - AbstractBogeyBlockEntity firstBogeyBlockEntity = (AbstractBogeyBlockEntity) level.getBlockEntity(firstBogeyPos); - CarriageBogey firstBogey = - new CarriageBogey(typeOfFirstBogey, firstBogeyIsUpsideDown, firstBogeyBlockEntity.getBogeyData(), points.get(pointIndex), points.get(pointIndex + 1)); + AbstractBogeyBlockEntity firstBogeyBlockEntity = + (AbstractBogeyBlockEntity) level.getBlockEntity(firstBogeyPos); + CarriageBogey firstBogey = new CarriageBogey(typeOfFirstBogey, firstBogeyIsUpsideDown, + firstBogeyBlockEntity.getBogeyData(), points.get(pointIndex), points.get(pointIndex + 1)); CarriageBogey secondBogey = null; BlockPos secondBogeyPos = contraption.getSecondBogeyPos(); int bogeySpacing = 0; if (secondBogeyPos != null) { if (bogeyIndex == bogeyCount - 1 || !secondBogeyPos - .equals((upsideDownBogeys[bogeyIndex + 1] ? upsideDownBogeyPosOffset : bogeyPosOffset).relative(assemblyDirection, bogeyLocations[bogeyIndex + 1] + 1))) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.not_connected_in_order")), + .equals((upsideDownBogeys[bogeyIndex + 1] ? upsideDownBogeyPosOffset : bogeyPosOffset) + .relative(assemblyDirection, bogeyLocations[bogeyIndex + 1] + 1))) { + exception( + new AssemblyException(CreateLang.translateDirect("train_assembly.not_connected_in_order")), contraptions.size() + 1); return; } AbstractBogeyBlockEntity secondBogeyBlockEntity = - (AbstractBogeyBlockEntity) level.getBlockEntity(secondBogeyPos); + (AbstractBogeyBlockEntity) level.getBlockEntity(secondBogeyPos); bogeySpacing = bogeyLocations[bogeyIndex + 1] - bogeyLocations[bogeyIndex]; - secondBogey = new CarriageBogey(bogeyTypes[bogeyIndex + 1], upsideDownBogeys[bogeyIndex + 1], secondBogeyBlockEntity.getBogeyData(), - points.get(pointIndex + 2), points.get(pointIndex + 3)); + secondBogey = new CarriageBogey(bogeyTypes[bogeyIndex + 1], upsideDownBogeys[bogeyIndex + 1], + secondBogeyBlockEntity.getBogeyData(), points.get(pointIndex + 2), points.get(pointIndex + 3)); bogeyIndex++; } else if (!typeOfFirstBogey.allowsSingleBogeyCarriage()) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.single_bogey_carriage")), + exception(new AssemblyException(CreateLang.translateDirect("train_assembly.single_bogey_carriage")), contraptions.size() + 1); return; } @@ -797,7 +821,7 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab } if (!atLeastOneForwardControls) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.no_controls")), -1); + exception(new AssemblyException(CreateLang.translateDirect("train_assembly.no_controls")), -1); return; } @@ -811,7 +835,9 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab if (lastDisassembledTrainName != null) { train.name = lastDisassembledTrainName; + train.mapColorIndex = lastDisassembledMapColorIndex; lastDisassembledTrainName = null; + lastDisassembledMapColorIndex = 0; } for (int i = 0; i < contraptions.size(); i++) { @@ -830,7 +856,8 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab train.collectInitiallyOccupiedSignalBlocks(); Create.RAILWAYS.addTrain(train); - AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainPacket(train, true)); + AllPackets.getChannel() + .send(PacketDistributor.ALL.noArg(), new TrainPacket(train, true)); clearException(); award(AllAdvancements.TRAIN); @@ -944,8 +971,44 @@ public class StationBlockEntity extends SmartBlockEntity implements ITransformab } @Override - public void transform(StructureTransform transform) { - edgePoint.transform(transform); + public void transform(BlockEntity be, StructureTransform transform) { + edgePoint.transform(be, transform); + } + + // Package port integration + + public void attachPackagePort(PackagePortBlockEntity ppbe) { + GlobalStation station = getStation(); + if (station == null || level.isClientSide) + return; + + if (ppbe instanceof PostboxBlockEntity pbe) + pbe.trackedGlobalStation = new WeakReference<>(station); + + if (station.connectedPorts.containsKey(ppbe.getBlockPos())) + restoreOfflineBuffer(ppbe, station.connectedPorts.get(ppbe.getBlockPos())); + + GlobalPackagePort globalPackagePort = new GlobalPackagePort(); + globalPackagePort.address = ppbe.addressFilter; + station.connectedPorts.put(ppbe.getBlockPos(), globalPackagePort); + } + + private void restoreOfflineBuffer(PackagePortBlockEntity ppbe, GlobalPackagePort globalPackagePort) { + if (!globalPackagePort.primed) + return; + for (int i = 0; i < globalPackagePort.offlineBuffer.getSlots(); i++) { + ppbe.inventory.setStackInSlot(i, globalPackagePort.offlineBuffer.getStackInSlot(i)); + globalPackagePort.offlineBuffer.setStackInSlot(i, ItemStack.EMPTY); + } + globalPackagePort.primed = false; + } + + public void removePackagePort(PackagePortBlockEntity ppbe) { + GlobalStation station = getStation(); + if (station == null) + return; + + station.connectedPorts.remove(ppbe.getBlockPos()); } } diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationEditPacket.java b/src/main/java/com/simibubi/create/content/trains/station/StationEditPacket.java index ca13624f99..abdb56db7f 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/StationEditPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationEditPacket.java @@ -92,9 +92,12 @@ public class StationEditPacket extends BlockEntityConfigurationPacket { - public StationRenderer(BlockEntityRendererProvider.Context context) {} + public StationRenderer(BlockEntityRendererProvider.Context context) { + } @Override protected void renderSafe(StationBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { + int light, int overlay) { BlockPos pos = be.getBlockPos(); TrackTargetingBehaviour target = be.edgePoint; @@ -43,7 +44,7 @@ public class StationRenderer extends SafeBlockEntityRenderer BlockState trackState = level.getBlockState(targetPosition); Block block = trackState.getBlock(); - if (!(block instanceof ITrackBlock)) + if (!(block instanceof ITrackBlock track)) return; GlobalStation station = be.getStation(); @@ -65,7 +66,6 @@ public class StationRenderer extends SafeBlockEntityRenderer renderFlag(AllPartialModels.STATION_ASSEMBLE, be, partialTicks, ms, buffer, light, overlay); - ITrackBlock track = (ITrackBlock) block; Direction direction = be.assemblyDirection; if (be.isVirtual() && be.bogeyLocations == null) @@ -99,7 +99,7 @@ public class StationRenderer extends SafeBlockEntityRenderer if (valid != -1) { int lightColor = LevelRenderer.getLightColor(level, currentPos); - SuperByteBuffer sbb = CachedBufferer.partial(assemblyOverlay, trackState); + SuperByteBuffer sbb = CachedBuffers.partial(assemblyOverlay, trackState); sbb.color(valid); sbb.light(lightColor); sbb.renderInto(ms, vb); @@ -112,10 +112,10 @@ public class StationRenderer extends SafeBlockEntityRenderer } public static void renderFlag(PartialModel flag, StationBlockEntity be, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { + MultiBufferSource buffer, int light, int overlay) { if (!be.resolveFlagAngle()) return; - SuperByteBuffer flagBB = CachedBufferer.partial(flag, be.getBlockState()); + SuperByteBuffer flagBB = CachedBuffers.partial(flag, be.getBlockState()); transformFlag(flagBB, be, partialTicks, be.flagYRot, be.flagFlipped); flagBB.translate(0.5f / 16, 0, 0) .rotateYDegrees(be.flagFlipped ? 0 : 180) @@ -125,7 +125,7 @@ public class StationRenderer extends SafeBlockEntityRenderer } public static void transformFlag(Transform flag, StationBlockEntity be, float partialTicks, int yRot, - boolean flipped) { + boolean flipped) { float value = be.flag.getValue(partialTicks); float progress = (float) (Math.pow(Math.min(value * 5, 1), 2)); if (be.flag.getChaseTarget() > 0 && !be.flag.settled() && progress == 1) { diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationScreen.java b/src/main/java/com/simibubi/create/content/trains/station/StationScreen.java index 70cd9e9989..af54849d30 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/StationScreen.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationScreen.java @@ -17,20 +17,20 @@ import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.entity.TrainIconType; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.gui.UIRenderHelper; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; @@ -46,7 +46,7 @@ public class StationScreen extends AbstractStationScreen { private int leavingAnimation; private LerpedFloat trainPosition; private DoorControl doorControl; - + private ScrollInput colorTypeScroll; private int messedWithColors; @@ -71,8 +71,8 @@ public class StationScreen extends AbstractStationScreen { Consumer onTextChanged; onTextChanged = s -> nameBox.setX(nameBoxX(s, nameBox)); - nameBox = new EditBox(new NoShadowFontWrapper(font), x + 23, y + 4, background.width - 20, 10, - Components.literal(station.name)); + nameBox = new EditBox(new NoShadowFontWrapper(font), x + 23, y + 4, background.getWidth() - 20, 10, + Component.literal(station.name)); nameBox.setBordered(false); nameBox.setMaxLength(25); nameBox.setTextColor(0x592424); @@ -104,23 +104,23 @@ public class StationScreen extends AbstractStationScreen { dropScheduleButton.withCallback(() -> AllPackets.getChannel() .sendToServer(StationEditPacket.dropSchedule(blockEntity.getBlockPos()))); addRenderableWidget(dropScheduleButton); - - colorTypeScroll = new ScrollInput(x + 166, y + 17, 22, 14).titled(Lang.translateDirect("station.train_map_color")); + + colorTypeScroll = new ScrollInput(x + 166, y + 17, 22, 14).titled(CreateLang.translateDirect("station.train_map_color")); colorTypeScroll.withRange(0, 16); - colorTypeScroll.withStepFunction(ctx -> -colorTypeScroll.standardStep() + colorTypeScroll.withStepFunction(ctx -> colorTypeScroll.standardStep() .apply(ctx)); colorTypeScroll.calling(s -> { Train train = displayedTrain.get(); if (train != null) { train.mapColorIndex = s; - messedWithColors = 10; + messedWithColors = 10; } }); colorTypeScroll.active = colorTypeScroll.visible = false; addRenderableWidget(colorTypeScroll); onTextChanged = s -> trainNameBox.setX(nameBoxX(s, trainNameBox)); - trainNameBox = new EditBox(font, x + 23, y + 47, background.width - 75, 10, Components.immutableEmpty()); + trainNameBox = new EditBox(font, x + 23, y + 47, background.getWidth() - 75, 10, CommonComponents.EMPTY); trainNameBox.setBordered(false); trainNameBox.setMaxLength(35); trainNameBox.setTextColor(0xC6C6C6); @@ -150,7 +150,7 @@ public class StationScreen extends AbstractStationScreen { .length()); trainNameBox.setHighlightPos(trainNameBox.getCursorPosition()); } - + if (messedWithColors > 0) { messedWithColors--; if (messedWithColors == 0) @@ -161,7 +161,7 @@ public class StationScreen extends AbstractStationScreen { updateAssemblyTooltip(blockEntity.edgePoint.isOnCurve() ? "no_assembly_curve" : !blockEntity.edgePoint.isOrthogonal() ? "no_assembly_diagonal" - : trainPresent() && !blockEntity.trainCanDisassemble ? "train_not_aligned" : null); + : trainPresent() && !blockEntity.trainCanDisassemble ? "train_not_aligned" : null); } private void tickTrainDisplay() { @@ -188,16 +188,18 @@ public class StationScreen extends AbstractStationScreen { disassembleTrainButton.visible = true; dropScheduleButton.active = blockEntity.trainHasSchedule; dropScheduleButton.visible = true; - colorTypeScroll.setState(imminentTrain.mapColorIndex); - colorTypeScroll.visible = true; - colorTypeScroll.active = true; + if (mapModsPresent()) { + colorTypeScroll.setState(imminentTrain.mapColorIndex); + colorTypeScroll.visible = true; + colorTypeScroll.active = true; + } trainNameBox.active = true; trainNameBox.setValue(imminentTrain.name.getString()); trainNameBox.setX(nameBoxX(trainNameBox.getValue(), trainNameBox)); addRenderableWidget(trainNameBox); int trainIconWidth = getTrainIconWidth(imminentTrain); - int targetPos = background.width / 2 - trainIconWidth / 2; + int targetPos = background.getWidth() / 2 - trainIconWidth / 2; if (trainIconWidth > 130) targetPos -= trainIconWidth - 130; float f = (float) (imminentTrain.navigation.distanceToDestination / 15f); @@ -209,7 +211,7 @@ public class StationScreen extends AbstractStationScreen { } int trainIconWidth = getTrainIconWidth(train); - int targetPos = background.width / 2 - trainIconWidth / 2; + int targetPos = background.getWidth() / 2 - trainIconWidth / 2; if (trainIconWidth > 130) targetPos -= trainIconWidth - 130; @@ -218,7 +220,7 @@ public class StationScreen extends AbstractStationScreen { colorTypeScroll.active = false; disassembleTrainButton.active = false; float f = 1 - (leavingAnimation / 80f); - trainPosition.setValue(targetPos + f * f * f * (background.width - targetPos + 5)); + trainPosition.setValue(targetPos + f * f * f * (background.getWidth() - targetPos + 5)); leavingAnimation--; if (leavingAnimation > 0) return; @@ -241,7 +243,7 @@ public class StationScreen extends AbstractStationScreen { dropScheduleButton.active = blockEntity.trainHasSchedule; if (blockEntity.trainHasSchedule) - dropScheduleButton.setToolTip(Lang.translateDirect( + dropScheduleButton.setToolTip(CreateLang.translateDirect( blockEntity.trainHasAutoSchedule ? "station.remove_auto_schedule" : "station.remove_schedule")); else dropScheduleButton.getToolTip() @@ -252,21 +254,21 @@ public class StationScreen extends AbstractStationScreen { } private int nameBoxX(String s, EditBox nameBox) { - return guiLeft + background.width / 2 - (Math.min(font.width(s), nameBox.getWidth()) + 10) / 2; + return guiLeft + background.getWidth() / 2 - (Math.min(font.width(s), nameBox.getWidth()) + 10) / 2; } private void updateAssemblyTooltip(String key) { if (key == null) { - disassembleTrainButton.setToolTip(Lang.translateDirect("station.disassemble_train")); - newTrainButton.setToolTip(Lang.translateDirect("station.create_train")); + disassembleTrainButton.setToolTip(CreateLang.translateDirect("station.disassemble_train")); + newTrainButton.setToolTip(CreateLang.translateDirect("station.create_train")); return; } - for (IconButton ib : new IconButton[] { disassembleTrainButton, newTrainButton }) { + for (IconButton ib : new IconButton[]{disassembleTrainButton, newTrainButton}) { List toolTip = ib.getToolTip(); toolTip.clear(); - toolTip.add(Lang.translateDirect("station." + key) + toolTip.add(CreateLang.translateDirect("station." + key) .withStyle(ChatFormatting.GRAY)); - toolTip.add(Lang.translateDirect("station." + key + "_1") + toolTip.add(CreateLang.translateDirect("station." + key + "_1") .withStyle(ChatFormatting.GRAY)); } } @@ -286,7 +288,7 @@ public class StationScreen extends AbstractStationScreen { Train train = displayedTrain.get(); if (train == null) { - MutableComponent header = Lang.translateDirect("station.idle"); + MutableComponent header = CreateLang.translateDirect("station.idle"); graphics.drawString(font, header, x + 97 - font.width(header) / 2, y + 47, 0x7A7A7A, false); return; } @@ -303,13 +305,13 @@ public class StationScreen extends AbstractStationScreen { List carriages = train.carriages; for (int i = carriages.size() - 1; i > 0; i--) { RenderSystem.setShaderColor(1, 1, 1, Math.min(1f, - Math.min((position + offset - 10) / 30f, (background.width - 40 - position - offset) / 30f))); + Math.min((position + offset - 10) / 30f, (background.getWidth() - 40 - position - offset) / 30f))); Carriage carriage = carriages.get(blockEntity.trainBackwards ? carriages.size() - i - 1 : i); offset += icon.render(carriage.bogeySpacing, graphics, x + offset, y + 20) + 1; } RenderSystem.setShaderColor(1, 1, 1, - Math.min(1f, Math.min((position + offset - 10) / 30f, (background.width - 40 - position - offset) / 30f))); + Math.min(1f, Math.min((position + offset - 10) / 30f, (background.getWidth() - 40 - position - offset) / 30f))); offset += icon.render(TrainIconType.ENGINE, graphics, x + offset, y + 20); RenderSystem.disableBlend(); ms.popPose(); @@ -332,10 +334,10 @@ public class StationScreen extends AbstractStationScreen { if (font.width(text) > trainNameBox.getWidth()) graphics.drawString(font, "...", guiLeft + 26, guiTop + 47, 0xa6a6a6); } - - if (!Mods.FTBCHUNKS.isLoaded()) + + if (!mapModsPresent()) return; - + AllGuiTextures sprite = AllGuiTextures.TRAINMAP_SPRITES; sprite.bind(); int trainColorIndex = colorTypeScroll.getState(); @@ -351,14 +353,18 @@ public class StationScreen extends AbstractStationScreen { int sheetX = col * 16 + colorCol * 128; int sheetY = row * 16 + colorRow * 64; - graphics.blit(sprite.location, positionX, positionY, sheetX, sheetY, 16, 16, sprite.width, sprite.height); + graphics.blit(sprite.location, positionX, positionY, sheetX, sheetY, 16, 16, sprite.getWidth(), sprite.getHeight()); } } + public boolean mapModsPresent() { + return Mods.FTBCHUNKS.isLoaded() || Mods.JOURNEYMAP.isLoaded(); + } + @Override public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { if (!nameBox.isFocused() && pMouseY > guiTop && pMouseY < guiTop + 14 && pMouseX > guiLeft - && pMouseX < guiLeft + background.width) { + && pMouseX < guiLeft + background.getWidth()) { nameBox.setFocused(true); nameBox.setHighlightPos(0); setFocused(nameBox); diff --git a/src/main/java/com/simibubi/create/content/trains/station/TrainEditPacket.java b/src/main/java/com/simibubi/create/content/trains/station/TrainEditPacket.java index d2ba96eab8..8376aabe5d 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/TrainEditPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/station/TrainEditPacket.java @@ -7,9 +7,9 @@ import com.simibubi.create.Create; import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.content.trains.entity.TrainIconType; import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.Components; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.Level; @@ -53,8 +53,9 @@ public class TrainEditPacket extends SimplePacketBase { Train train = Create.RAILWAYS.sided(level).trains.get(id); if (train == null) return; - if (!name.isBlank()) - train.name = Components.literal(name); + if (!name.isBlank()) { + train.name = Component.literal(name); + } train.icon = TrainIconType.byId(iconType); train.mapColorIndex = mapColor; if (sender != null) diff --git a/src/main/java/com/simibubi/create/content/trains/station/WideIconButton.java b/src/main/java/com/simibubi/create/content/trains/station/WideIconButton.java index 0e4b18724d..9edeec7f68 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/WideIconButton.java +++ b/src/main/java/com/simibubi/create/content/trains/station/WideIconButton.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.trains.station; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.ScreenElement; import com.simibubi.create.foundation.gui.widget.IconButton; +import net.createmod.catnip.gui.element.ScreenElement; import net.minecraft.client.gui.GuiGraphics; public class WideIconButton extends IconButton { @@ -15,7 +15,7 @@ public class WideIconButton extends IconButton { @Override protected void drawBg(GuiGraphics graphics, AllGuiTextures button) { super.drawBg(graphics, button); - graphics.blit(button.location, getX() + 9, getY(), button.startX + 1, button.startY, button.width - 1, button.height); + graphics.blit(button.location, getX() + 9, getY(), button.getStartX() + 1, button.getStartY(), button.getWidth() - 1, button.getHeight()); } } diff --git a/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java b/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java index 4fb8b200c5..b128bd4104 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java +++ b/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java @@ -2,16 +2,14 @@ package com.simibubi.create.content.trains.track; import java.util.function.BiFunction; import java.util.function.Function; -import java.util.function.UnaryOperator; import com.simibubi.create.Create; +import com.simibubi.create.api.contraption.train.PortalTrackProvider; import com.simibubi.create.compat.Mods; import com.simibubi.create.compat.betterend.BetterEndPortalCompat; import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; -import com.simibubi.create.foundation.utility.AttachedRegistry; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.math.BlockFace; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.registries.Registries; @@ -26,6 +24,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.portal.PortalInfo; import net.minecraft.world.phys.AABB; + import net.minecraftforge.common.util.ITeleporter; import net.minecraftforge.registries.ForgeRegistries; @@ -38,62 +37,19 @@ import net.minecraftforge.registries.ForgeRegistries; */ public class AllPortalTracks { /** - * Functional interface representing a provider for portal track connections. - * It takes a pair of {@link ServerLevel} and {@link BlockFace} representing the inbound track - * and returns a similar pair for the outbound track. - */ - @FunctionalInterface - public interface PortalTrackProvider extends UnaryOperator> {} - - /** - * Registry mapping portal blocks to their respective {@link PortalTrackProvider}s. - */ - private static final AttachedRegistry PORTAL_BEHAVIOURS = - new AttachedRegistry<>(ForgeRegistries.BLOCKS); - - /** - * Registers a portal track integration for a given block identified by its {@link ResourceLocation}. + * Registers a portal track integration for a given block identified by its {@link ResourceLocation}, if it exists. + * If it does not, a warning will be logged. * - * @param block The resource location of the portal block. + * @param id The resource location of the portal block. * @param provider The portal track provider for the block. */ - public static void registerIntegration(ResourceLocation block, PortalTrackProvider provider) { - PORTAL_BEHAVIOURS.register(block, provider); - } - - /** - * Registers a portal track integration for a given {@link Block}. - * - * @param block The portal block. - * @param provider The portal track provider for the block. - */ - public static void registerIntegration(Block block, PortalTrackProvider provider) { - PORTAL_BEHAVIOURS.register(block, provider); - } - - /** - * Checks if a given {@link BlockState} represents a supported portal block. - * - * @param state The block state to check. - * @return {@code true} if the block state represents a supported portal; {@code false} otherwise. - */ - public static boolean isSupportedPortal(BlockState state) { - return PORTAL_BEHAVIOURS.get(state.getBlock()) != null; - } - - /** - * Retrieves the corresponding outbound track on the other side of a portal. - * - * @param level The current {@link ServerLevel}. - * @param inboundTrack The inbound track {@link BlockFace}. - * @return A pair containing the target {@link ServerLevel} and outbound {@link BlockFace}, - * or {@code null} if no corresponding portal is found. - */ - public static Pair getOtherSide(ServerLevel level, BlockFace inboundTrack) { - BlockPos portalPos = inboundTrack.getConnectedPos(); - BlockState portalState = level.getBlockState(portalPos); - PortalTrackProvider provider = PORTAL_BEHAVIOURS.get(portalState.getBlock()); - return provider == null ? null : provider.apply(Pair.of(level, inboundTrack)); + public static void tryRegisterIntegration(ResourceLocation id, PortalTrackProvider provider) { + if (ForgeRegistries.BLOCKS.containsKey(id)) { + Block block = ForgeRegistries.BLOCKS.getValue(id); + PortalTrackProvider.REGISTRY.register(block, provider); + } else { + Create.LOGGER.warn("Portal for integration wasn't found: {}. Compat outdated?", id); + } } // Built-in handlers @@ -103,79 +59,52 @@ public class AllPortalTracks { * This includes the Nether and the Aether (if loaded). */ public static void registerDefaults() { - registerIntegration(Blocks.NETHER_PORTAL, AllPortalTracks::nether); - if (Mods.AETHER.isLoaded()) - registerIntegration(Mods.AETHER.rl("aether_portal"), AllPortalTracks::aether); - if (Mods.BETTEREND.isLoaded()) - registerIntegration(Mods.BETTEREND.rl("end_portal_block"), AllPortalTracks::betterend); + PortalTrackProvider.REGISTRY.register(Blocks.NETHER_PORTAL, AllPortalTracks::nether); + + if (Mods.AETHER.isLoaded()) { + tryRegisterIntegration(Mods.AETHER.rl("aether_portal"), AllPortalTracks::aether); + } + + if (Mods.BETTEREND.isLoaded()) { + tryRegisterIntegration(Mods.BETTEREND.rl("end_portal_block"), AllPortalTracks::betterend); + } } - /** - * Portal track provider for the Nether portal. - * - * @param inbound A pair containing the current {@link ServerLevel} and inbound {@link BlockFace}. - * @return A pair with the target {@link ServerLevel} and outbound {@link BlockFace}, or {@code null} if not applicable. - */ - private static Pair nether(Pair inbound) { - ServerLevel level = inbound.getFirst(); + private static PortalTrackProvider.Exit nether(ServerLevel level, BlockFace face) { MinecraftServer minecraftServer = level.getServer(); if (!minecraftServer.isNetherEnabled()) return null; - return standardPortalProvider(inbound, Level.OVERWORLD, Level.NETHER, ServerLevel::getPortalForcer); + return PortalTrackProvider.fromTeleporter(level, face, Level.OVERWORLD, Level.NETHER, ServerLevel::getPortalForcer); } - /** - * Portal track provider for the Aether mod's portal. - * - * @param inbound A pair containing the current {@link ServerLevel} and inbound {@link BlockFace}. - * @return A pair with the target {@link ServerLevel} and outbound {@link BlockFace}, or {@code null} if not applicable. - */ - private static Pair aether(Pair inbound) { - ResourceKey aetherLevelKey = - ResourceKey.create(Registries.DIMENSION, Mods.AETHER.rl("the_aether")); - return standardPortalProvider(inbound, Level.OVERWORLD, aetherLevelKey, level -> { + private static PortalTrackProvider.Exit aether(ServerLevel level, BlockFace face) { + ResourceKey aetherLevelKey = ResourceKey.create(Registries.DIMENSION, Mods.AETHER.rl("the_aether")); + return PortalTrackProvider.fromTeleporter(level, face, Level.OVERWORLD, aetherLevelKey, serverLevel -> { try { return (ITeleporter) Class.forName("com.aetherteam.aether.block.portal.AetherPortalForcer") .getDeclaredConstructor(ServerLevel.class, boolean.class) - .newInstance(level, true); + .newInstance(serverLevel, true); } catch (Exception e) { Create.LOGGER.error("Failed to create Aether teleporter: ", e); } - return level.getPortalForcer(); + return serverLevel.getPortalForcer(); }); } - /** - * Portal track provider for the Better End mod's portal. - * - * @param inbound A pair containing the current {@link ServerLevel} and inbound {@link BlockFace}. - * @return A pair with the target {@link ServerLevel} and outbound {@link BlockFace}, or {@code null} if not applicable. - */ - private static Pair betterend(Pair inbound) { - return portalProvider(inbound, Level.OVERWORLD, Level.END, BetterEndPortalCompat::getBetterEndPortalInfo); + private static PortalTrackProvider.Exit betterend(ServerLevel level, BlockFace face) { + return fromProbe(level, face, Level.OVERWORLD, Level.END, BetterEndPortalCompat::getBetterEndPortalInfo); } - /** - * Provides a standard portal track provider that handles portal traversal between two dimensions. - * - * @param inbound A pair containing the current {@link ServerLevel} and inbound {@link BlockFace}. - * @param firstDimension The first dimension (typically the Overworld). - * @param secondDimension The second dimension (e.g., Nether, Aether). - * @param customPortalForcer A function to obtain the {@link ITeleporter} for the target level. - * @return A pair with the target {@link ServerLevel} and outbound {@link BlockFace}, or {@code null} if not applicable. - */ - public static Pair standardPortalProvider( - Pair inbound, + public static PortalTrackProvider.Exit fromTeleporter( + ServerLevel level, BlockFace inboundTrack, ResourceKey firstDimension, ResourceKey secondDimension, Function customPortalForcer ) { - return portalProvider( - inbound, - firstDimension, - secondDimension, + return PortalTrackProvider.fromProbe( + level, inboundTrack, firstDimension, secondDimension, (otherLevel, probe) -> { ITeleporter teleporter = customPortalForcer.apply(otherLevel); return teleporter.getPortalInfo(probe, otherLevel, probe::findDimensionEntryPoint); @@ -183,22 +112,12 @@ public class AllPortalTracks { ); } - /** - * Generalized portal provider method that calculates the corresponding outbound track across a portal. - * - * @param inbound A pair containing the current {@link ServerLevel} and inbound {@link BlockFace}. - * @param firstDimension The first dimension. - * @param secondDimension The second dimension. - * @param portalInfoProvider A function that provides the {@link PortalInfo} given the target level and probe entity. - * @return A pair with the target {@link ServerLevel} and outbound {@link BlockFace}, or {@code null} if not applicable. - */ - public static Pair portalProvider( - Pair inbound, + public static PortalTrackProvider.Exit fromProbe( + ServerLevel level, BlockFace inboundTrack, ResourceKey firstDimension, ResourceKey secondDimension, BiFunction portalInfoProvider ) { - ServerLevel level = inbound.getFirst(); ResourceKey resourceKey = level.dimension() == secondDimension ? firstDimension : secondDimension; MinecraftServer minecraftServer = level.getServer(); @@ -207,7 +126,6 @@ public class AllPortalTracks { if (otherLevel == null) return null; - BlockFace inboundTrack = inbound.getSecond(); BlockPos portalPos = inboundTrack.getConnectedPos(); BlockState portalState = level.getBlockState(portalPos); @@ -228,6 +146,6 @@ public class AllPortalTracks { if (targetDirection.getAxis() == otherPortalState.getValue(BlockStateProperties.HORIZONTAL_AXIS)) targetDirection = targetDirection.getClockWise(); BlockPos otherPos = otherPortalPos.relative(targetDirection); - return Pair.of(otherLevel, new BlockFace(otherPos, targetDirection.getOpposite())); + return new PortalTrackProvider.Exit(otherLevel, new BlockFace(otherPos, targetDirection.getOpposite())); } } diff --git a/src/main/java/com/simibubi/create/content/trains/track/BezierConnection.java b/src/main/java/com/simibubi/create/content/trains/track/BezierConnection.java index 5f18851074..669b6e905d 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/BezierConnection.java +++ b/src/main/java/com/simibubi/create/content/trains/track/BezierConnection.java @@ -7,13 +7,13 @@ import java.util.Map; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; import net.minecraft.core.particles.BlockParticleOption; diff --git a/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackInteraction.java b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackInteraction.java index d24aacf7b8..a6def30ebd 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackInteraction.java +++ b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackInteraction.java @@ -4,9 +4,9 @@ import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; import com.simibubi.create.AllTags; import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.math.VecHelper; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -117,7 +117,7 @@ public class CurvedTrackInteraction { ItemStack heldItem = player.getMainHandItem(); Item item = heldItem.getItem(); if (AllTags.AllBlockTags.TRACKS.matches(heldItem)) { - player.displayClientMessage(Lang.translateDirect("track.turn_start") + player.displayClientMessage(CreateLang.translateDirect("track.turn_start") .withStyle(ChatFormatting.RED), true); player.swing(InteractionHand.MAIN_HAND); return true; diff --git a/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackSelectionPacket.java b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackSelectionPacket.java index d55177614a..d8fbca93c9 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackSelectionPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackSelectionPacket.java @@ -7,7 +7,7 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.trains.graph.EdgePointType; import com.simibubi.create.content.trains.track.TrackTargetingBlockItem.OverlapResult; import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -61,7 +61,7 @@ public class CurvedTrackSelectionPacket extends BlockEntityConfigurationPacket result.setValue(overlap)); if (result.getValue().feedback != null) { - player.displayClientMessage(Lang.translateDirect(result.getValue().feedback) + player.displayClientMessage(CreateLang.translateDirect(result.getValue().feedback) .withStyle(ChatFormatting.RED), true); AllSoundEvents.DENY.play(player.level(), null, pos, .5f, 1); return; @@ -89,7 +89,7 @@ public class CurvedTrackSelectionPacket extends BlockEntityConfigurationPacket, IWrenchable, ITrackBlock, ISpecialBlockItemRequirement, ProperWaterloggedBlock, IHaveBigOutline { + implements IBE, IWrenchable, ITrackBlock, SpecialBlockItemRequirement, ProperWaterloggedBlock, IHaveBigOutline { public static final EnumProperty SHAPE = EnumProperty.create("shape", TrackShape.class); public static final BooleanProperty HAS_BE = BooleanProperty.create("turn"); @@ -253,18 +253,18 @@ public class TrackBlock extends Block for (Direction d : Iterate.directionsInAxis(portalTest)) { BlockPos portalPos = pos.relative(d); BlockState portalState = level.getBlockState(portalPos); - if (!AllPortalTracks.isSupportedPortal(portalState)) + if (!PortalTrackProvider.isSupportedPortal(portalState)) continue; pop = true; - Pair otherSide = AllPortalTracks.getOtherSide(level, new BlockFace(pos, d)); + PortalTrackProvider.Exit otherSide = PortalTrackProvider.getOtherSide(level, new BlockFace(pos, d)); if (otherSide == null) { fail = "missing"; continue; } - ServerLevel otherLevel = otherSide.getFirst(); - BlockFace otherTrack = otherSide.getSecond(); + ServerLevel otherLevel = otherSide.level(); + BlockFace otherTrack = otherSide.face(); BlockPos otherTrackPos = otherTrack.getPos(); BlockState existing = otherLevel.getBlockState(otherTrackPos); if (!existing.canBeReplaced()) { @@ -298,13 +298,13 @@ public class TrackBlock extends Block Player player = level.getNearestPlayer(pos.getX(), pos.getY(), pos.getZ(), 10, Predicates.alwaysTrue()); if (player == null) return; - player.displayClientMessage(Components.literal(" ") - .append(Lang.translateDirect("portal_track.failed")) + player.displayClientMessage(Component.literal(" ") + .append(CreateLang.translateDirect("portal_track.failed")) .withStyle(ChatFormatting.GOLD), false); MutableComponent component = failPos != null - ? Lang.translateDirect("portal_track." + fail, failPos.getX(), failPos.getY(), failPos.getZ()) - : Lang.translateDirect("portal_track." + fail); - player.displayClientMessage(Components.literal(" - ") + ? CreateLang.translateDirect("portal_track." + fail, failPos.getX(), failPos.getY(), failPos.getZ()) + : CreateLang.translateDirect("portal_track." + fail); + player.displayClientMessage(Component.literal(" - ") .withStyle(ChatFormatting.GRAY) .append(component.withStyle(st -> st.withColor(0xFFD3B4))), false); } @@ -325,7 +325,7 @@ public class TrackBlock extends Block BlockPos portalPos = pCurrentPos.relative(d); BlockState portalState = level.getBlockState(portalPos); - if (!AllPortalTracks.isSupportedPortal(portalState)) + if (!PortalTrackProvider.isSupportedPortal(portalState)) return Blocks.AIR.defaultBlockState(); } diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntity.java index ce0fab09d1..48ede28c05 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntity.java @@ -11,7 +11,7 @@ import java.util.Set; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; import com.simibubi.create.AllTags; -import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; @@ -19,9 +19,9 @@ import com.simibubi.create.foundation.blockEntity.IMergeableBE; import com.simibubi.create.foundation.blockEntity.RemoveBlockEntityPacket; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Pair; import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; +import net.createmod.catnip.data.Pair; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction.Axis; import net.minecraft.core.registries.Registries; @@ -41,12 +41,13 @@ import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.fml.DistExecutor; -public class TrackBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity, IMergeableBE { +public class TrackBlockEntity extends SmartBlockEntity implements TransformableBlockEntity, IMergeableBE { Map connections; boolean cancelDrops; @@ -262,7 +263,7 @@ public class TrackBlockEntity extends SmartBlockEntity implements ITransformable } @Override - public void transform(StructureTransform transform) { + public void transform(BlockEntity be, StructureTransform transform) { Map restoredConnections = new HashMap<>(); for (Entry entry : connections.entrySet()) restoredConnections.put(entry.getKey(), diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntityTilt.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntityTilt.java index 847929bc13..3fae5d1065 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntityTilt.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntityTilt.java @@ -6,9 +6,9 @@ import java.util.Objects; import java.util.Optional; import com.simibubi.create.content.trains.graph.TrackNodeLocation; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; import net.minecraft.world.level.Level; diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockItem.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockItem.java index 1038e7a4b2..91a8bb0cb0 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockItem.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockItem.java @@ -5,10 +5,10 @@ import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllTags; import com.simibubi.create.content.trains.track.TrackPlacement.PlacementInfo; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; @@ -30,6 +30,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.event.entity.player.PlayerInteractEvent; @@ -62,14 +63,14 @@ public class TrackBlockItem extends BlockItem { if (state.getBlock() instanceof TrackBlock track && track.getTrackAxes(level, pos, state) .size() > 1) { if (!level.isClientSide) - player.displayClientMessage(Lang.translateDirect("track.junction_start") + player.displayClientMessage(CreateLang.translateDirect("track.junction_start") .withStyle(ChatFormatting.RED), true); return InteractionResult.SUCCESS; } - + if (level.getBlockEntity(pos) instanceof TrackBlockEntity tbe && tbe.isTilted()) { if (!level.isClientSide) - player.displayClientMessage(Lang.translateDirect("track.turn_start") + player.displayClientMessage(CreateLang.translateDirect("track.turn_start") .withStyle(ChatFormatting.RED), true); return InteractionResult.SUCCESS; } @@ -82,7 +83,7 @@ public class TrackBlockItem extends BlockItem { } else if (player.isShiftKeyDown()) { if (!level.isClientSide) { - player.displayClientMessage(Lang.translateDirect("track.selection_cleared"), true); + player.displayClientMessage(CreateLang.translateDirect("track.selection_cleared"), true); stack.setTag(null); } else level.playSound(player, pos, SoundEvents.ITEM_FRAME_REMOVE_ITEM, SoundSource.BLOCKS, 0.75f, 1); @@ -107,7 +108,7 @@ public class TrackBlockItem extends BlockItem { PlacementInfo info = TrackPlacement.tryConnect(level, player, pos, state, stack, hasGirder, extend); if (info.message != null && !level.isClientSide) - player.displayClientMessage(Lang.translateDirect(info.message), true); + player.displayClientMessage(CreateLang.translateDirect(info.message), true); if (!info.valid) { AllSoundEvents.DENY.playFrom(player, 1, 1); return InteractionResult.FAIL; @@ -137,10 +138,9 @@ public class TrackBlockItem extends BlockItem { public static boolean select(LevelAccessor world, BlockPos pos, Vec3 lookVec, ItemStack heldItem) { BlockState blockState = world.getBlockState(pos); Block block = blockState.getBlock(); - if (!(block instanceof ITrackBlock)) + if (!(block instanceof ITrackBlock track)) return false; - ITrackBlock track = (ITrackBlock) block; Pair nearestTrackAxis = track.getNearestTrackAxis(world, pos, blockState, lookVec); Vec3 axis = nearestTrackAxis.getFirst() .scale(nearestTrackAxis.getSecond() == AxisDirection.POSITIVE ? -1 : 1); diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockOutline.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockOutline.java index 6ce8343899..8eacdac2cf 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockOutline.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockOutline.java @@ -9,14 +9,14 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTags; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.RaycastHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.WorldAttached; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.data.WorldAttached; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackModel.java b/src/main/java/com/simibubi/create/content/trains/track/TrackModel.java index 3089982582..b8b4ee6af0 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackModel.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackModel.java @@ -8,8 +8,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.simibubi.create.foundation.model.BakedQuadHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; @@ -19,6 +19,7 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.client.model.BakedModelWrapper; import net.minecraftforge.client.model.data.ModelData; @@ -30,7 +31,7 @@ public class TrackModel extends BakedModelWrapper { @Override public @NotNull List getQuads(@Nullable BlockState state, @Nullable Direction side, - @NotNull RandomSource rand, @NotNull ModelData extraData, @Nullable RenderType renderType) { + @NotNull RandomSource rand, @NotNull ModelData extraData, @Nullable RenderType renderType) { List templateQuads = super.getQuads(state, side, rand, extraData, renderType); if (templateQuads.isEmpty()) return templateQuads; @@ -43,11 +44,11 @@ public class TrackModel extends BakedModelWrapper { TrackShape trackShape = state.getValue(TrackBlock.SHAPE); double hAngle = switch (trackShape) { - case XO -> 0; - case PD -> 45; - case ZO -> 90; - case ND -> 135; - default -> 0; + case XO -> 0; + case PD -> 45; + case ZO -> 90; + case ND -> 135; + default -> 0; }; Vec3 verticalOffset = new Vec3(0, -0.25, 0); @@ -68,8 +69,8 @@ public class TrackModel extends BakedModelWrapper { int size = templateQuads.size(); List quads = new ArrayList<>(); - for (int i = 0; i < size; i++) { - BakedQuad quad = BakedQuadHelper.clone(templateQuads.get(i)); + for (BakedQuad templateQuad : templateQuads) { + BakedQuad quad = BakedQuadHelper.clone(templateQuad); int[] vertexData = quad.getVertices(); for (int j = 0; j < 4; j++) BakedQuadHelper.setXYZ(vertexData, j, transform.apply(BakedQuadHelper.getXYZ(vertexData, j))); diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackPaver.java b/src/main/java/com/simibubi/create/content/trains/track/TrackPaver.java index bb7ced1432..8203dab923 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackPaver.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackPaver.java @@ -9,10 +9,10 @@ import java.util.Set; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.decoration.girder.GirderBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackPlacement.java b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacement.java index e6cc6cf032..37232bd94e 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackPlacement.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacement.java @@ -8,21 +8,22 @@ import java.util.Set; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.AllTags; -import com.simibubi.create.CreateClient; +import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; +import net.createmod.catnip.theme.Color; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -50,6 +51,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult.Type; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.items.ItemHandlerHelper; @@ -106,7 +108,7 @@ public class TrackPlacement { static int extraTipWarmup; public static PlacementInfo tryConnect(Level level, Player player, BlockPos pos2, BlockState state2, - ItemStack stack, boolean girder, boolean maximiseTurn) { + ItemStack stack, boolean girder, boolean maximiseTurn) { Vec3 lookVec = player.getLookAngle(); int lookAngle = (int) (22.5 + AngleHelper.deg(Mth.atan2(lookVec.z, lookVec.x)) % 360) / 8; int maxLength = AllConfigs.server().trains.maxTrackPlacementLength.get(); @@ -360,8 +362,8 @@ public class TrackPlacement { info.curve = skipCurve ? null : new BezierConnection(Couple.create(targetPos1, targetPos2), - Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2), - Couple.create(normal1, normal2), true, girder, TrackMaterial.fromItem(stack.getItem())); + Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2), + Couple.create(normal1, normal2), true, girder, TrackMaterial.fromItem(stack.getItem())); info.valid = true; @@ -374,7 +376,7 @@ public class TrackPlacement { ItemStack offhandItem = player.getOffhandItem() .copy(); - boolean shouldPave = offhandItem.getItem() instanceof BlockItem; + boolean shouldPave = offhandItem.getItem() instanceof BlockItem && !AllItemTags.INVALID_FOR_TRACK_PAVING.matches(offhandItem); if (shouldPave) { BlockItem paveItem = (BlockItem) offhandItem.getItem(); paveTracks(level, info, paveItem, true); @@ -480,7 +482,7 @@ public class TrackPlacement { } private static PlacementInfo placeTracks(Level level, PlacementInfo info, BlockState state1, BlockState state2, - BlockPos targetPos1, BlockPos targetPos2, boolean simulate) { + BlockPos targetPos1, BlockPos targetPos2, boolean simulate) { info.requiredTracks = 0; for (boolean first : Iterate.trueAndFalse) { @@ -492,14 +494,14 @@ public class TrackPlacement { state = state.setValue(TrackBlock.HAS_BE, false); switch (state.getValue(TrackBlock.SHAPE)) { - case TE, TW: - state = state.setValue(TrackBlock.SHAPE, TrackShape.XO); - break; - case TN, TS: - state = state.setValue(TrackBlock.SHAPE, TrackShape.ZO); - break; - default: - break; + case TE, TW: + state = state.setValue(TrackBlock.SHAPE, TrackShape.XO); + break; + case TN, TS: + state = state.setValue(TrackBlock.SHAPE, TrackShape.ZO); + break; + default: + break; } for (int i = 0; i < (info.curve != null ? extent + 1 : extent); i++) { @@ -532,27 +534,24 @@ public class TrackPlacement { BlockState onto = info.trackMaterial.getBlock().defaultBlockState(); BlockState stateAtPos = level.getBlockState(targetPos1); level.setBlock(targetPos1, ProperWaterloggedBlock.withWater(level, - (AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : BlockHelper.copyProperties(state1, onto)) - .setValue(TrackBlock.HAS_BE, true), targetPos1), 3); + (AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : BlockHelper.copyProperties(state1, onto)) + .setValue(TrackBlock.HAS_BE, true), targetPos1), 3); stateAtPos = level.getBlockState(targetPos2); level.setBlock(targetPos2, ProperWaterloggedBlock.withWater(level, - (AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : BlockHelper.copyProperties(state2, onto)) - .setValue(TrackBlock.HAS_BE, true), targetPos2), 3); + (AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : BlockHelper.copyProperties(state2, onto)) + .setValue(TrackBlock.HAS_BE, true), targetPos2), 3); } BlockEntity te1 = level.getBlockEntity(targetPos1); BlockEntity te2 = level.getBlockEntity(targetPos2); int requiredTracksForTurn = (info.curve.getSegmentCount() + 1) / 2; - if (!(te1 instanceof TrackBlockEntity) || !(te2 instanceof TrackBlockEntity)) { + if (!(te1 instanceof TrackBlockEntity tte1) || !(te2 instanceof TrackBlockEntity tte2)) { info.requiredTracks += requiredTracksForTurn; return info; } - TrackBlockEntity tte1 = (TrackBlockEntity) te1; - TrackBlockEntity tte2 = (TrackBlockEntity) te2; - if (!tte1.getConnections() .containsKey(tte2.getBlockPos())) info.requiredTracks += requiredTracksForTurn; @@ -626,11 +625,11 @@ public class TrackPlacement { BlueprintOverlayRenderer.displayTrackRequirements(info, player.getOffhandItem()); if (info.valid) - player.displayClientMessage(Lang.translateDirect("track.valid_connection") + player.displayClientMessage(CreateLang.translateDirect("track.valid_connection") .withStyle(ChatFormatting.GREEN), true); else if (info.message != null) - player.displayClientMessage(Lang.translateDirect(info.message) - .withStyle(info.message.equals("track.second_point") ? ChatFormatting.WHITE : ChatFormatting.RED), + player.displayClientMessage(CreateLang.translateDirect(info.message) + .withStyle(info.message.equals("track.second_point") ? ChatFormatting.WHITE : ChatFormatting.RED), true); if (bhr.getDirection() == Direction.UP) { @@ -653,11 +652,11 @@ public class TrackPlacement { } if (hints != null && !hints.either(Collection::isEmpty)) { - CreateClient.OUTLINER.showCluster("track_valid", hints.getFirst()) + Outliner.getInstance().showCluster("track_valid", hints.getFirst()) .withFaceTexture(AllSpecialTextures.THIN_CHECKERED) .colored(0x95CD41) .lineWidth(0); - CreateClient.OUTLINER.showCluster("track_invalid", hints.getSecond()) + Outliner.getInstance().showCluster("track_invalid", hints.getSecond()) .withFaceTexture(AllSpecialTextures.THIN_CHECKERED) .colored(0xEA5C2B) .lineWidth(0); @@ -737,13 +736,13 @@ public class TrackPlacement { .scale(0.5f); Vec3 middle2 = rail2.add(previous2) .scale(0.5f); - CreateClient.OUTLINER + Outliner.getInstance() .showLine(Pair.of(key, i * 2), VecHelper.lerp(s, middle1, previous1), VecHelper.lerp(s, middle1, rail1)) .colored(railcolor) .disableLineNormals() .lineWidth(lw); - CreateClient.OUTLINER + Outliner.getInstance() .showLine(Pair.of(key, i * 2 + 1), VecHelper.lerp(s, middle2, previous2), VecHelper.lerp(s, middle2, rail2)) .colored(railcolor) @@ -756,8 +755,8 @@ public class TrackPlacement { } for (int i = segCount + 1; i <= lastLineCount; i++) { - CreateClient.OUTLINER.remove(Pair.of(key, i * 2)); - CreateClient.OUTLINER.remove(Pair.of(key, i * 2 + 1)); + Outliner.getInstance().remove(Pair.of(key, i * 2)); + Outliner.getInstance().remove(Pair.of(key, i * 2 + 1)); } lastLineCount = segCount; @@ -766,7 +765,7 @@ public class TrackPlacement { @OnlyIn(Dist.CLIENT) private static void line(int id, Vec3 v1, Vec3 o1, Vec3 ex) { int color = Color.mixColors(0xEA5C2B, 0x95CD41, animation.getValue()); - CreateClient.OUTLINER.showLine(Pair.of("start", id), v1.subtract(o1), v1.add(ex)) + Outliner.getInstance().showLine(Pair.of("start", id), v1.subtract(o1), v1.add(ex)) .lineWidth(1 / 8f) .disableLineNormals() .colored(color); diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackPlacementOverlay.java b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacementOverlay.java index 229c37ca5b..7d76ce6ff0 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackPlacementOverlay.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacementOverlay.java @@ -1,14 +1,14 @@ package com.simibubi.create.content.trains.track; import com.mojang.blaze3d.platform.Window; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.theme.Color; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.world.level.GameType; @@ -18,7 +18,7 @@ import net.minecraftforge.fml.util.ObfuscationReflectionHelper; public class TrackPlacementOverlay implements IGuiOverlay { public static final TrackPlacementOverlay INSTANCE = new TrackPlacementOverlay(); - + @Override public void render(ForgeGui gui, GuiGraphics graphics, float partialTicks, int width, int height) { Minecraft mc = Minecraft.getInstance(); @@ -34,11 +34,11 @@ public class TrackPlacementOverlay implements IGuiOverlay { if (ObfuscationReflectionHelper.getPrivateValue(Gui.class, gui, "f_92993_") instanceof Integer toolHighlightTimer && toolHighlightTimer > 0) return; - + boolean active = mc.options.keySprint.isDown(); - MutableComponent text = Lang.translateDirect("track.hold_for_smooth_curve", Components.keybind("key.sprint") + MutableComponent text = CreateLang.translateDirect("track.hold_for_smooth_curve", Component.keybind("key.sprint") .withStyle(active ? ChatFormatting.WHITE : ChatFormatting.GRAY)); - + Window window = mc.getWindow(); int x = (window.getGuiScaledWidth() - gui.getFont() .width(text)) / 2; diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackRenderer.java b/src/main/java/com/simibubi/create/content/trains/track/TrackRenderer.java index 3ca20016f7..476047783d 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackRenderer.java @@ -10,12 +10,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.content.trains.track.BezierConnection.GirderAngles; import com.simibubi.create.content.trains.track.BezierConnection.SegmentAngles; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -60,7 +60,7 @@ public class TrackRenderer extends SafeBlockEntityRenderer { TrackMaterial.TrackModelHolder modelHolder = bc.getMaterial().getModelHolder(); - CachedBufferer.partial(modelHolder.tie(), air) + CachedBuffers.partial(modelHolder.tie(), air) .mulPose(segment.tieTransform.pose()) .mulNormal(segment.tieTransform.normal()) .light(light) @@ -68,7 +68,7 @@ public class TrackRenderer extends SafeBlockEntityRenderer { for (boolean first : Iterate.trueAndFalse) { Pose transform = segment.railTransforms.get(first); - CachedBufferer.partial(first ? modelHolder.leftSegment() : modelHolder.rightSegment(), air) + CachedBuffers.partial(first ? modelHolder.leftSegment() : modelHolder.rightSegment(), air) .mulPose(transform.pose()) .mulNormal(transform.normal()) .light(light) @@ -93,7 +93,7 @@ public class TrackRenderer extends SafeBlockEntityRenderer { for (boolean first : Iterate.trueAndFalse) { Pose beamTransform = segment.beams.get(first); - CachedBufferer.partial(GIRDER_SEGMENT_MIDDLE, air) + CachedBuffers.partial(GIRDER_SEGMENT_MIDDLE, air) .mulPose(beamTransform.pose()) .mulNormal(beamTransform.normal()) .light(light) @@ -102,7 +102,7 @@ public class TrackRenderer extends SafeBlockEntityRenderer { for (boolean top : Iterate.trueAndFalse) { Pose beamCapTransform = segment.beamCaps.get(top) .get(first); - CachedBufferer.partial(top ? GIRDER_SEGMENT_TOP : GIRDER_SEGMENT_BOTTOM, air) + CachedBuffers.partial(top ? GIRDER_SEGMENT_TOP : GIRDER_SEGMENT_BOTTOM, air) .mulPose(beamCapTransform.pose()) .mulNormal(beamCapTransform.normal()) .light(light) diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackShape.java b/src/main/java/com/simibubi/create/content/trains/track/TrackShape.java index 660db94cea..dfb23cddaf 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackShape.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackShape.java @@ -5,8 +5,8 @@ import java.util.List; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.core.Direction; import net.minecraft.util.StringRepresentable; import net.minecraft.world.level.block.Mirror; @@ -161,4 +161,4 @@ public enum TrackShape implements StringRepresentable { return shape; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBehaviour.java b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBehaviour.java index abba938ee2..76997d1624 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBehaviour.java @@ -8,7 +8,6 @@ import javax.annotation.Nullable; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.StructureTransform; -import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.content.trains.graph.DimensionPalette; import com.simibubi.create.content.trains.graph.EdgeData; import com.simibubi.create.content.trains.graph.EdgePointType; @@ -22,12 +21,13 @@ import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.ponder.PonderWorld; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.model.baked.PartialModel; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.levelWrappers.SchematicLevel; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.render.CachedBuffers; +import net.createmod.ponder.api.level.PonderLevel; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; @@ -41,8 +41,10 @@ import net.minecraft.util.Mth; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -309,21 +311,20 @@ public class TrackTargetingBehaviour extends BlockEnti @OnlyIn(Dist.CLIENT) public static void render(LevelAccessor level, BlockPos pos, AxisDirection direction, - BezierTrackPointLocation bezier, PoseStack ms, MultiBufferSource buffer, int light, int overlay, - RenderedTrackOverlayType type, float scale) { - if (level instanceof SchematicWorld && !(level instanceof PonderWorld)) + BezierTrackPointLocation bezier, PoseStack ms, MultiBufferSource buffer, int light, int overlay, + RenderedTrackOverlayType type, float scale) { + if (level instanceof SchematicLevel && !(level instanceof PonderLevel)) return; BlockState trackState = level.getBlockState(pos); Block block = trackState.getBlock(); - if (!(block instanceof ITrackBlock)) + if (!(block instanceof ITrackBlock track)) return; ms.pushPose(); - ITrackBlock track = (ITrackBlock) block; PartialModel partial = track.prepareTrackOverlay(level, pos, trackState, bezier, direction, ms, type); if (partial != null) - CachedBufferer.partial(partial, trackState) + CachedBuffers.partial(partial, trackState) .translate(.5, 0, .5) .scale(scale) .translate(-.5, 0, -.5) @@ -332,14 +333,14 @@ public class TrackTargetingBehaviour extends BlockEnti ms.popPose(); } - public void transform(StructureTransform transform) { + public void transform(BlockEntity be, StructureTransform transform) { id = UUID.randomUUID(); targetTrack = transform.applyWithoutOffset(targetTrack); if (prevDirection != null) rotatedDirection = transform.applyWithoutOffsetUncentered(prevDirection); if (targetBezier != null) targetBezier = new BezierTrackPointLocation(transform.applyWithoutOffset(targetBezier.curveTarget() - .subtract(getPos())) + .subtract(getPos())) .offset(getPos()), targetBezier.segment()); blockEntity.notifyUpdate(); } diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBlockItem.java b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBlockItem.java index 8da6b114d2..57ee267ddb 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBlockItem.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBlockItem.java @@ -16,10 +16,10 @@ import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import com.tterrag.registrate.util.nullness.NonNullBiFunction; +import net.createmod.catnip.data.Couple; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -68,7 +68,7 @@ public class TrackTargetingBlockItem extends BlockItem { if (player.isShiftKeyDown() && stack.hasTag()) { if (level.isClientSide) return InteractionResult.SUCCESS; - player.displayClientMessage(Lang.translateDirect("track_target.clear"), true); + player.displayClientMessage(CreateLang.translateDirect("track_target.clear"), true); stack.setTag(null); AllSoundEvents.CONTROLLER_CLICK.play(level, null, pos, 1, .5f); return InteractionResult.SUCCESS; @@ -87,7 +87,7 @@ public class TrackTargetingBlockItem extends BlockItem { withGraphLocation(level, pos, front, null, type, (overlap, location) -> result.setValue(overlap)); if (result.getValue().feedback != null) { - player.displayClientMessage(Lang.translateDirect(result.getValue().feedback) + player.displayClientMessage(CreateLang.translateDirect(result.getValue().feedback) .withStyle(ChatFormatting.RED), true); AllSoundEvents.DENY.play(level, null, pos, .5f, 1); return InteractionResult.FAIL; @@ -97,14 +97,14 @@ public class TrackTargetingBlockItem extends BlockItem { stackTag.put("SelectedPos", NbtUtils.writeBlockPos(pos)); stackTag.putBoolean("SelectedDirection", front); stackTag.remove("Bezier"); - player.displayClientMessage(Lang.translateDirect("track_target.set"), true); + player.displayClientMessage(CreateLang.translateDirect("track_target.set"), true); stack.setTag(stackTag); AllSoundEvents.CONTROLLER_CLICK.play(level, null, pos, 1, 1); return InteractionResult.SUCCESS; } if (!stack.hasTag()) { - player.displayClientMessage(Lang.translateDirect("track_target.missing") + player.displayClientMessage(CreateLang.translateDirect("track_target.missing") .withStyle(ChatFormatting.RED), true); return InteractionResult.FAIL; } @@ -119,7 +119,7 @@ public class TrackTargetingBlockItem extends BlockItem { boolean bezier = tag.contains("Bezier"); if (!selectedPos.closerThan(placedPos, bezier ? 64 + 16 : 16)) { - player.displayClientMessage(Lang.translateDirect("track_target.too_far") + player.displayClientMessage(CreateLang.translateDirect("track_target.too_far") .withStyle(ChatFormatting.RED), true); return InteractionResult.FAIL; } @@ -137,12 +137,12 @@ public class TrackTargetingBlockItem extends BlockItem { ItemStack itemInHand = player.getItemInHand(pContext.getHand()); if (!itemInHand.isEmpty()) itemInHand.setTag(null); - player.displayClientMessage(Lang.translateDirect("track_target.success") + player.displayClientMessage(CreateLang.translateDirect("track_target.success") .withStyle(ChatFormatting.GREEN), true); - + if (type == EdgePointType.SIGNAL) AllAdvancements.SIGNAL.awardTo(player); - + return useOn; } diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingClient.java b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingClient.java index b68bc4be0c..41d0477931 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingClient.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingClient.java @@ -8,9 +8,9 @@ import com.simibubi.create.content.trains.graph.TrackGraphLocation; import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; import com.simibubi.create.content.trains.track.TrackTargetingBlockItem.OverlapResult; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.SuperRenderTypeBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.LevelRenderer; diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackVisual.java b/src/main/java/com/simibubi/create/content/trains/track/TrackVisual.java index ec614f18b2..6f14ff3342 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackVisual.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackVisual.java @@ -10,12 +10,13 @@ import javax.annotation.Nullable; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.render.ContraptionVisual; import com.simibubi.create.content.trains.track.BezierConnection.GirderAngles; import com.simibubi.create.content.trains.track.BezierConnection.SegmentAngles; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.render.SpecialModels; import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.visual.ShaderLightVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.FlatLit; import dev.engine_room.flywheel.lib.instance.InstanceTypes; @@ -25,12 +26,14 @@ import dev.engine_room.flywheel.lib.transform.TransformStack; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import it.unimi.dsi.fastutil.longs.LongArraySet; import it.unimi.dsi.fastutil.longs.LongSet; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LightLayer; -public class TrackVisual extends AbstractBlockEntityVisual { +public class TrackVisual extends AbstractBlockEntityVisual implements ShaderLightVisual { private final List visuals = new ArrayList<>(); @@ -40,6 +43,12 @@ public class TrackVisual extends AbstractBlockEntityVisual { collectConnections(); } + @Override + public void setSectionCollector(SectionCollector sectionCollector) { + super.setSectionCollector(sectionCollector); + lightSections.sections(collectLightSections()); + } + @Override public void update(float pt) { if (blockEntity.connections.isEmpty()) @@ -79,8 +88,6 @@ public class TrackVisual extends AbstractBlockEntityVisual { } public LongSet collectLightSections() { - LongSet longSet = new LongArraySet(); - if (blockEntity.connections.isEmpty()) { return LongSet.of(); } @@ -90,19 +97,35 @@ public class TrackVisual extends AbstractBlockEntityVisual { int maxX = Integer.MIN_VALUE; int maxY = Integer.MIN_VALUE; int maxZ = Integer.MIN_VALUE; - for (BlockPos pos : blockEntity.connections.keySet()) { - minX = Math.min(minX, pos.getX()); - minY = Math.min(minY, pos.getY()); - minZ = Math.min(minZ, pos.getZ()); - maxX = Math.max(maxX, pos.getX()); - maxY = Math.max(maxY, pos.getY()); - maxZ = Math.max(maxZ, pos.getZ()); + for (BezierConnection connection : blockEntity.connections.values()) { + for (BlockPos pos : connection.bePositions) { + minX = Math.min(minX, pos.getX()); + minY = Math.min(minY, pos.getY()); + minZ = Math.min(minZ, pos.getZ()); + maxX = Math.max(maxX, pos.getX()); + maxY = Math.max(maxY, pos.getY()); + maxZ = Math.max(maxZ, pos.getZ()); + } } - SectionPos.betweenClosedStream(SectionPos.blockToSectionCoord(minX), SectionPos.blockToSectionCoord(minY), SectionPos.blockToSectionCoord(minZ), SectionPos.blockToSectionCoord(maxX), SectionPos.blockToSectionCoord(maxY), SectionPos.blockToSectionCoord(maxZ)) - .mapToLong(SectionPos::asLong) - .forEach(longSet::add); - return longSet; + var minSectionX = ContraptionVisual.minLightSection(minX); + var minSectionY = ContraptionVisual.minLightSection(minY); + var minSectionZ = ContraptionVisual.minLightSection(minZ); + int maxSectionX = ContraptionVisual.maxLightSection(maxX); + int maxSectionY = ContraptionVisual.maxLightSection(maxY); + int maxSectionZ = ContraptionVisual.maxLightSection(maxZ); + + LongSet out = new LongArraySet(); + + for (int x = minSectionX; x <= maxSectionX; x++) { + for (int y = minSectionY; y <= maxSectionY; y++) { + for (int z = minSectionZ; z <= maxSectionZ; z++) { + out.add(SectionPos.asLong(x, y, z)); + } + } + } + + return out; } @Override @@ -117,14 +140,10 @@ public class TrackVisual extends AbstractBlockEntityVisual { private final TransformedInstance[] ties; private final TransformedInstance[] left; private final TransformedInstance[] right; - private final BlockPos[] tiesLightPos; - private final BlockPos[] leftLightPos; - private final BlockPos[] rightLightPos; private @Nullable GirderVisual girder; private BezierTrackVisual(BezierConnection bc) { - BlockPos tePosition = bc.bePositions.getFirst(); girder = bc.hasGirder ? new GirderVisual(bc) : null; PoseStack pose = new PoseStack(); @@ -135,17 +154,14 @@ public class TrackVisual extends AbstractBlockEntityVisual { ties = new TransformedInstance[segCount]; left = new TransformedInstance[segCount]; right = new TransformedInstance[segCount]; - tiesLightPos = new BlockPos[segCount]; - leftLightPos = new BlockPos[segCount]; - rightLightPos = new BlockPos[segCount]; TrackMaterial.TrackModelHolder modelHolder = bc.getMaterial().getModelHolder(); - instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(modelHolder.tie())) + instancerProvider().instancer(InstanceTypes.TRANSFORMED, SpecialModels.flatChunk(modelHolder.tie())) .createInstances(ties); - instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(modelHolder.leftSegment())) + instancerProvider().instancer(InstanceTypes.TRANSFORMED, SpecialModels.flatChunk(modelHolder.leftSegment())) .createInstances(left); - instancerProvider().instancer(InstanceTypes.TRANSFORMED, Models.partial(modelHolder.rightSegment())) + instancerProvider().instancer(InstanceTypes.TRANSFORMED, SpecialModels.flatChunk(modelHolder.rightSegment())) .createInstances(right); SegmentAngles[] segments = bc.getBakedSegments(); @@ -156,14 +172,12 @@ public class TrackVisual extends AbstractBlockEntityVisual { ties[modelIndex].setTransform(pose) .mul(segment.tieTransform) .setChanged(); - tiesLightPos[modelIndex] = segment.lightPosition.offset(tePosition); for (boolean first : Iterate.trueAndFalse) { Pose transform = segment.railTransforms.get(first); (first ? this.left : this.right)[modelIndex].setTransform(pose) .mul(transform) .setChanged(); - (first ? leftLightPos : rightLightPos)[modelIndex] = segment.lightPosition.offset(tePosition); } } @@ -182,12 +196,7 @@ public class TrackVisual extends AbstractBlockEntityVisual { } void updateLight() { - for (int i = 0; i < ties.length; i++) - TrackVisual.updateLight(ties[i], level, tiesLightPos[i]); - for (int i = 0; i < left.length; i++) - TrackVisual.updateLight(left[i], level, leftLightPos[i]); - for (int i = 0; i < right.length; i++) - TrackVisual.updateLight(right[i], level, rightLightPos[i]); + // Light for ties/rails handled by shader light since they tend to clip into blocks if (girder != null) girder.updateLight(); } diff --git a/src/main/java/com/simibubi/create/foundation/ClientResourceReloadListener.java b/src/main/java/com/simibubi/create/foundation/ClientResourceReloadListener.java index 32ae579fb7..878a0ce280 100644 --- a/src/main/java/com/simibubi/create/foundation/ClientResourceReloadListener.java +++ b/src/main/java/com/simibubi/create/foundation/ClientResourceReloadListener.java @@ -2,8 +2,8 @@ package com.simibubi.create.foundation; import com.simibubi.create.CreateClient; import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.logistics.tableCloth.TableClothModel; import com.simibubi.create.foundation.sound.SoundScapes; -import com.simibubi.create.foundation.utility.LangNumberFormat; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; @@ -14,8 +14,8 @@ public class ClientResourceReloadListener implements ResourceManagerReloadListen public void onResourceManagerReload(ResourceManager resourceManager) { CreateClient.invalidateRenderers(); SoundScapes.invalidateAll(); - LangNumberFormat.numberFormat.update(); BeltHelper.uprightCache.clear(); + TableClothModel.reload(); } } diff --git a/src/main/java/com/simibubi/create/foundation/CreateNBTProcessors.java b/src/main/java/com/simibubi/create/foundation/CreateNBTProcessors.java new file mode 100644 index 0000000000..6291c9bd66 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/CreateNBTProcessors.java @@ -0,0 +1,78 @@ +package com.simibubi.create.foundation; + +import java.util.List; + +import com.simibubi.create.AllBlockEntityTypes; + +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.nbt.NBTProcessors; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.entity.BlockEntityType; + +import net.minecraftforge.registries.ForgeRegistries; + +public class CreateNBTProcessors { + public static void register() { + + NBTProcessors.addProcessor(BlockEntityType.SIGN, data -> { + for (int i = 0; i < 4; ++i) { + if (NBTProcessors.textComponentHasClickEvent(data.getString("Text" + (i + 1)))) + return null; + } + return data; + }); + + NBTProcessors.addProcessor(BlockEntityType.LECTERN, data -> { + if (!data.contains("Book", Tag.TAG_COMPOUND)) + return data; + CompoundTag book = data.getCompound("Book"); + + // Writable books can't have click events, so they're safe to keep + ResourceLocation writableBookResource = ForgeRegistries.ITEMS.getKey(Items.WRITABLE_BOOK); + if (writableBookResource != null && book.getString("id").equals(writableBookResource.toString())) + return data; + + if (!book.contains("tag", Tag.TAG_COMPOUND)) + return data; + CompoundTag tag = book.getCompound("tag"); + + if (!tag.contains("pages", Tag.TAG_LIST)) + return data; + ListTag pages = tag.getList("pages", Tag.TAG_STRING); + + for (Tag inbt : pages) { + if (NBTProcessors.textComponentHasClickEvent(inbt.getAsString())) + return null; + } + return data; + }); + + NBTProcessors.addProcessor(AllBlockEntityTypes.CLIPBOARD.get(), CreateNBTProcessors::clipboardProcessor); + + NBTProcessors.addProcessor(AllBlockEntityTypes.CREATIVE_CRATE.get(), NBTProcessors.itemProcessor("Filter")); + NBTProcessors.addProcessor(AllBlockEntityTypes.PLACARD.get(), NBTProcessors.itemProcessor("Item")); + } + + public static CompoundTag clipboardProcessor(CompoundTag data) { + if (!data.contains("Item", Tag.TAG_COMPOUND)) + return data; + CompoundTag book = data.getCompound("Item"); + + if (!book.contains("tag", Tag.TAG_COMPOUND)) + return data; + CompoundTag itemData = book.getCompound("tag"); + + for (List entries : NBTHelper.readCompoundList(itemData.getList("Pages", Tag.TAG_COMPOUND), + pageTag -> NBTHelper.readCompoundList(pageTag.getList("Entries", Tag.TAG_COMPOUND), + tag -> tag.getString("Text")))) { + for (String entry : entries) + if (NBTProcessors.textComponentHasClickEvent(entry)) + return null; + } + return data; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java index b4f2bba640..d6203485dd 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java @@ -19,6 +19,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.logistics.box.PackageStyles; import com.simibubi.create.foundation.advancement.CreateAdvancement.Builder; import net.minecraft.advancements.Advancement; @@ -26,8 +27,10 @@ import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; import net.minecraft.data.PackOutput.PathProvider; +import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; @@ -36,572 +39,637 @@ public class AllAdvancements implements DataProvider { public static final List ENTRIES = new ArrayList<>(); public static final CreateAdvancement START = null, - /* - * Some ids have trailing 0's to modify their vertical position on the tree - * (Advancement ordering seems to be deterministic but hash based) - */ + /* + * Some ids have trailing 0's to modify their vertical position on the tree + * (Advancement ordering seems to be deterministic but hash based) + */ - ROOT = create("root", b -> b.icon(AllItems.BRASS_HAND) - .title("Welcome to Create") - .description("Here Be Contraptions") - .awardedForFree() - .special(SILENT)), + ROOT = create("root", b -> b.icon(AllItems.BRASS_HAND) + .title("Welcome to Create") + .description("Here Be Contraptions") + .awardedForFree() + .special(SILENT)), - // Andesite - Central Branch + // Andesite - Central Branch - ANDESITE = create("andesite_alloy", b -> b.icon(AllItems.ANDESITE_ALLOY) - .title("Sturdier Rocks") - .description("Obtain some Andesite Alloy, Create's most important resource") - .after(ROOT) - .whenIconCollected()), + ANDESITE = create("andesite_alloy", b -> b.icon(AllItems.ANDESITE_ALLOY) + .title("Sturdier Rocks") + .description("Obtain some Andesite Alloy, Create's most important resource") + .after(ROOT) + .whenIconCollected()), - ANDESITE_CASING = create("andesite_casing", b -> b.icon(AllBlocks.ANDESITE_CASING) - .title("The Andesite Age") - .description("Apply Andesite Alloy to stripped wood, creating a basic casing for your machines") - .after(ANDESITE) - .special(NOISY)), + ANDESITE_CASING = create("andesite_casing", b -> b.icon(AllBlocks.ANDESITE_CASING) + .title("The Andesite Age") + .description("Apply Andesite Alloy to stripped wood, creating a basic casing for your machines") + .after(ANDESITE) + .special(NOISY)), - PRESS = create("mechanical_press", b -> b.icon(AllBlocks.MECHANICAL_PRESS) - .title("Bonk!") - .description("Create some sheets in a Mechanical Press") - .after(ANDESITE_CASING) - .special(NOISY)), + PRESS = create("mechanical_press", b -> b.icon(AllBlocks.MECHANICAL_PRESS) + .title("Bonk!") + .description("Create some sheets in a Mechanical Press") + .after(ANDESITE_CASING) + .special(NOISY)), - ENCASED_FAN = create("encased_fan", b -> b.icon(AllBlocks.ENCASED_FAN) - .title("Wind Maker") - .description("Place and power an Encased Fan") - .after(PRESS)), + ENCASED_FAN = create("encased_fan", b -> b.icon(AllBlocks.ENCASED_FAN) + .title("Wind Maker") + .description("Place and power an Encased Fan") + .after(PRESS)), - FAN_PROCESSING = create("fan_processing", b -> b.icon(AllItems.PROPELLER) - .title("Processing by Particle") - .description("Use an Encased Fan to process materials") - .after(ENCASED_FAN)), + FAN_PROCESSING = create("fan_processing", b -> b.icon(AllItems.PROPELLER) + .title("Processing by Particle") + .description("Use an Encased Fan to process materials") + .after(ENCASED_FAN)), - SAW_PROCESSING = create("saw_processing", b -> b.icon(AllBlocks.MECHANICAL_SAW) - .title("Workshop's Most Feared") - .description("Use an upright Mechanical Saw to process materials") - .after(FAN_PROCESSING)), + SAW_PROCESSING = create("saw_processing", b -> b.icon(AllBlocks.MECHANICAL_SAW) + .title("Workshop's Most Feared") + .description("Use an upright Mechanical Saw to process materials") + .after(FAN_PROCESSING)), - COMPACTING = create("compacting", b -> b.icon(Blocks.IRON_BLOCK) - .title("Compactification") - .description("Use a Mechanical Press and a Basin to create fewer items from more") - .after(SAW_PROCESSING)), + COMPACTING = create("compacting", b -> b.icon(Blocks.IRON_BLOCK) + .title("Compactification") + .description("Use a Mechanical Press and a Basin to create fewer items from more") + .after(SAW_PROCESSING)), - BELT = create("belt", b -> b.icon(AllItems.BELT_CONNECTOR) - .title("Kelp Drive") - .description("Connect two Shafts with a Mechanical Belt") - .after(COMPACTING)), + BELT = create("belt", b -> b.icon(AllItems.BELT_CONNECTOR) + .title("Kelp Drive") + .description("Connect two Shafts with a Mechanical Belt") + .after(COMPACTING)), - FUNNEL = create("funnel", b -> b.icon(AllBlocks.ANDESITE_FUNNEL) - .title("Airport Aesthetic") - .description("Extract or insert items into a container using a Funnel") - .after(BELT)), + FUNNEL = create("funnel", b -> b.icon(AllBlocks.ANDESITE_FUNNEL) + .title("Airport Aesthetic") + .description("Extract or insert items into a container using a Funnel") + .after(BELT)), - CHUTE = create("chute", b -> b.icon(AllBlocks.CHUTE) - .title("Vertical Logistics") - .description("Transport some items by Chute") - .after(FUNNEL)), + CHUTE = create("chute", b -> b.icon(AllBlocks.CHUTE) + .title("Vertical Logistics") + .description("Transport some items by Chute") + .after(FUNNEL)), - MIXER = create("mechanical_mixer", b -> b.icon(AllBlocks.MECHANICAL_MIXER) - .title("Mixing It Up") - .description("Combine ingredients in a Mechanical Mixer") - .after(CHUTE)), + MIXER = create("mechanical_mixer", b -> b.icon(AllBlocks.MECHANICAL_MIXER) + .title("Mixing It Up") + .description("Combine ingredients in a Mechanical Mixer") + .after(CHUTE)), - BLAZE_BURNER = create("burner", b -> b.icon(AllBlocks.BLAZE_BURNER) - .title("Sentient Fireplace") - .description("Obtain a Blaze Burner") - .whenIconCollected() - .after(MIXER)), + BLAZE_BURNER = create("burner", b -> b.icon(AllBlocks.BLAZE_BURNER) + .title("Sentient Fireplace") + .description("Obtain a Blaze Burner") + .whenIconCollected() + .after(MIXER)), - // Andesite - Top Branch + // Andesite - Top Branch - WATER_WHEEL = create("water_wheel", b -> b.icon(AllBlocks.WATER_WHEEL) - .title("Harnessed Hydraulics") - .description("Place a Water Wheel and use it to generate torque") - .after(ANDESITE)), + WATER_WHEEL = create("water_wheel", b -> b.icon(AllBlocks.WATER_WHEEL) + .title("Harnessed Hydraulics") + .description("Place a Water Wheel and use it to generate torque") + .after(ANDESITE)), - WINDMILL = create("windmill", b -> b.icon(AllBlocks.SAIL_FRAME) - .title("A Mild Breeze") - .description("Assemble a windmill and use it to generate torque") - .after(WATER_WHEEL)), + WINDMILL = create("windmill", b -> b.icon(AllBlocks.SAIL_FRAME) + .title("A mild Breeze") + .description("Assemble a windmill and use it to generate torque") + .after(WATER_WHEEL)), - COGS = create("shifting_gears", b -> b.icon(AllBlocks.COGWHEEL) - .title("Shifting Gears") - .description( - "Connect a Large Cogwheel to a Small Cogwheel, allowing you to change the speed of your Contraption") - .after(WINDMILL)), + COGS = create("shifting_gears", b -> b.icon(AllBlocks.COGWHEEL) + .title("Shifting Gears") + .description( + "Connect a Large Cogwheel to a Small Cogwheel, allowing you to change the speed of your Contraption") + .after(WINDMILL)), - MILLSTONE = create("millstone", b -> b.icon(AllBlocks.MILLSTONE) - .title("Embrace the Grind") - .description("Use a Millstone to pulverise materials") - .after(COGS)), + MILLSTONE = create("millstone", b -> b.icon(AllBlocks.MILLSTONE) + .title("Embrace the Grind") + .description("Use a Millstone to pulverise materials") + .after(COGS)), - SUPER_GLUE = create("super_glue", b -> b.icon(AllItems.SUPER_GLUE) - .title("Area of Connect") - .description("Super Glue some blocks into a group") - .after(MILLSTONE)), + SUPER_GLUE = create("super_glue", b -> b.icon(AllItems.SUPER_GLUE) + .title("Area of Connect") + .description("Super Glue some blocks into a group") + .after(MILLSTONE)), - CONTRAPTION_ACTORS = create("contraption_actors", b -> b.icon(AllBlocks.MECHANICAL_HARVESTER) - .title("Moving with Purpose") - .description("Create a Contraption with drills, saws, or harvesters on board") - .after(SUPER_GLUE)), + CONTRAPTION_ACTORS = create("contraption_actors", b -> b.icon(AllBlocks.MECHANICAL_HARVESTER) + .title("Moving with Purpose") + .description("Create a Contraption with drills, saws, or harvesters on board") + .after(SUPER_GLUE)), - PSI = create("portable_storage_interface", b -> b.icon(AllBlocks.PORTABLE_STORAGE_INTERFACE) - .title("Drive-By Exchange") - .description("Use a Portable Storage Interface to take or insert items into a Contraption") - .after(CONTRAPTION_ACTORS)), + PSI = create("portable_storage_interface", b -> b.icon(AllBlocks.PORTABLE_STORAGE_INTERFACE) + .title("Drive-by Exchange") + .description("Use a Portable Storage Interface to take or insert items into a Contraption") + .after(CONTRAPTION_ACTORS)), - WRENCH_GOGGLES = create("wrench_goggles", b -> b.icon(AllItems.WRENCH) - .title("Kitted Out") - .description("Equip Engineer's Goggles and a Wrench") - .whenIconCollected() - .whenItemCollected(AllItems.GOGGLES) - .after(PSI)), + WRENCH_GOGGLES = create("wrench_goggles", b -> b.icon(AllItems.WRENCH) + .title("Kitted Out") + .description("Equip Engineer's Goggles and a Wrench") + .whenIconCollected() + .whenItemCollected(AllItems.GOGGLES) + .after(PSI)), - STRESSOMETER = create("stressometer", b -> b.icon(AllBlocks.STRESSOMETER) - .title("Stress for Nerds") - .description("Get an exact readout with the help of Engineer's Goggles and a Stressometer") - .after(WRENCH_GOGGLES)), + STRESSOMETER = create("stressometer", b -> b.icon(AllBlocks.STRESSOMETER) + .title("Stress for Nerds") + .description("Get an exact readout with the help of Engineer's Goggles and a Stressometer") + .after(WRENCH_GOGGLES)), - CUCKOO_CLOCK = create("cuckoo_clock", b -> b.icon(AllBlocks.CUCKOO_CLOCK) - .title("Is It Time?") - .description("Witness your Cuckoo Clock announce bedtime") - .after(STRESSOMETER) - .special(NOISY)), + CUCKOO_CLOCK = create("cuckoo_clock", b -> b.icon(AllBlocks.CUCKOO_CLOCK) + .title("Is it Time?") + .description("Witness your Cuckoo Clock announce bedtime") + .after(STRESSOMETER) + .special(NOISY)), - // Andesite - Expert Branch + // Andesite - Expert Branch - WINDMILL_MAXED = create("windmill_maxed", b -> b.icon(AllBlocks.SAIL) - .title("A Strong Breeze") - .description("Assemble a windmill of maximum strength") - .after(ANDESITE) - .special(EXPERT)), + WINDMILL_MAXED = create("windmill_maxed", b -> b.icon(AllBlocks.SAIL) + .title("A strong Breeze") + .description("Assemble a windmill of maximum strength") + .after(ANDESITE) + .special(EXPERT)), - EJECTOR_MAXED = create("ejector_maxed", b -> b.icon(AllBlocks.WEIGHTED_EJECTOR) - .title("Springboard Champion") - .description("Get launched more than 30 blocks by a Weighted Ejector") - .after(WINDMILL_MAXED) - .special(EXPERT)), + EJECTOR_MAXED = create("ejector_maxed", b -> b.icon(AllBlocks.WEIGHTED_EJECTOR) + .title("Springboard Champion") + .description("Get launched more than 30 blocks by a Weighted Ejector") + .after(WINDMILL_MAXED) + .special(EXPERT)), - PULLEY_MAXED = create("pulley_maxed", b -> b.icon(AllBlocks.ROPE_PULLEY) - .title("Rope to Nowhere") - .description("Extend a Rope Pulley over 200 blocks deep") - .after(EJECTOR_MAXED) - .special(EXPERT)), + PULLEY_MAXED = create("pulley_maxed", b -> b.icon(AllBlocks.ROPE_PULLEY) + .title("Rope to Nowhere") + .description("Extend a Rope Pulley over 200 blocks deep") + .after(EJECTOR_MAXED) + .special(EXPERT)), - CART_PICKUP = create("cart_pickup", b -> b.icon(AllItems.CHEST_MINECART_CONTRAPTION) - .title("Strong Arms") - .description("Pick up a Minecart Contraption with at least 200 attached blocks") - .after(PULLEY_MAXED) - .special(EXPERT)), + CART_PICKUP = create("cart_pickup", b -> b.icon(AllItems.CHEST_MINECART_CONTRAPTION) + .title("Strong Arms") + .description("Pick up a Minecart Contraption with at least 200 attached blocks") + .after(PULLEY_MAXED) + .special(EXPERT)), - ANVIL_PLOUGH = create("anvil_plough", b -> b.icon(Blocks.CHIPPED_ANVIL) - .title("Blacksmith Artillery") - .description("Launch an Anvil with Mechanical Ploughs") - .after(CART_PICKUP) - .special(EXPERT)), + ANVIL_PLOUGH = create("anvil_plough", b -> b.icon(Blocks.CHIPPED_ANVIL) + .title("Blacksmith Artillery") + .description("Launch an Anvil with Mechanical Ploughs") + .after(CART_PICKUP) + .special(EXPERT)), - // Andesite - Hidden + // Andesite - Hidden - LAVA_WHEEL = create("lava_wheel_00000", b -> b.icon(AllBlocks.WATER_WHEEL) - .title("Magma Wheel") - .description("This shouldn't have worked") - .after(MIXER) + LAVA_WHEEL = create("lava_wheel_00000", b -> b.icon(AllBlocks.WATER_WHEEL) + .title("Magma Wheel") + .description("This shouldn't have worked") + .after(MIXER) + .special(SECRET)), + + HAND_CRANK = create("hand_crank_000", b -> b.icon(AllBlocks.HAND_CRANK) + .title("Workout Session") + .description("Use a Hand Crank until fully exhausted") + .after(MIXER) + .special(SECRET)), + + FUNNEL_KISS = create("belt_funnel_kiss", b -> b.icon(AllBlocks.BRASS_FUNNEL) + .title("The Parrots and the Flaps") + .description("Make two Belt-mounted Funnels kiss") + .after(MIXER) + .special(SECRET)), + + STRESSOMETER_MAXED = create("stressometer_maxed", b -> b.icon(AllBlocks.STRESSOMETER) + .title("Perfectly Stressed") + .description("Get a 100% readout from a Stressometer") + .after(MIXER) + .special(SECRET)), + + // Logistics + + CARDBOARD = create("cardboard", b -> b.icon(AllItems.CARDBOARD) + .title("Part and Parcel") + .description("Produce or obtain your first Cardboard") + .whenIconCollected() + .after(MIXER)), + + PACKAGER = create("packager", b -> b.icon(AllBlocks.PACKAGER) + .title("Post Production") + .description("Package items from an inventory using the Packager") + .after(CARDBOARD)), + + STOCK_TICKER = create("stock_ticker", b -> b.icon(AllBlocks.STOCK_TICKER) + .title("Order Up!") + .description("Employ a mob at your stock ticker and make your first requests") + .special(NOISY) + .after(PACKAGER)), + + FROGPORT = create("frogport", b -> b.icon(AllBlocks.PACKAGE_FROGPORT) + .title("Hungry hoppers") + .description("Catch packages from your Chain Conveyor using a Frogport") + .special(NOISY) + .after(STOCK_TICKER)), + + TABLE_CLOTH_SHOP = create("table_cloth_shop", b -> b.icon(AllBlocks.TABLE_CLOTHS.get(DyeColor.RED)) + .title("Open for business") + .description("Put items up for sale using a Table Cloth") + .special(NOISY) + .after(FROGPORT)), + + FACTORY_GAUGE = create("factory_gauge", b -> b.icon(AllBlocks.FACTORY_GAUGE) + .title("High Logistics") + .description("Trigger an automatic package request using Factory Gauges") + .special(NOISY) + .after(TABLE_CLOTH_SHOP)), + + CARDBOARD_ARMOR = create("cardboard_armor", b -> b.icon(AllItems.CARDBOARD_CHESTPLATE) + .title("Full Stealth") + .description("Sneak around in full Cardboard Armor") + .after(FACTORY_GAUGE)), + + // Logistics - Secret + + PACKAGE_CHUTE_THROW = create("package_chute_throw", b -> b.icon(PackageStyles.getDefaultBox()) + .title("Nothing but net") + .description("Land your cardboard package throw in an item chute") + .after(CARDBOARD_ARMOR) + .special(SECRET)), + + CARDBOARD_ARMOR_TRIM = create("cardboard_armor_trim", + b -> b.icon(createArmorTrimmedCardboardChestplate()) + .title("Arts and Crafts") + .description("Decorate your cardboard equipment with armor trims") + .after(CARDBOARD_ARMOR) .special(SECRET)), - HAND_CRANK = create("hand_crank_000", b -> b.icon(AllBlocks.HAND_CRANK) - .title("Workout Session") - .description("Use a Hand Crank until fully exhausted") - .after(MIXER) - .special(SECRET)), + // Copper - Central Branch - FUNNEL_KISS = create("belt_funnel_kiss", b -> b.icon(AllBlocks.BRASS_FUNNEL) - .title("The Parrots and the Flaps") - .description("Make two Belt-mounted Funnels kiss") - .after(MIXER) - .special(SECRET)), + COPPER = create("copper", b -> b.icon(Items.COPPER_INGOT) + .title("Cuprum Bokum") + .description("Amass some Copper Ingots for your exploits in fluid manipulation") + .whenIconCollected() + .after(BLAZE_BURNER) + .special(SILENT)), - STRESSOMETER_MAXED = create("stressometer_maxed", b -> b.icon(AllBlocks.STRESSOMETER) - .title("Perfectly Stressed") - .description("Get a 100% readout from a Stressometer") - .after(MIXER) - .special(SECRET)), + COPPER_CASING = create("copper_casing", b -> b.icon(AllBlocks.COPPER_CASING) + .title("The Copper Age") + .description("Apply Copper Ingots to stripped wood, creating a waterproof casing for your machines") + .after(COPPER)), - // Copper - Central Branch + SPOUT = create("spout", b -> b.icon(AllBlocks.SPOUT) + .title("Sploosh") + .description("Watch a fluid-containing item be filled by a Spout") + .after(COPPER_CASING)), - COPPER = create("copper", b -> b.icon(Items.COPPER_INGOT) - .title("Cuprum Bokum") - .description("Amass some Copper Ingots for your exploits in fluid manipulation") - .whenIconCollected() - .after(BLAZE_BURNER) - .special(SILENT)), + DRAIN = create("drain", b -> b.icon(AllBlocks.ITEM_DRAIN) + .title("Tumble Draining") + .description("Watch a fluid-containing item be emptied by an Item Drain") + .after(SPOUT)), - COPPER_CASING = create("copper_casing", b -> b.icon(AllBlocks.COPPER_CASING) - .title("The Copper Age") - .description("Apply Copper Ingots to stripped wood, creating a waterproof casing for your machines") - .after(COPPER) - .special(NOISY)), + STEAM_ENGINE = create("steam_engine", b -> b.icon(AllBlocks.STEAM_ENGINE) + .title("The Powerhouse") + .description("Use a Steam Engine to generate torque") + .after(DRAIN)), - SPOUT = create("spout", b -> b.icon(AllBlocks.SPOUT) - .title("Sploosh") - .description("Watch a fluid-containing item be filled by a Spout") - .after(COPPER_CASING)), + STEAM_WHISTLE = create("steam_whistle", b -> b.icon(AllBlocks.STEAM_WHISTLE) + .title("Voice of an Angel") + .description("Activate a Steam Whistle") + .after(STEAM_ENGINE)), - DRAIN = create("drain", b -> b.icon(AllBlocks.ITEM_DRAIN) - .title("Tumble Draining") - .description("Watch a fluid-containing item be emptied by an Item Drain") - .after(SPOUT)), + BACKTANK = create("backtank", b -> b.icon(AllItems.COPPER_BACKTANK) + .title("Pressure to Go") + .description("Create a Copper Backtank and make it accumulate air pressure") + .after(STEAM_WHISTLE)), - STEAM_ENGINE = create("steam_engine", b -> b.icon(AllBlocks.STEAM_ENGINE) - .title("The Powerhouse") - .description("Use a Steam Engine to generate torque") - .after(DRAIN)), + DIVING_SUIT = create("diving_suit", b -> b.icon(AllItems.COPPER_DIVING_HELMET) + .title("Ready for the Depths") + .description("Equip a Diving Helmet and a Copper Backtank, then jump into water") + .after(BACKTANK)), - STEAM_WHISTLE = create("steam_whistle", b -> b.icon(AllBlocks.STEAM_WHISTLE) - .title("Voice of an Angel") - .description("Activate a Steam Whistle") - .after(STEAM_ENGINE)), + // Copper - Top Branch - BACKTANK = create("backtank", b -> b.icon(AllItems.COPPER_BACKTANK) - .title("Pressure to Go") - .description("Create a Copper Backtank and make it accumulate air pressure") - .after(STEAM_WHISTLE)), + PUMP = create("mechanical_pump_0", b -> b.icon(AllBlocks.MECHANICAL_PUMP) + .title("Under Pressure") + .description("Place and power a Mechanical Pump") + .after(COPPER)), - DIVING_SUIT = create("diving_suit", b -> b.icon(AllItems.COPPER_DIVING_HELMET) - .title("Ready for the Depths") - .description("Equip a Diving Helmet and a Copper Backtank, then jump into water") - .after(BACKTANK)), + GLASS_PIPE = create("glass_pipe", b -> b.icon(AllBlocks.FLUID_PIPE) + .title("Flow Discovery") + .description("Use your Wrench on a pipe that contains a fluid") + .after(PUMP)), - // Copper - Top Branch + WATER_SUPPLY = create("water_supply", b -> b.icon(Items.WATER_BUCKET) + .title("Puddle Collector") + .description("Use the pulling end of a Fluid Pipe or Mechanical Pump to collect water") + .after(GLASS_PIPE)), - PUMP = create("mechanical_pump_0", b -> b.icon(AllBlocks.MECHANICAL_PUMP) - .title("Under Pressure") - .description("Place and power a Mechanical Pump") - .after(COPPER)), + HOSE_PULLEY = create("hose_pulley", b -> b.icon(AllBlocks.HOSE_PULLEY) + .title("Industrial Spillage") + .description("Lower a Hose Pulley and watch it drain or fill a body of fluid") + .after(WATER_SUPPLY)), - GLASS_PIPE = create("glass_pipe", b -> b.icon(AllBlocks.FLUID_PIPE) - .title("Flow Discovery") - .description("Use your Wrench on a pipe that contains a fluid") - .after(PUMP)), - - WATER_SUPPLY = create("water_supply", b -> b.icon(Items.WATER_BUCKET) - .title("Puddle Collector") - .description("Use the pulling end of a Fluid Pipe or Mechanical Pump to collect water") - .after(GLASS_PIPE)), - - HOSE_PULLEY = create("hose_pulley", b -> b.icon(AllBlocks.HOSE_PULLEY) - .title("Industrial Spillage") - .description("Lower a Hose Pulley and watch it drain or fill a body of fluid") - .after(WATER_SUPPLY)), - - CHOCOLATE_BUCKET = create("chocolate_bucket", b -> b.icon(AllFluids.CHOCOLATE.get() + CHOCOLATE_BUCKET = create("chocolate_bucket", b -> b.icon(AllFluids.CHOCOLATE.get() .getBucket()) - .title("A World of Imagination") - .description("Obtain a bucket of molten chocolate") - .whenIconCollected() - .after(HOSE_PULLEY)), + .title("A World of Imagination") + .description("Obtain a bucket of molten chocolate") + .whenIconCollected() + .after(HOSE_PULLEY)), - HONEY_DRAIN = create("honey_drain", b -> b.icon(Items.BEEHIVE) - .title("Autonomous Bee-Keeping") - .description("Use pipes to pull honey from a Bee Nest or Beehive") - .after(CHOCOLATE_BUCKET)), + HONEY_DRAIN = create("honey_drain", b -> b.icon(Items.BEEHIVE) + .title("Autonomous Bee-Keeping") + .description("Use pipes to pull honey from a Bee Nest or Beehive") + .after(CHOCOLATE_BUCKET)), - // Copper - Expert Branch + // Copper - Expert Branch - HOSE_PULLEY_LAVA = create("hose_pulley_lava", b -> b.icon(AllBlocks.HOSE_PULLEY) - .title("Tapping the Mantle") - .description("Pump from a body of lava large enough to be considered infinite") - .after(COPPER) - .special(EXPERT)), + HOSE_PULLEY_LAVA = create("hose_pulley_lava", b -> b.icon(AllBlocks.HOSE_PULLEY) + .title("Tapping the Mantle") + .description("Pump from a body of lava large enough to be considered infinite") + .after(COPPER) + .special(EXPERT)), - STEAM_ENGINE_MAXED = create("steam_engine_maxed", b -> b.icon(AllBlocks.STEAM_ENGINE) - .title("Full Steam") - .description("Run a boiler at the maximum level of power") - .after(HOSE_PULLEY_LAVA) - .special(EXPERT)), + STEAM_ENGINE_MAXED = create("steam_engine_maxed", b -> b.icon(AllBlocks.STEAM_ENGINE) + .title("Full Steam") + .description("Run a boiler at the maximum level of power") + .after(HOSE_PULLEY_LAVA) + .special(EXPERT)), - FOODS = create("foods", b -> b.icon(AllItems.CHOCOLATE_BERRIES) - .title("Balanced Diet") - .description("Create Chocolate Glazed Berries, a Honeyed Apple, and a Sweet Roll all from the same Spout") - .after(STEAM_ENGINE_MAXED) - .special(EXPERT)), + FOODS = create("foods", b -> b.icon(AllItems.CHOCOLATE_BERRIES) + .title("Balanced Diet") + .description("Create Chocolate Glazed Berries, a Honeyed Apple, and a Sweet Roll all from the same Spout") + .after(STEAM_ENGINE_MAXED) + .special(EXPERT)), - DIVING_SUIT_LAVA = create("diving_suit_lava", b -> b.icon(AllItems.NETHERITE_DIVING_HELMET) - .title("Swimming with the Striders") - .description("Attempt to take a dive in lava with your netherite diving gear") - .after(FOODS) - .special(EXPERT)), + DIVING_SUIT_LAVA = create("diving_suit_lava", b -> b.icon(AllItems.NETHERITE_DIVING_HELMET) + .title("Swimming with the Striders") + .description("Attempt to take a dive in lava with your netherite diving gear") + .after(FOODS) + .special(EXPERT)), - // Copper - Hidden + // Copper - Hidden - CHAINED_DRAIN = create("chained_drain", b -> b.icon(AllBlocks.ITEM_DRAIN) - .title("On a Roll") - .description("Watch an item move across a row of Item Drains") - .after(BACKTANK) - .special(SECRET)), + CHAINED_DRAIN = create("chained_drain", b -> b.icon(AllBlocks.ITEM_DRAIN) + .title("On a Roll") + .description("Watch an item move across a row of Item Drains") + .after(BACKTANK) + .special(SECRET)), - CROSS_STREAMS = create("cross_streams", b -> b.icon(Blocks.COBBLESTONE) - .title("Don't Cross the Streams!") - .description("Watch two fluids meet in your pipe network") - .after(BACKTANK) - .special(SECRET)), + CROSS_STREAMS = create("cross_streams", b -> b.icon(Blocks.COBBLESTONE) + .title("Don't Cross the Streams!") + .description("Watch two fluids meet in your pipe network") + .after(BACKTANK) + .special(SECRET)), - PIPE_ORGAN = create("pipe_organ", b -> b.icon(AllBlocks.STEAM_WHISTLE) - .title("The Pipe Organ") - .description("Attach 12 uniquely pitched Steam Whistles to a single Fluid Tank") - .after(BACKTANK) - .special(SECRET)), + PIPE_ORGAN = create("pipe_organ", b -> b.icon(AllBlocks.STEAM_WHISTLE) + .title("The Pipe Organ") + .description("Attach 12 uniquely pitched Steam Whistles to a single Fluid Tank") + .after(BACKTANK) + .special(SECRET)), - // Brass - Central Branch + // Brass - Central Branch - BRASS = create("brass", b -> b.icon(AllItems.BRASS_INGOT) - .title("Real Alloys") - .description("Create Brass Ingots by alloying Copper and Zinc Ingots in your Blaze-heated Mechanical Mixer") - .whenIconCollected() - .after(DIVING_SUIT)), + BRASS = create("brass", b -> b.icon(AllItems.BRASS_INGOT) + .title("Real Alloys") + .description("Create Brass Ingots by alloying Copper and Zinc Ingots in your Blaze-heated Mechanical Mixer") + .whenIconCollected() + .after(DIVING_SUIT)), - BRASS_CASING = create("brass_casing", b -> b.icon(AllBlocks.BRASS_CASING) - .title("The Brass Age") - .description("Apply Brass Ingots to stripped wood, creating a casing for more sophisticated machines") - .after(BRASS) - .special(NOISY)), + BRASS_CASING = create("brass_casing", b -> b.icon(AllBlocks.BRASS_CASING) + .title("The Brass Age") + .description("Apply Brass Ingots to stripped wood, creating a casing for more sophisticated machines") + .after(BRASS) + .special(NOISY)), - ROSE_QUARTZ = create("rose_quartz", b -> b.icon(AllItems.POLISHED_ROSE_QUARTZ) - .title("Pink Diamonds") - .description("Polish some Rose Quartz") - .whenIconCollected() - .after(BRASS_CASING)), + ROSE_QUARTZ = create("rose_quartz", b -> b.icon(AllItems.POLISHED_ROSE_QUARTZ) + .title("Supercharged") + .description("Polish some Rose Quartz") + .whenIconCollected() + .after(BRASS_CASING)), - DEPLOYER = create("deployer", b -> b.icon(AllBlocks.DEPLOYER) - .title("Artificial Intelligence") - .description("Place and power a Deployer, the perfect reflection of yourself") - .after(ROSE_QUARTZ)), + DEPLOYER = create("deployer", b -> b.icon(AllBlocks.DEPLOYER) + .title("Artificial Intelligence") + .description("Place and power a Deployer, the perfect reflection of yourself") + .after(ROSE_QUARTZ)), - MECHANISM = create("precision_mechanism", b -> b.icon(AllItems.PRECISION_MECHANISM) - .title("Complex Curiosities") - .description("Assemble a Precision Mechanism") - .whenIconCollected() - .after(DEPLOYER) - .special(NOISY)), + MECHANISM = create("precision_mechanism", b -> b.icon(AllItems.PRECISION_MECHANISM) + .title("Complex Curiosities") + .description("Assemble a Precision Mechanism") + .whenIconCollected() + .after(DEPLOYER) + .special(NOISY)), - SPEED_CONTROLLER = create("speed_controller", b -> b.icon(AllBlocks.ROTATION_SPEED_CONTROLLER) - .title("Engineers hate this simple trick!") - .description("Fine-tune your Contraption with a Rotation Speed Controller") - .after(MECHANISM)), + SPEED_CONTROLLER = create("speed_controller", b -> b.icon(AllBlocks.ROTATION_SPEED_CONTROLLER) + .title("Engineers hate this simple trick!") + .description("Fine-tune your Contraption with a Rotation Speed Controller") + .after(MECHANISM)), - MECHANICAL_ARM = create("mechanical_arm", b -> b.icon(AllBlocks.MECHANICAL_ARM) - .title("Busy Hands") - .description("Watch your Mechanical Arm transport its first item") - .after(SPEED_CONTROLLER) - .special(NOISY)), + MECHANICAL_ARM = create("mechanical_arm", b -> b.icon(AllBlocks.MECHANICAL_ARM) + .title("Busy Hands") + .description("Watch your Mechanical Arm transport its first item") + .after(SPEED_CONTROLLER) + .special(NOISY)), - CRAFTER = create("mechanical_crafter", b -> b.icon(AllBlocks.MECHANICAL_CRAFTER) - .title("Automated Assembly") - .description("Place and power some Mechanical Crafters") - .after(MECHANICAL_ARM)), + CRAFTER = create("mechanical_crafter", b -> b.icon(AllBlocks.MECHANICAL_CRAFTER) + .title("Automated Assembly") + .description("Place and power some Mechanical Crafters") + .after(MECHANICAL_ARM)), - CRUSHING_WHEEL = create("crushing_wheel", b -> b.icon(AllBlocks.CRUSHING_WHEEL) - .title("A Pair of Giants") - .description("Place and power a set of Crushing Wheels") - .after(CRAFTER) - .special(NOISY)), + CRUSHING_WHEEL = create("crushing_wheel", b -> b.icon(AllBlocks.CRUSHING_WHEEL) + .title("Wheels of Destruction") + .description("Place and power a set of Crushing Wheels") + .after(CRAFTER) + .special(NOISY)), - // Brass - Top Branch + // Brass - Top Branch - HAUNTED_BELL = create("haunted_bell", b -> b.icon(AllBlocks.HAUNTED_BELL) - .title("Shadow Sense") - .description("Toll a Haunted Bell") - .after(BRASS) - .special(NOISY)), + HAUNTED_BELL = create("haunted_bell", b -> b.icon(AllBlocks.HAUNTED_BELL) + .title("Shadow Sense") + .description("Toll a Haunted Bell") + .after(BRASS) + .special(NOISY)), - CLOCKWORK_BEARING = create("clockwork_bearing", b -> b.icon(AllBlocks.CLOCKWORK_BEARING) - .title("Contraption O'Clock") - .description("Assemble a structure mounted on a Clockwork Bearing") - .after(HAUNTED_BELL) - .special(NOISY)), + CLOCKWORK_BEARING = create("clockwork_bearing", b -> b.icon(AllBlocks.CLOCKWORK_BEARING) + .title("Contraption o'Clock") + .description("Assemble a structure mounted on a Clockwork Bearing") + .after(HAUNTED_BELL) + .special(NOISY)), - DISPLAY_LINK = create("display_link", b -> b.icon(AllBlocks.DISPLAY_LINK) - .title("Big Data") - .description("Use a Display Link to visualise information") - .after(CLOCKWORK_BEARING) - .special(NOISY)), + DISPLAY_LINK = create("display_link", b -> b.icon(AllBlocks.DISPLAY_LINK) + .title("Big Data") + .description("Use a Display Link to visualise information") + .after(CLOCKWORK_BEARING)), - POTATO_CANNON = create("potato_cannon", b -> b.icon(AllItems.POTATO_CANNON) - .title("Fwoomp!") - .description("Defeat an enemy with your Potato Cannon") - .after(DISPLAY_LINK) - .special(NOISY)), + POTATO_CANNON = create("potato_cannon", b -> b.icon(AllItems.POTATO_CANNON) + .title("Fwoomp!") + .description("Defeat an enemy with your Potato Cannon") + .after(DISPLAY_LINK) + .special(NOISY)), - EXTENDO_GRIP = create("extendo_grip", b -> b.icon(AllItems.EXTENDO_GRIP) - .title("Boioioing!") - .description("Get hold of an Extendo Grip") - .after(POTATO_CANNON)), + EXTENDO_GRIP = create("extendo_grip", b -> b.icon(AllItems.EXTENDO_GRIP) + .title("Boioioing!") + .description("Get hold of an Extendo Grip") + .after(POTATO_CANNON)), - LINKED_CONTROLLER = create("linked_controller", b -> b.icon(AllItems.LINKED_CONTROLLER) - .title("Remote Activation") - .description("Activate a Redstone Link using a Linked Controller") - .after(EXTENDO_GRIP)), + LINKED_CONTROLLER = create("linked_controller", b -> b.icon(AllItems.LINKED_CONTROLLER) + .title("Remote Activation") + .description("Activate a Redstone Link using a Linked Controller") + .after(EXTENDO_GRIP)), - ARM_BLAZE_BURNER = create("arm_blaze_burner", b -> b.icon(AllBlocks.BLAZE_BURNER) - .title("Combust-o-Tron") - .description("Instruct a Mechanical Arm to feed your Blaze Burner") - .after(LINKED_CONTROLLER)), + ARM_BLAZE_BURNER = create("arm_blaze_burner", b -> b.icon(AllBlocks.BLAZE_BURNER) + .title("Combust-o-Tron") + .description("Instruct a Mechanical Arm to feed your Blaze Burner") + .after(LINKED_CONTROLLER)), - // Brass - Expert Branch + // Brass - Expert Branch - CRUSHER_MAXED = create("crusher_maxed_0000", b -> b.icon(AllBlocks.CRUSHING_WHEEL) - .title("Crushing It") - .description("Operate a pair of Crushing Wheels at maximum speed") - .after(BRASS) - .special(EXPERT)), + CRUSHER_MAXED = create("crusher_maxed_0000", b -> b.icon(AllBlocks.CRUSHING_WHEEL) + .title("Crushing It") + .description("Operate a pair of Crushing Wheels at maximum speed") + .after(BRASS) + .special(EXPERT)), - ARM_MANY_TARGETS = create("arm_many_targets", b -> b.icon(AllBlocks.MECHANICAL_ARM) - .title("Organize-o-Tron") - .description("Program a Mechanical Arm with 10 or more output locations") - .after(CRUSHER_MAXED) - .special(EXPERT)), + ARM_MANY_TARGETS = create("arm_many_targets", b -> b.icon(AllBlocks.MECHANICAL_ARM) + .title("Organize-o-Tron") + .description("Program a Mechanical Arm with 10 or more output locations") + .after(CRUSHER_MAXED) + .special(EXPERT)), - POTATO_CANNON_COLLIDE = create("potato_cannon_collide", b -> b.icon(Items.CARROT) - .title("Veggie Fireworks") - .description("Cause Potato Cannon projectiles of different types to collide with each other") - .after(ARM_MANY_TARGETS) - .special(EXPERT)), + POTATO_CANNON_COLLIDE = create("potato_cannon_collide", b -> b.icon(Items.CARROT) + .title("Veggie Fireworks") + .description("Cause Potato Cannon projectiles of different types to collide with each other") + .after(ARM_MANY_TARGETS) + .special(EXPERT)), - SELF_DEPLOYING = create("self_deploying", b -> b.icon(Items.RAIL) - .title("Self-Driving Cart") - .description("Create a Minecart Contraption that places tracks in front of itself") - .after(POTATO_CANNON_COLLIDE) - .special(EXPERT)), + SELF_DEPLOYING = create("self_deploying", b -> b.icon(Items.RAIL) + .title("Self-Driving Cart") + .description("Create a Minecart Contraption that places tracks in front of itself") + .after(POTATO_CANNON_COLLIDE) + .special(EXPERT)), - // Brass - Hidden + // Brass - Hidden - FIST_BUMP = create("fist_bump", b -> b.icon(AllBlocks.DEPLOYER) - .title("Pound It, Bro!") - .description("Make two Deployers fist-bump") - .after(CRAFTER) - .special(SECRET)), + FIST_BUMP = create("fist_bump", b -> b.icon(AllBlocks.DEPLOYER) + .title("Pound It, Bro!") + .description("Make two Deployers fist-bump") + .after(CRAFTER) + .special(SECRET)), - CRAFTER_LAZY = create("crafter_lazy_000", b -> b.icon(AllBlocks.MECHANICAL_CRAFTER) - .title("Desperate Measures") - .description("Drastically slow down a Mechanical Crafter to procrastinate on proper infrastructure") - .after(CRAFTER) - .special(SECRET)), + CRAFTER_LAZY = create("crafter_lazy_000", b -> b.icon(AllBlocks.MECHANICAL_CRAFTER) + .title("Desperate Measures") + .description("Drastically slow down a Mechanical Crafter to procrastinate on proper infrastructure") + .after(CRAFTER) + .special(SECRET)), - EXTENDO_GRIP_DUAL = create("extendo_grip_dual", b -> b.icon(AllItems.EXTENDO_GRIP) - .title("To Full Extent") - .description("Dual-wield Extendo Grips for superhuman reach") - .after(CRAFTER) - .special(SECRET)), + EXTENDO_GRIP_DUAL = create("extendo_grip_dual", b -> b.icon(AllItems.EXTENDO_GRIP) + .title("To Full Extent") + .description("Dual-wield Extendo Grips for superhuman reach") + .after(CRAFTER) + .special(SECRET)), - MUSICAL_ARM = create("musical_arm", b -> b.icon(Blocks.JUKEBOX) - .title("DJ Mechanico") - .description("Watch a Mechanical Arm operate your Jukebox") - .after(CRAFTER) - .special(SECRET)), + MUSICAL_ARM = create("musical_arm", b -> b.icon(Blocks.JUKEBOX) + .title("DJ Mechanico") + .description("Watch a Mechanical Arm operate your Jukebox") + .after(CRAFTER) + .special(SECRET)), - // Trains - Central Branch + // Trains - Central Branch - STURDY_SHEET = create("sturdy_sheet", b -> b.icon(AllItems.STURDY_SHEET) - .title("The Sturdiest Rocks") - .description("Assemble a Sturdy Sheet by refining Powdered Obsidian") - .whenIconCollected() - .after(CRUSHING_WHEEL)), + STURDY_SHEET = create("sturdy_sheet", b -> b.icon(AllItems.STURDY_SHEET) + .title("The Sturdiest Rocks") + .description("Assemble a Sturdy Sheet by refining Powdered Obsidian") + .whenIconCollected() + .after(CRUSHING_WHEEL)), - TRAIN_CASING = create("train_casing_00", b -> b.icon(AllBlocks.RAILWAY_CASING) - .title("The Logistical Age") - .description("Use Sturdy Sheets to create a casing for railway components") - .after(STURDY_SHEET) - .special(NOISY)), + TRAIN_CASING = create("train_casing_00", b -> b.icon(AllBlocks.RAILWAY_CASING) + .title("The Locomotive Age") + .description("Use Sturdy Sheets to create a casing for railway components") + .after(STURDY_SHEET)), - TRAIN = create("train", b -> b.icon(AllBlocks.TRACK_STATION) - .title("All Aboard!") - .description("Assemble your first Train") - .after(TRAIN_CASING) - .special(NOISY)), + TRAIN = create("train", b -> b.icon(AllBlocks.TRACK_STATION) + .title("All Aboard!") + .description("Assemble your first Train") + .after(TRAIN_CASING) + .special(NOISY)), - CONDUCTOR = create("conductor", b -> b.icon(AllItems.SCHEDULE) - .title("Conductor Instructor") - .description("Instruct a Train driver with a Train Schedule") - .after(TRAIN)), + CONDUCTOR = create("conductor", b -> b.icon(AllItems.SCHEDULE) + .title("Conductor Instructor") + .description("Instruct a Train driver with a Train Schedule") + .after(TRAIN)), - SIGNAL = create("track_signal", b -> b.icon(AllBlocks.TRACK_SIGNAL) - .title("Traffic Control") - .description("Place a Train Signal") - .after(CONDUCTOR)), + SIGNAL = create("track_signal", b -> b.icon(AllBlocks.TRACK_SIGNAL) + .title("Traffic Control") + .description("Place a Train Signal") + .after(CONDUCTOR)), - DISPLAY_BOARD = create("display_board_0", b -> b.icon(AllBlocks.DISPLAY_BOARD) - .title("Dynamic Timetables") - .description("Forecast a Train's arrival on your Display Board with the help of Display Links") - .after(SIGNAL) - .special(NOISY)), + DISPLAY_BOARD = create("display_board_0", b -> b.icon(AllBlocks.DISPLAY_BOARD) + .title("Dynamic Timetables") + .description("Forecast a Train's arrival on your Display Board with the help of Display Links") + .after(SIGNAL) + .special(NOISY)), - // Trains - Top Branch + // Trains - Top Branch - TRAIN_TRACK = create("track_0", b -> b.icon(AllBlocks.TRACK) - .title("A New Gauge") - .description("Obtain some Train Tracks") - .whenItemCollected(AllItemTags.TRACKS.tag) - .after(STURDY_SHEET)), + TRAIN_TRACK = create("track_0", b -> b.icon(AllBlocks.TRACK) + .title("A New Gauge") + .description("Obtain some Train Tracks") + .whenItemCollected(AllItemTags.TRACKS.tag) + .after(STURDY_SHEET)), - TRAIN_WHISTLE = create("train_whistle", b -> b.icon(AllBlocks.STEAM_WHISTLE) - .title("Choo Choo!") - .description("Assemble a Steam Whistle to your Train and activate it while driving") - .after(TRAIN_TRACK)), + TRAIN_WHISTLE = create("train_whistle", b -> b.icon(AllBlocks.STEAM_WHISTLE) + .title("Choo Choo!") + .description("Assemble a Steam Whistle to your Train and activate it while driving") + .after(TRAIN_TRACK)), - TRAIN_PORTAL = create("train_portal", b -> b.icon(Blocks.AMETHYST_BLOCK) - .title("Dimensional Commuter") - .description("Ride a Train through a portal") - .after(TRAIN_WHISTLE) - .special(NOISY)), + TRAIN_PORTAL = create("train_portal", b -> b.icon(Blocks.AMETHYST_BLOCK) + .title("Dimensional Commuter") + .description("Ride a Train through a portal") + .after(TRAIN_WHISTLE) + .special(NOISY)), - // Trains - Expert Branch + // Trains - Expert Branch - TRACK_CRAFTING = create("track_crafting_factory", b -> b.icon(AllBlocks.MECHANICAL_PRESS) - .title("Track Factory") - .description("Produce more than 1000 Train Tracks with the same Mechanical Press") - .after(STURDY_SHEET) - .special(EXPERT)), + TRACK_CRAFTING = create("track_crafting_factory", b -> b.icon(AllBlocks.MECHANICAL_PRESS) + .title("Track Factory") + .description("Produce more than 1000 Train Tracks with the same Mechanical Press") + .after(STURDY_SHEET) + .special(EXPERT)), - LONG_TRAIN = create("long_train", b -> b.icon(Items.MINECART) - .title("Ambitious Endeavours") - .description("Create a Train with at least 6 carriages") - .after(TRACK_CRAFTING) - .special(EXPERT)), + LONG_TRAIN = create("long_train", b -> b.icon(Items.MINECART) + .title("Ambitious Endeavours") + .description("Create a Train with at least 6 carriages") + .after(TRACK_CRAFTING) + .special(EXPERT)), - LONG_TRAVEL = create("long_travel", b -> b.icon(AllBlocks.SEATS.get(DyeColor.GREEN)) - .title("Field Trip") - .description("Leave a Train Seat over 5000 blocks away from where you started travelling") - .after(LONG_TRAIN) - .special(EXPERT)), + LONG_TRAVEL = create("long_travel", b -> b.icon(AllBlocks.SEATS.get(DyeColor.GREEN)) + .title("Field Trip") + .description("Leave a Train Seat over 5000 blocks away from where you started travelling") + .after(LONG_TRAIN) + .special(EXPERT)), - // Trains - Hidden + // Trains - Hidden - TRAIN_ROADKILL = create("train_roadkill", b -> b.icon(Items.DIAMOND_SWORD) - .title("Road Kill") - .description("Run over an enemy with your Train") - .after(SIGNAL) - .special(SECRET)), + TRAIN_ROADKILL = create("train_roadkill", b -> b.icon(Items.DIAMOND_SWORD) + .title("Road Kill") + .description("Run over an enemy with your Train") + .after(SIGNAL) + .special(SECRET)), - RED_SIGNAL = create("red_signal", b -> b.icon(AllBlocks.TRACK_SIGNAL) - .title("Expert Driver") - .description("Run a red Train Signal") - .after(SIGNAL) - .special(SECRET)), + RED_SIGNAL = create("red_signal", b -> b.icon(AllBlocks.TRACK_SIGNAL) + .title("Expert Driver") + .description("Run a red Train Signal") + .after(SIGNAL) + .special(SECRET)), - TRAIN_CRASH = create("train_crash", b -> b.icon(AllItems.INCOMPLETE_TRACK) - .title("Terrible Service") - .description("Witness a Train crash as a passenger") - .after(SIGNAL) - .special(SECRET)), + TRAIN_CRASH = create("train_crash", b -> b.icon(AllItems.INCOMPLETE_TRACK) + .title("Terrible Service") + .description("Witness a Train crash as a passenger") + .after(SIGNAL) + .special(SECRET)), - TRAIN_CRASH_BACKWARDS = create("train_crash_backwards", b -> b.icon(AllItems.INCOMPLETE_TRACK) - .title("Blind Spot") - .description("Crash into another Train while driving backwards") - .after(SIGNAL) - .special(SECRET)), + TRAIN_CRASH_BACKWARDS = create("train_crash_backwards", b -> b.icon(AllItems.INCOMPLETE_TRACK) + .title("Blind Spot") + .description("Crash into another Train while driving backwards") + .after(SIGNAL) + .special(SECRET)), - // - END = null; + // + END = null; + + private static ItemStack createArmorTrimmedCardboardChestplate() { + ItemStack asStack = AllItems.CARDBOARD_CHESTPLATE.asStack(); + CompoundTag tag = new CompoundTag(); + CompoundTag trimTag = new CompoundTag(); + trimTag.putString("material", "minecraft:diamond"); + trimTag.putString("pattern", "minecraft:sentry"); + tag.put("Trim", trimTag); + asStack.setTag(tag); + return asStack; + } private static CreateAdvancement create(String id, UnaryOperator b) { return new CreateAdvancement(id, b); @@ -646,6 +714,7 @@ public class AllAdvancements implements DataProvider { advancement.provideLang(consumer); } - public static void register() {} + public static void register() { + } } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/CreateAdvancement.java b/src/main/java/com/simibubi/create/foundation/advancement/CreateAdvancement.java index ca5152bc36..cbfd86df9f 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/CreateAdvancement.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/CreateAdvancement.java @@ -5,7 +5,6 @@ import java.util.function.Consumer; import java.util.function.UnaryOperator; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.Components; import com.tterrag.registrate.util.entry.ItemProviderEntry; import net.minecraft.advancements.Advancement; @@ -17,6 +16,7 @@ import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.advancements.critereon.ItemUsedOnLocationTrigger; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.advancements.critereon.NbtPredicate; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; @@ -54,8 +54,8 @@ public class CreateAdvancement { builder.addCriterion("0", builtinTrigger.instance()); } - builder.display(t.icon, Components.translatable(titleKey()), - Components.translatable(descriptionKey()).withStyle(s -> s.withColor(0xDBA213)), + builder.display(t.icon, Component.translatable(titleKey()), + Component.translatable(descriptionKey()).withStyle(s -> s.withColor(0xDBA213)), id.equals("root") ? BACKGROUND : null, t.type.frame, t.type.toast, t.type.announce, t.type.hide); if (t.type == TaskType.SECRET) diff --git a/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java b/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java index 302d185eb5..191d2aa5b9 100644 --- a/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java +++ b/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java @@ -1,9 +1,9 @@ package com.simibubi.create.foundation.block; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.RaycastHelper; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.math.VecHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -34,7 +34,7 @@ public class BigOutlines { double maxRange = mc.hitResult == null ? Double.MAX_VALUE : mc.hitResult.getLocation() - .distanceToSqr(origin); + .distanceToSqr(origin) + 0.5; AttributeInstance range = player.getAttribute(ForgeMod.BLOCK_REACH.get()); Vec3 target = RaycastHelper.getTraceTarget(player, Math.min(maxRange, range.getValue()) + 1, origin); diff --git a/src/main/java/com/simibubi/create/foundation/block/CopperBlockSet.java b/src/main/java/com/simibubi/create/foundation/block/CopperBlockSet.java index 2aca149ad7..24704b5467 100644 --- a/src/main/java/com/simibubi/create/foundation/block/CopperBlockSet.java +++ b/src/main/java/com/simibubi/create/foundation/block/CopperBlockSet.java @@ -7,14 +7,9 @@ import java.util.Map; import java.util.Objects; import java.util.function.Supplier; -import net.minecraft.tags.ItemTags; - import org.apache.commons.lang3.ArrayUtils; import com.simibubi.create.foundation.data.TagGen; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.RegisteredObjects; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.providers.DataGenContext; @@ -26,6 +21,9 @@ import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.nullness.NonNullBiConsumer; import com.tterrag.registrate.util.nullness.NonNullFunction; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.ShapelessRecipeBuilder; import net.minecraft.resources.ResourceLocation; @@ -41,6 +39,7 @@ import net.minecraft.world.level.block.WeatheringCopperSlabBlock; import net.minecraft.world.level.block.WeatheringCopperStairBlock; import net.minecraft.world.level.block.state.BlockBehaviour.Properties; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.client.model.generators.ModelProvider; import net.minecraftforge.fml.util.ObfuscationReflectionHelper; @@ -49,6 +48,7 @@ public class CopperBlockSet { protected static final int WEATHER_STATE_COUNT = WEATHER_STATES.length; protected static final Map> BASE_BLOCKS = new EnumMap<>(WeatherState.class); + static { BASE_BLOCKS.put(WeatherState.UNAFFECTED, () -> Blocks.COPPER_BLOCK); BASE_BLOCKS.put(WeatherState.EXPOSED, () -> Blocks.EXPOSED_COPPER); @@ -57,7 +57,7 @@ public class CopperBlockSet { } public static final Variant[] DEFAULT_VARIANTS = - new Variant[] { BlockVariant.INSTANCE, SlabVariant.INSTANCE, StairVariant.INSTANCE }; + new Variant[]{BlockVariant.INSTANCE, SlabVariant.INSTANCE, StairVariant.INSTANCE}; protected final String name; protected final String generalDirectory; // Leave empty for root folder @@ -65,26 +65,33 @@ public class CopperBlockSet { protected final Map, BlockEntry[]> entries = new HashMap<>(); protected final NonNullBiConsumer, RegistrateRecipeProvider> mainBlockRecipe; protected final String endTextureName; + protected final NonNullBiConsumer onRegister; public CopperBlockSet(AbstractRegistrate registrate, String name, String endTextureName, Variant[] variants) { - this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), "copper/"); + this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), "copper/", NonNullBiConsumer.noop()); } public CopperBlockSet(AbstractRegistrate registrate, String name, String endTextureName, Variant[] variants, String generalDirectory) { - this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), generalDirectory); + this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), generalDirectory, NonNullBiConsumer.noop()); } public CopperBlockSet(AbstractRegistrate registrate, String name, String endTextureName, Variant[] variants, NonNullBiConsumer, RegistrateRecipeProvider> mainBlockRecipe) { - this(registrate, name, endTextureName, variants, mainBlockRecipe, "copper/"); + this(registrate, name, endTextureName, variants, mainBlockRecipe, "copper/", NonNullBiConsumer.noop()); + } + + public CopperBlockSet(AbstractRegistrate registrate, String name, String endTextureName, Variant[] variants, NonNullBiConsumer, RegistrateRecipeProvider> mainBlockRecipe, NonNullBiConsumer onRegister) { + this(registrate, name, endTextureName, variants, mainBlockRecipe, "copper/", onRegister); } public CopperBlockSet(AbstractRegistrate registrate, String name, String endTextureName, Variant[] variants, - NonNullBiConsumer, RegistrateRecipeProvider> mainBlockRecipe, String generalDirectory) { + NonNullBiConsumer, RegistrateRecipeProvider> mainBlockRecipe, String generalDirectory, NonNullBiConsumer onRegister) { this.name = name; this.generalDirectory = generalDirectory; this.endTextureName = endTextureName; this.variants = variants; this.mainBlockRecipe = mainBlockRecipe; + this.onRegister = onRegister; + for (boolean waxed : Iterate.falseAndTrue) { for (Variant variant : this.variants) { BlockEntry[] entries = @@ -109,7 +116,7 @@ public class CopperBlockSet { } protected BlockEntry createEntry(AbstractRegistrate registrate, Variant variant, - WeatherState state, boolean waxed) { + WeatherState state, boolean waxed) { String name = ""; if (waxed) { name += "waxed_"; @@ -130,6 +137,7 @@ public class CopperBlockSet { .blockstate((ctx, prov) -> variant.generateBlockState(ctx, prov, this, state, waxed)) .recipe((c, p) -> variant.generateRecipes(entries.get(BlockVariant.INSTANCE)[state.ordinal()], c, p)) .transform(TagGen.pickaxeOnly()) + .onRegister(block -> onRegister.accept(state, block)) .tag(BlockTags.NEEDS_STONE_TOOL) .simpleItem(); @@ -203,20 +211,21 @@ public class CopperBlockSet { NonNullFunction getFactory(CopperBlockSet blocks, WeatherState state, boolean waxed); default void generateLootTable(RegistrateBlockLootTables lootTable, T block, CopperBlockSet blocks, - WeatherState state, boolean waxed) { + WeatherState state, boolean waxed) { lootTable.dropSelf(block); } void generateRecipes(BlockEntry blockVariant, DataGenContext ctx, RegistrateRecipeProvider prov); void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, CopperBlockSet blocks, - WeatherState state, boolean waxed); + WeatherState state, boolean waxed); } public static class BlockVariant implements Variant { public static final BlockVariant INSTANCE = new BlockVariant(); - protected BlockVariant() {} + protected BlockVariant() { + } @Override public String getSuffix() { @@ -234,9 +243,9 @@ public class CopperBlockSet { @Override public void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, - CopperBlockSet blocks, WeatherState state, boolean waxed) { + CopperBlockSet blocks, WeatherState state, boolean waxed) { Block block = ctx.get(); - String path = RegisteredObjects.getKeyOrThrow(block) + String path = CatnipServices.REGISTRIES.getKeyOrThrow(block) .getPath(); String baseLoc = ModelProvider.BLOCK_FOLDER + "/" + blocks.generalDirectory + getWeatherStatePrefix(state); @@ -248,21 +257,23 @@ public class CopperBlockSet { // End texture and base texture aren't equal, so we should use cube_column. ResourceLocation endTexture = prov.modLoc(baseLoc + blocks.getEndTextureName()); prov.simpleBlock(block, prov.models() - .cubeColumn(path, texture, endTexture)); + .cubeColumn(path, texture, endTexture)); } } @Override public void generateRecipes(BlockEntry blockVariant, DataGenContext ctx, - RegistrateRecipeProvider prov) {} + RegistrateRecipeProvider prov) { + } } public static class SlabVariant implements Variant { public static final SlabVariant INSTANCE = new SlabVariant(); - protected SlabVariant() {} + protected SlabVariant() { + } @Override public String getSuffix() { @@ -271,7 +282,7 @@ public class CopperBlockSet { @Override public NonNullFunction getFactory(CopperBlockSet blocks, WeatherState state, - boolean waxed) { + boolean waxed) { if (waxed) { return SlabBlock::new; } else { @@ -281,13 +292,13 @@ public class CopperBlockSet { @Override public void generateLootTable(RegistrateBlockLootTables lootTable, SlabBlock block, CopperBlockSet blocks, - WeatherState state, boolean waxed) { + WeatherState state, boolean waxed) { lootTable.add(block, lootTable.createSlabItemTable(block)); } @Override public void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, - CopperBlockSet blocks, WeatherState state, boolean waxed) { + CopperBlockSet blocks, WeatherState state, boolean waxed) { ResourceLocation fullModel = prov.modLoc(ModelProvider.BLOCK_FOLDER + "/" + getWeatherStatePrefix(state) + blocks.getName()); @@ -300,7 +311,7 @@ public class CopperBlockSet { @Override public void generateRecipes(BlockEntry blockVariant, DataGenContext ctx, - RegistrateRecipeProvider prov) { + RegistrateRecipeProvider prov) { prov.slab(DataIngredient.items(blockVariant.get()), RecipeCategory.BUILDING_BLOCKS, ctx::get, null, true); } } @@ -321,7 +332,7 @@ public class CopperBlockSet { @Override public NonNullFunction getFactory(CopperBlockSet blocks, WeatherState state, - boolean waxed) { + boolean waxed) { if (!blocks.hasVariant(parent)) { throw new IllegalStateException( "Cannot add StairVariant '" + toString() + "' without parent Variant '" + parent.toString() + "'!"); @@ -345,7 +356,7 @@ public class CopperBlockSet { @Override public void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, - CopperBlockSet blocks, WeatherState state, boolean waxed) { + CopperBlockSet blocks, WeatherState state, boolean waxed) { String baseLoc = ModelProvider.BLOCK_FOLDER + "/" + blocks.generalDirectory + getWeatherStatePrefix(state); ResourceLocation texture = prov.modLoc(baseLoc + blocks.getName()); ResourceLocation endTexture = prov.modLoc(baseLoc + blocks.getEndTextureName()); @@ -354,7 +365,7 @@ public class CopperBlockSet { @Override public void generateRecipes(BlockEntry blockVariant, DataGenContext ctx, - RegistrateRecipeProvider prov) { + RegistrateRecipeProvider prov) { prov.stairs(DataIngredient.items(blockVariant.get()), RecipeCategory.BUILDING_BLOCKS, ctx::get, null, true); } } diff --git a/src/main/java/com/simibubi/create/foundation/block/IBE.java b/src/main/java/com/simibubi/create/foundation/block/IBE.java index b616490d45..c2a21d67d1 100644 --- a/src/main/java/com/simibubi/create/foundation/block/IBE.java +++ b/src/main/java/com/simibubi/create/foundation/block/IBE.java @@ -38,7 +38,7 @@ public interface IBE extends EntityBlock { * if the IBE is bound to a SmartBlockEntity, which implements destroy(),
* call this method in BlockBehaviour::onRemove (replace super call) */ - public static void onRemove(BlockState blockState, Level level, BlockPos pos, BlockState newBlockState) { + static void onRemove(BlockState blockState, Level level, BlockPos pos, BlockState newBlockState) { if (!blockState.hasBlockEntity()) return; if (blockState.is(newBlockState.getBlock()) && newBlockState.hasBlockEntity()) diff --git a/src/main/java/com/simibubi/create/foundation/block/IHaveBigOutline.java b/src/main/java/com/simibubi/create/foundation/block/IHaveBigOutline.java index 60de01e5e0..8d2c95e539 100644 --- a/src/main/java/com/simibubi/create/foundation/block/IHaveBigOutline.java +++ b/src/main/java/com/simibubi/create/foundation/block/IHaveBigOutline.java @@ -1,11 +1,12 @@ package com.simibubi.create.foundation.block; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import com.simibubi.create.content.trains.track.TrackBlock; + import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockBehaviour; -import com.simibubi.create.content.trains.track.TrackBlock; -import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import net.minecraft.world.level.block.state.BlockState; /** * Implementing this interface will allow you to have bigger outlines when overriding {@link BlockBehaviour#getInteractionShape(BlockState, BlockGetter, BlockPos)} diff --git a/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java b/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java index 8200269253..9da6425598 100644 --- a/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java +++ b/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java @@ -4,9 +4,9 @@ import java.util.HashSet; import java.util.Set; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.simibubi.create.foundation.utility.VecHelper; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.math.VecHelper; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionResult; import net.minecraft.world.level.block.Block; @@ -22,7 +22,7 @@ public class ItemUseOverrides { private static final Set OVERRIDES = new HashSet<>(); public static void addBlock(Block block) { - OVERRIDES.add(RegisteredObjects.getKeyOrThrow(block)); + OVERRIDES.add(CatnipServices.REGISTRIES.getKeyOrThrow(block)); } @SubscribeEvent @@ -32,7 +32,7 @@ public class ItemUseOverrides { BlockState state = event.getLevel() .getBlockState(event.getPos()); - ResourceLocation id = RegisteredObjects.getKeyOrThrow(state.getBlock()); + ResourceLocation id = CatnipServices.REGISTRIES.getKeyOrThrow(state.getBlock()); if (!OVERRIDES.contains(id)) return; diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/AllCTTypes.java b/src/main/java/com/simibubi/create/foundation/block/connected/AllCTTypes.java index c0bec9a52b..b8246c7f5b 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/AllCTTypes.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/AllCTTypes.java @@ -3,8 +3,8 @@ package com.simibubi.create.foundation.block.connected; import com.simibubi.create.Create; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.ContextRequirement; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.resources.ResourceLocation; public enum AllCTTypes implements CTType { @@ -89,6 +89,71 @@ public enum AllCTTypes implements CTType { return tileX + 8 * tileY; } }, + ROOF(4, ContextRequirement.builder().all().build()) { + @Override + public int getTextureIndex(CTContext context) { + boolean upDrops = context.down && !context.up && (context.left || context.right); + boolean downDrops = !context.down && context.up && (context.left || context.right); + boolean leftDrops = !context.left && context.right && (context.up || context.down); + boolean rightDrops = context.left && !context.right && (context.up || context.down); + + if (upDrops) { + if (leftDrops) + return context.bottomRight ? 0 : 5; + if (rightDrops) + return context.bottomLeft ? 2 : 5; + return 1; + } + + if (downDrops) { + if (leftDrops) + return context.topRight ? 8 : 5; + if (rightDrops) + return context.topLeft ? 10 : 5; + return 9; + } + + if (leftDrops) + return 4; + if (rightDrops) + return 6; + + if (!context.up || !context.down || !context.left || !context.right) + return 5; + + if (context.bottomLeft && context.topRight) { + if (context.topLeft && !context.bottomRight) + return 12; + if (context.bottomRight && !context.topLeft) + return 15; + if (!context.bottomRight && !context.topLeft) + return 7; + } + + if (context.bottomRight && context.topLeft) { + if (context.topRight && !context.bottomLeft) + return 13; + if (context.bottomLeft && !context.topRight) + return 14; + if (!context.bottomLeft && !context.topRight) + return 11; + } + + return 5; + } + }, + ROOF_STAIR(4, ContextRequirement.builder() + .axisAligned() + .build()) { + private static final int[][] MAPPING = { { 1, 6, 9, 4 }, { 14, 12, 13, 15 }, { 2, 10, 8, 0 }, { 5, 5, 5, 5 } }; + + @Override + public int getTextureIndex(CTContext context) { + int type = (context.up ? 2 : 0) + (context.right ? 1 : 0); + int rot = (context.left ? 2 : 0) + (context.down ? 1 : 0); + return MAPPING[type][rot]; + } + }, CROSS(4, ContextRequirement.builder().axisAligned().build()) { @Override public int getTextureIndex(CTContext context) { diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java b/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java index a9ef18947b..73f028934b 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java @@ -8,8 +8,8 @@ import com.simibubi.create.content.decoration.copycat.CopycatBlock; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext; import com.simibubi.create.foundation.model.BakedModelWrapperWithData; import com.simibubi.create.foundation.model.BakedQuadHelper; -import com.simibubi.create.foundation.utility.Iterate; +import net.createmod.catnip.data.Iterate; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; @@ -76,7 +76,7 @@ public class CTModel extends BakedModelWrapperWithData { if (index == -1) continue; - CTSpriteShiftEntry spriteShift = behaviour.getShift(state, quad.getDirection(), quad.getSprite()); + CTSpriteShiftEntry spriteShift = behaviour.getShift(state, rand, quad.getDirection(), quad.getSprite()); if (spriteShift == null) continue; if (quad.getSprite() != spriteShift.getOriginal()) diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java index eea270bc45..1b3e4c03d9 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.block.connected; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import net.createmod.catnip.render.SpriteShiftEntry; public class CTSpriteShiftEntry extends SpriteShiftEntry { diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java index 7fb456fb83..0752e5525a 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java @@ -3,23 +3,20 @@ package com.simibubi.create.foundation.block.connected; import java.util.HashMap; import java.util.Map; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; - +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; public class CTSpriteShifter { - private static final Map ENTRY_CACHE = new HashMap<>(); + private static final Map ENTRY_CACHE = new HashMap<>(); public static CTSpriteShiftEntry getCT(CTType type, ResourceLocation blockTexture, ResourceLocation connectedTexture) { String key = blockTexture + "->" + connectedTexture + "+" + type.getId(); if (ENTRY_CACHE.containsKey(key)) - return (CTSpriteShiftEntry) ENTRY_CACHE.get(key); + return ENTRY_CACHE.get(key); CTSpriteShiftEntry entry = new CTSpriteShiftEntry(type); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> entry.set(blockTexture, connectedTexture)); + CatnipServices.PLATFORM.executeOnClientOnly(() -> () -> entry.set(blockTexture, connectedTexture)); ENTRY_CACHE.put(key, entry); return entry; } diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java b/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java index 14ddabc41a..d6ca27b432 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java @@ -8,12 +8,19 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; public abstract class ConnectedTextureBehaviour { + @Nullable + public CTSpriteShiftEntry getShift(BlockState state, RandomSource rand, Direction direction, + @NotNull TextureAtlasSprite sprite) { + return getShift(state, direction, sprite); + } + @Nullable public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, @NotNull TextureAtlasSprite sprite); diff --git a/src/main/java/com/simibubi/create/foundation/block/render/BlockDestructionProgressExtension.java b/src/main/java/com/simibubi/create/foundation/block/render/BlockDestructionProgressExtension.java index 2a7bca863f..1948efe36d 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/BlockDestructionProgressExtension.java +++ b/src/main/java/com/simibubi/create/foundation/block/render/BlockDestructionProgressExtension.java @@ -8,7 +8,7 @@ import net.minecraft.core.BlockPos; public interface BlockDestructionProgressExtension { @Nullable - Set getExtraPositions(); + Set create$getExtraPositions(); - void setExtraPositions(@Nullable Set positions); + void create$setExtraPositions(@Nullable Set positions); } diff --git a/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java b/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java index 534958cd5f..b66b63faed 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java +++ b/src/main/java/com/simibubi/create/foundation/block/render/ReducedDestroyEffects.java @@ -10,15 +10,15 @@ import net.minecraft.util.Mth; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraftforge.client.extensions.common.IClientBlockExtensions; public class ReducedDestroyEffects implements IClientBlockExtensions { @Override public boolean addDestroyEffects(BlockState state, Level worldIn, BlockPos pos, ParticleEngine manager) { - if (!(worldIn instanceof ClientLevel)) + if (!(worldIn instanceof ClientLevel world)) return true; - ClientLevel world = (ClientLevel) worldIn; VoxelShape voxelshape = state.getShape(world, pos); MutableInt amtBoxes = new MutableInt(0); voxelshape.forAllBoxes((x1, y1, z1, x2, y2, z2) -> amtBoxes.increment()); diff --git a/src/main/java/com/simibubi/create/foundation/block/render/SpriteShiftEntry.java b/src/main/java/com/simibubi/create/foundation/block/render/SpriteShiftEntry.java deleted file mode 100644 index 8d3d3a948d..0000000000 --- a/src/main/java/com/simibubi/create/foundation/block/render/SpriteShiftEntry.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.simibubi.create.foundation.block.render; - -import com.simibubi.create.foundation.render.StitchedSprite; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.resources.ResourceLocation; - -public class SpriteShiftEntry { - protected StitchedSprite original; - protected StitchedSprite target; - - public void set(ResourceLocation originalTextureLocation, ResourceLocation targetTextureLocation) { - original = new StitchedSprite(originalTextureLocation); - target = new StitchedSprite(targetTextureLocation); - } - - public ResourceLocation getOriginalResourceLocation() { - return original.getLocation(); - } - - public ResourceLocation getTargetResourceLocation() { - return target.getLocation(); - } - - public TextureAtlasSprite getOriginal() { - return original.get(); - } - - public TextureAtlasSprite getTarget() { - return target.get(); - } - - public float getTargetU(float localU) { - return getTarget().getU(getUnInterpolatedU(getOriginal(), localU)); - } - - public float getTargetV(float localV) { - return getTarget().getV(getUnInterpolatedV(getOriginal(), localV)); - } - - public static float getUnInterpolatedU(TextureAtlasSprite sprite, float u) { - float f = sprite.getU1() - sprite.getU0(); - return (u - sprite.getU0()) / f * 16.0F; - } - - public static float getUnInterpolatedV(TextureAtlasSprite sprite, float v) { - float f = sprite.getV1() - sprite.getV0(); - return (v - sprite.getV0()) / f * 16.0F; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/block/render/SpriteShifter.java b/src/main/java/com/simibubi/create/foundation/block/render/SpriteShifter.java deleted file mode 100644 index a9bcb3644b..0000000000 --- a/src/main/java/com/simibubi/create/foundation/block/render/SpriteShifter.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.simibubi.create.foundation.block.render; - -import java.util.HashMap; -import java.util.Map; - -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; - -public class SpriteShifter { - - private static final Map ENTRY_CACHE = new HashMap<>(); - - public static SpriteShiftEntry get(ResourceLocation originalLocation, ResourceLocation targetLocation) { - String key = originalLocation + "->" + targetLocation; - if (ENTRY_CACHE.containsKey(key)) - return ENTRY_CACHE.get(key); - - SpriteShiftEntry entry = new SpriteShiftEntry(); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> entry.set(originalLocation, targetLocation)); - ENTRY_CACHE.put(key, entry); - return entry; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntity.java b/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntity.java index f5a8a4fa69..b81fd26a9e 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntity.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntity.java @@ -2,35 +2,37 @@ package com.simibubi.create.foundation.blockEntity; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; import com.simibubi.create.api.event.BlockEntityBehaviourEvent; -import com.simibubi.create.content.schematics.requirement.ISpecialBlockEntityItemRequirement; +import com.simibubi.create.api.schematic.nbt.PartialSafeNBT; +import com.simibubi.create.api.schematic.requirement.SpecialBlockEntityItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.CreateAdvancement; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.IInteractionChecker; -import com.simibubi.create.foundation.utility.IPartialSafeNBT; +import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; +import net.createmod.ponder.api.VirtualBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; + import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity - implements IPartialSafeNBT, IInteractionChecker, ISpecialBlockEntityItemRequirement { + implements PartialSafeNBT, IInteractionChecker, SpecialBlockEntityItemRequirement, VirtualBlockEntity { - private final Map, BlockEntityBehaviour> behaviours = new HashMap<>(); + private final Map, BlockEntityBehaviour> behaviours = new Reference2ObjectArrayMap<>(); private boolean initialized = false; private boolean firstNbtRead = true; protected int lazyTickRate; @@ -97,7 +99,7 @@ public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity super.saveAdditional(tag); forEachBehaviour(tb -> { if (tb.isSafeNBT()) - tb.write(tag, false); + tb.writeSafe(tag); }); } @@ -183,8 +185,9 @@ public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity return behaviours.values(); } - protected void attachBehaviourLate(BlockEntityBehaviour behaviour) { + public void attachBehaviourLate(BlockEntityBehaviour behaviour) { behaviours.put(behaviour.getType(), behaviour); + behaviour.blockEntity = this; behaviour.initialize(); } @@ -193,7 +196,7 @@ public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity .reduce(ItemRequirement.NONE, (r, b) -> r.union(b.getRequiredItems()), (r, r1) -> r.union(r1)); } - protected void removeBehaviour(BehaviourType type) { + public void removeBehaviour(BehaviourType type) { BlockEntityBehaviour remove = behaviours.remove(type); if (remove != null) { remove.unload(); diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour.java index d52125dea1..1935af6e62 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour.java @@ -45,6 +45,13 @@ public abstract class BlockEntityBehaviour { } + /** + * Called when isSafeNBT == true. Defaults to write() + */ + public void writeSafe(CompoundTag nbt) { + write(nbt, false); + } + public boolean isSafeNBT() { return false; } @@ -64,12 +71,14 @@ public abstract class BlockEntityBehaviour { /** * Block destroyed or Chunk unloaded. Usually invalidates capabilities */ - public void unload() {} + public void unload() { + } /** * Block destroyed or removed. Requires block to call ITE::onRemove */ - public void destroy() {} + public void destroy() { + } public void setLazyTickRate(int slowTickRate) { this.lazyTickRate = slowTickRate; @@ -101,9 +110,8 @@ public abstract class BlockEntityBehaviour { public static T get(BlockEntity be, BehaviourType type) { if (be == null) return null; - if (!(be instanceof SmartBlockEntity)) + if (!(be instanceof SmartBlockEntity ste)) return null; - SmartBlockEntity ste = (SmartBlockEntity) be; return ste.getBehaviour(type); } } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/CenteredSideValueBoxTransform.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/CenteredSideValueBoxTransform.java index 6ecd7615ef..8133079fe0 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/CenteredSideValueBoxTransform.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/CenteredSideValueBoxTransform.java @@ -2,8 +2,7 @@ package com.simibubi.create.foundation.blockEntity.behaviour; import java.util.function.BiPredicate; -import com.simibubi.create.foundation.utility.VecHelper; - +import net.createmod.catnip.math.VecHelper; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -15,7 +14,7 @@ public class CenteredSideValueBoxTransform extends ValueBoxTransform.Sided { public CenteredSideValueBoxTransform() { this((b, d) -> true); } - + public CenteredSideValueBoxTransform(BiPredicate allowedDirections) { this.allowedDirections = allowedDirections; } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBox.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBox.java index 7a3b9abb0b..a7f6a31be0 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBox.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBox.java @@ -1,14 +1,15 @@ package com.simibubi.create.foundation.blockEntity.behaviour; +import java.lang.ref.WeakReference; + import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.outliner.ChasingAABBOutline; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.Components; +import net.createmod.catnip.outliner.ChasingAABBOutline; +import net.createmod.catnip.render.SuperRenderTypeBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.LightTexture; @@ -16,8 +17,11 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -25,16 +29,18 @@ import net.minecraft.world.phys.Vec3; public class ValueBox extends ChasingAABBOutline { protected Component label; - protected Component sublabel = Components.immutableEmpty(); - protected Component scrollTooltip = Components.immutableEmpty(); + protected Component sublabel = CommonComponents.EMPTY; + protected Component scrollTooltip = CommonComponents.EMPTY; protected Vec3 labelOffset = Vec3.ZERO; public int overrideColor = -1; - + public boolean isPassive; - protected BlockPos pos; protected ValueBoxTransform transform; + + protected WeakReference level; + protected BlockPos pos; protected BlockState blockState; protected AllIcons outline = AllIcons.VALUE_BOX_HOVER_4PX; @@ -48,6 +54,7 @@ public class ValueBox extends ChasingAABBOutline { this.label = label; this.pos = pos; this.blockState = state; + this.level = new WeakReference<>(Minecraft.getInstance().level); } public ValueBox transform(ValueBoxTransform transform) { @@ -64,7 +71,7 @@ public class ValueBox extends ChasingAABBOutline { this.isPassive = passive; return this; } - + public ValueBox withColor(int color) { this.overrideColor = color; return this; @@ -75,13 +82,15 @@ public class ValueBox extends ChasingAABBOutline { boolean hasTransform = transform != null; if (transform instanceof Sided && params.getHighlightedFace() != null) ((Sided) transform).fromSide(params.getHighlightedFace()); - if (hasTransform && !transform.shouldRender(blockState)) + + LevelAccessor levelAccessor = level.get(); + if (hasTransform && !transform.shouldRender(levelAccessor, pos, blockState)) return; ms.pushPose(); ms.translate(pos.getX() - camera.x, pos.getY() - camera.y, pos.getZ() - camera.z); if (hasTransform) - transform.transform(blockState, ms); + transform.transform(levelAccessor, pos, blockState, ms); if (!isPassive) { ms.pushPose(); @@ -94,7 +103,7 @@ public class ValueBox extends ChasingAABBOutline { float fontScale = hasTransform ? -transform.getFontScale() : -1 / 64f; ms.scale(fontScale, fontScale, fontScale); renderContents(ms, buffer); - + ms.popPose(); } @@ -102,18 +111,17 @@ public class ValueBox extends ChasingAABBOutline { return outline; } - public void renderContents(PoseStack ms, MultiBufferSource buffer) {} + public void renderContents(PoseStack ms, MultiBufferSource buffer) { + } public static class ItemValueBox extends ValueBox { ItemStack stack; - int count; - boolean upTo; + MutableComponent count; - public ItemValueBox(Component label, AABB bb, BlockPos pos, ItemStack stack, int count, boolean upTo) { + public ItemValueBox(Component label, AABB bb, BlockPos pos, ItemStack stack, MutableComponent count) { super(label, bb, pos); this.stack = stack; this.count = count; - this.upTo = upTo; } @Override @@ -126,12 +134,10 @@ public class ValueBox extends ChasingAABBOutline { @Override public void renderContents(PoseStack ms, MultiBufferSource buffer) { super.renderContents(ms, buffer); - if (count == -1) + if (count == null) return; Font font = Minecraft.getInstance().font; - boolean wildcard = count == 0 || upTo && count >= stack.getMaxStackSize(); - Component countString = Components.literal(wildcard ? "*" : count + ""); ms.translate(17.5f, -5f, 7f); boolean isFilter = stack.getItem() instanceof FilterItem; @@ -144,7 +150,7 @@ public class ValueBox extends ChasingAABBOutline { .size() <= 1; float scale = 1.5f; - ms.translate(-font.width(countString), 0, 0); + ms.translate(-font.width(count), 0, 0); if (isFilter) ms.translate(-5, 8, 7.25f); @@ -154,13 +160,12 @@ public class ValueBox extends ChasingAABBOutline { } else ms.translate(-7, 10, blockItem ? 10 + 1 / 4f : 0); - if (wildcard) + if (count.getString() + .equals("*")) ms.translate(-1, 3f, 0); ms.scale(scale, scale, scale); - drawString(ms, buffer, countString, 0, 0, isFilter ? 0xFFFFFF : 0xEDEDED); - ms.translate(0, 0, -1 / 16f); - drawString(ms, buffer, countString, 1 - 1 / 8f, 1 - 1 / 8f, 0x4F4F4F); + drawString8x(ms, buffer, count, 0, 0, isFilter ? 0xFFFFFF : 0xEDEDED); } } @@ -197,7 +202,10 @@ public class ValueBox extends ChasingAABBOutline { ms.translate(singleDigit ? stringWidth / 2 : 0, singleDigit ? -verticalMargin : verticalMargin, 0); int overrideColor = transform.getOverrideColor(); - renderHoveringText(ms, buffer, text, overrideColor != -1 ? overrideColor : 0xEDEDED); + if (overrideColor == -1) + drawString8x(ms, buffer, text, 0, 0, 0xEDEDED); + else + drawString(ms, buffer, text, 0, 0, overrideColor); } } @@ -216,23 +224,23 @@ public class ValueBox extends ChasingAABBOutline { float scale = 2 * 16; ms.scale(scale, scale, scale); ms.translate(-.5f, -.5f, 5 / 32f); - + int overrideColor = transform.getOverrideColor(); icon.render(ms, buffer, overrideColor != -1 ? overrideColor : 0xFFFFFF); } } - protected void renderHoveringText(PoseStack ms, MultiBufferSource buffer, Component text, int color) { - ms.pushPose(); - drawString(ms, buffer, text, 0, 0, color); - ms.popPose(); - } - private static void drawString(PoseStack ms, MultiBufferSource buffer, Component text, float x, float y, - int color) { + int color) { Minecraft.getInstance().font.drawInBatch(text, x, y, color, false, ms.last() .pose(), buffer, Font.DisplayMode.NORMAL, 0, LightTexture.FULL_BRIGHT); } + private static void drawString8x(PoseStack ms, MultiBufferSource buffer, Component text, float x, float y, + int color) { + Minecraft.getInstance().font.drawInBatch8xOutline(text.getVisualOrderText(), x, y, color, 0xff333333, ms.last() + .pose(), buffer, LightTexture.FULL_BRIGHT); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxRenderer.java index fc60eb4e41..2a20d8fdb5 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxRenderer.java @@ -34,7 +34,7 @@ public class ValueBoxRenderer { float zOffset = (!blockItem ? -.15f : 0) + customZOffset(filter.getItem()); ms.scale(scale, scale, scale); ms.translate(0, 0, zOffset); - itemRenderer.renderStatic(filter, ItemDisplayContext.FIXED, light, overlay, ms, buffer, mc.level, 0); + itemRenderer.render(filter, ItemDisplayContext.FIXED, false, ms, buffer, light, overlay, modelWithOverrides); } public static void renderFlatItemIntoValueBox(ItemStack filter, PoseStack ms, MultiBufferSource buffer, int light, diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxTransform.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxTransform.java index 0082e4b27b..988bafcea0 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxTransform.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxTransform.java @@ -5,12 +5,14 @@ import java.util.function.Function; import org.apache.commons.lang3.tuple.Pair; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.math.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.Vec3; @@ -19,28 +21,28 @@ public abstract class ValueBoxTransform { protected float scale = getScale(); - public abstract Vec3 getLocalOffset(BlockState state); + public abstract Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state); - public abstract void rotate(BlockState state, PoseStack ms); + public abstract void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms); - public boolean testHit(BlockState state, Vec3 localHit) { - Vec3 offset = getLocalOffset(state); + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(level, pos, state); if (offset == null) return false; return localHit.distanceTo(offset) < scale / 2; } - public void transform(BlockState state, PoseStack ms) { - Vec3 position = getLocalOffset(state); + public void transform(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { + Vec3 position = getLocalOffset(level, pos, state); if (position == null) return; ms.translate(position.x, position.y, position.z); - rotate(state, ms); + rotate(level, pos, state, ms); ms.scale(scale, scale, scale); } - public boolean shouldRender(BlockState state) { - return !state.isAir() && getLocalOffset(state) != null; + public boolean shouldRender(LevelAccessor level, BlockPos pos, BlockState state) { + return !state.isAir() && getLocalOffset(level, pos, state) != null; } public int getOverrideColor() { @@ -80,8 +82,9 @@ public abstract class ValueBoxTransform { return Pair.of(factory.apply(true), factory.apply(false)); } - public boolean testHit(BlockState state, Vec3 localHit) { - Vec3 offset = getLocalOffset(state); + @Override + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(level, pos, state); if (offset == null) return false; return localHit.distanceTo(offset) < scale / 3.5f; @@ -99,7 +102,7 @@ public abstract class ValueBoxTransform { } @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { Vec3 location = getSouthLocation(); location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Axis.Y); location = VecHelper.rotateCentered(location, AngleHelper.verticalAngle(getSide()), Axis.X); @@ -109,7 +112,7 @@ public abstract class ValueBoxTransform { protected abstract Vec3 getSouthLocation(); @Override - public void rotate(BlockState state, PoseStack ms) { + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { float yRot = AngleHelper.horizontalAngle(getSide()) + 180; float xRot = getSide() == Direction.UP ? 90 : getSide() == Direction.DOWN ? 270 : 0; TransformStack.of(ms) @@ -118,13 +121,13 @@ public abstract class ValueBoxTransform { } @Override - public boolean shouldRender(BlockState state) { - return super.shouldRender(state) && isSideActive(state, getSide()); + public boolean shouldRender(LevelAccessor level, BlockPos pos, BlockState state) { + return super.shouldRender(level, pos, state) && isSideActive(state, getSide()); } @Override - public boolean testHit(BlockState state, Vec3 localHit) { - return isSideActive(state, getSide()) && super.testHit(state, localHit); + public boolean testHit(LevelAccessor level, BlockPos pos, BlockState state, Vec3 localHit) { + return isSideActive(state, getSide()) && super.testHit(level, pos, state, localHit); } protected boolean isSideActive(BlockState state, Direction direction) { diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBehaviour.java index 1c320fc28a..782df92539 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBehaviour.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.blockEntity.behaviour; import com.simibubi.create.content.equipment.clipboard.ClipboardCloneable; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -10,6 +10,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; @@ -18,7 +19,7 @@ public interface ValueSettingsBehaviour extends ClipboardCloneable { public static record ValueSettings(int row, int value) { public MutableComponent format() { - return Lang.number(value) + return CreateLang.number(value) .component(); } @@ -81,6 +82,18 @@ public interface ValueSettingsBehaviour extends ClipboardCloneable { 1.125f); } - default void onShortInteract(Player player, InteractionHand hand, Direction side) {} + default void onShortInteract(Player player, InteractionHand hand, Direction side, BlockHitResult hitResult) {} + default boolean bypassesInput(ItemStack mainhandItem) { + return false; + } + + default boolean mayInteract(Player player) { + return true; + } + + default int netId() { + return 0; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsClient.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsClient.java index be561babfd..b05bad59b3 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsClient.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsClient.java @@ -4,9 +4,9 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.utility.Color; +import net.createmod.catnip.gui.ScreenOpener; +import net.createmod.catnip.theme.Color; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.BlockPos; @@ -22,7 +22,7 @@ import net.minecraftforge.client.gui.overlay.IGuiOverlay; import net.minecraftforge.event.entity.player.PlayerInteractEvent; public class ValueSettingsClient implements IGuiOverlay { - + private Minecraft mc; public int interactHeldTicks = -1; @@ -81,14 +81,16 @@ public class ValueSettingsClient implements IGuiOverlay { } BlockEntityBehaviour behaviour = BlockEntityBehaviour.get(mc.level, interactHeldPos, interactHeldBehaviour); if (!(behaviour instanceof ValueSettingsBehaviour valueSettingBehaviour) + || valueSettingBehaviour.bypassesInput(player.getMainHandItem()) || !valueSettingBehaviour.testHit(blockHitResult.getLocation())) { cancelInteraction(); return; } if (!mc.options.keyUse.isDown()) { AllPackets.getChannel() - .sendToServer( - new ValueSettingsPacket(interactHeldPos, 0, 0, interactHeldHand, interactHeldFace, false)); + .sendToServer(new ValueSettingsPacket(interactHeldPos, 0, 0, interactHeldHand, blockHitResult, + interactHeldFace, false, valueSettingBehaviour.netId())); + valueSettingBehaviour.onShortInteract(player, interactHeldHand, interactHeldFace, blockHitResult); cancelInteraction(); return; } @@ -97,9 +99,9 @@ public class ValueSettingsClient implements IGuiOverlay { player.swinging = false; if (interactHeldTicks++ < 5) return; - ScreenOpener - .open(new ValueSettingsScreen(interactHeldPos, valueSettingBehaviour.createBoard(player, blockHitResult), - valueSettingBehaviour.getValueSettings(), valueSettingBehaviour::newSettingHovered)); + ScreenOpener.open(new ValueSettingsScreen(interactHeldPos, + valueSettingBehaviour.createBoard(player, blockHitResult), valueSettingBehaviour.getValueSettings(), + valueSettingBehaviour::newSettingHovered, valueSettingBehaviour.netId())); interactHeldTicks = -1; } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsFormatter.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsFormatter.java index c8151c9f2f..d5f168da4a 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsFormatter.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsFormatter.java @@ -5,7 +5,7 @@ import java.util.function.Function; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour.ValueSettings; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.network.chat.MutableComponent; @@ -26,7 +26,7 @@ public class ValueSettingsFormatter { private INamedIconOptions[] options; public ScrollOptionSettingsFormatter(INamedIconOptions[] options) { - super(v -> Lang.translateDirect(options[v.value()].getTranslationKey())); + super(v -> CreateLang.translateDirect(options[v.value()].getTranslationKey())); this.options = options; } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsInputHandler.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsInputHandler.java index 5ab4fd6848..45f332c49c 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsInputHandler.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsInputHandler.java @@ -5,7 +5,7 @@ import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.SidedFilteringBehaviour; -import com.simibubi.create.foundation.utility.RaycastHelper; +import com.simibubi.create.foundation.utility.AdventureUtil; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; @@ -48,8 +48,12 @@ public class ValueSettingsInputHandler { for (BlockEntityBehaviour behaviour : sbe.getAllBehaviours()) { if (!(behaviour instanceof ValueSettingsBehaviour valueSettingsBehaviour)) continue; + if (valueSettingsBehaviour.bypassesInput(player.getMainHandItem())) + continue; + if (!valueSettingsBehaviour.mayInteract(player)) + continue; - BlockHitResult ray = RaycastHelper.rayTraceRange(world, player, 10); + BlockHitResult ray = event.getHitVec(); if (ray == null) return; if (behaviour instanceof SidedFilteringBehaviour) { @@ -77,7 +81,7 @@ public class ValueSettingsInputHandler { event.setCancellationResult(InteractionResult.SUCCESS); if (!valueSettingsBehaviour.acceptsValueSettings() || fakePlayer) { - valueSettingsBehaviour.onShortInteract(player, hand, ray.getDirection()); + valueSettingsBehaviour.onShortInteract(player, hand, ray.getDirection(), ray); return; } @@ -92,7 +96,6 @@ public class ValueSettingsInputHandler { } public static boolean canInteract(Player player) { - return player != null && !player.isSpectator() && !player.isShiftKeyDown(); + return player != null && !player.isSpectator() && !player.isShiftKeyDown() && !AdventureUtil.isAdventure(player); } - } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsPacket.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsPacket.java index 27638e80dd..d1e328c552 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsPacket.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsPacket.java @@ -11,6 +11,7 @@ import net.minecraft.core.Direction; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; +import net.minecraft.world.phys.BlockHitResult; public class ValueSettingsPacket extends BlockEntityConfigurationPacket { @@ -19,15 +20,19 @@ public class ValueSettingsPacket extends BlockEntityConfigurationPacket onHover) { + Consumer onHover, int netId) { this.pos = pos; this.board = board; this.initialSettings = valueSettings; this.onHover = onHover; + this.netId = netId; this.iconMode = board.formatter() instanceof ScrollOptionSettingsFormatter; this.milestoneSize = iconMode ? 8 : 4; } @@ -136,7 +137,8 @@ public class ValueSettingsScreen extends AbstractSimiScreen { int scale = board.maxValue() > 128 ? 1 : 2; Component title = board.title(); - Component tip = Lang.translateDirect("gui.value_settings.release_to_confirm", Components.keybind("key.use")); + Component tip = + CreateLang.translateDirect("gui.value_settings.release_to_confirm", Component.keybind("key.use")); double fadeIn = Math.pow(Mth.clamp((ticksOpen + partialTicks) / 4.0, 0, 1), 1); int fattestLabel = Math.max(font.width(tip), font.width(title)); @@ -152,17 +154,18 @@ public class ValueSettingsScreen extends AbstractSimiScreen { int additionalHeight = iconMode ? 46 : 33; int zLevel = 0; - UIRenderHelper.drawStretched(graphics, x - 11 + fadeInStart, y - 17, fadeInWidth, windowHeight + additionalHeight, - zLevel, AllGuiTextures.VALUE_SETTINGS_OUTER_BG); - UIRenderHelper.drawStretched(graphics, x - 10 + fadeInStart, y - 18, fadeInWidth - 2, 1, - zLevel, AllGuiTextures.VALUE_SETTINGS_OUTER_BG); - UIRenderHelper.drawStretched(graphics, x - 10 + fadeInStart, y - 17 + windowHeight + additionalHeight, - zLevel, fadeInWidth - 2, 1, AllGuiTextures.VALUE_SETTINGS_OUTER_BG); + UIRenderHelper.drawStretched(graphics, x - 11 + fadeInStart, y - 17, fadeInWidth, + windowHeight + additionalHeight, zLevel, AllGuiTextures.VALUE_SETTINGS_OUTER_BG); + UIRenderHelper.drawStretched(graphics, x - 10 + fadeInStart, y - 18, fadeInWidth - 2, 1, zLevel, + AllGuiTextures.VALUE_SETTINGS_OUTER_BG); + UIRenderHelper.drawStretched(graphics, x - 10 + fadeInStart, y - 17 + windowHeight + additionalHeight, zLevel, + fadeInWidth - 2, 1, AllGuiTextures.VALUE_SETTINGS_OUTER_BG); if (fadeInWidth > fattestLabel) { int textX = x - 11 - fatTipOffset + bgWidth / 2; graphics.drawString(font, title, textX - font.width(title) / 2, y - 14, 0xdddddd, false); - graphics.drawString(font, tip, textX - font.width(tip) / 2, y + windowHeight + additionalHeight - 27, 0xdddddd, false); + graphics.drawString(font, tip, textX - font.width(tip) / 2, y + windowHeight + additionalHeight - 27, + 0xdddddd, false); } renderBrassFrame(graphics, x + maxLabelWidth + 14, y - 3, valueBarWidth + 8, board.rows() @@ -175,12 +178,12 @@ public class ValueSettingsScreen extends AbstractSimiScreen { int valueBarX = x + maxLabelWidth + 14 + 4; if (!iconMode) { - UIRenderHelper.drawCropped(graphics, x - 4, y, maxLabelWidth + 8, 11, - zLevel, AllGuiTextures.VALUE_SETTINGS_LABEL_BG); - for (int w = 0; w < valueBarWidth; w += AllGuiTextures.VALUE_SETTINGS_BAR.width - 1) + UIRenderHelper.drawCropped(graphics, x - 4, y, maxLabelWidth + 8, 11, zLevel, + AllGuiTextures.VALUE_SETTINGS_LABEL_BG); + for (int w = 0; w < valueBarWidth; w += AllGuiTextures.VALUE_SETTINGS_BAR.getWidth() - 1) UIRenderHelper.drawCropped(graphics, valueBarX + w, y + 1, - Math.min(AllGuiTextures.VALUE_SETTINGS_BAR.width - 1, valueBarWidth - w), 8, - zLevel, AllGuiTextures.VALUE_SETTINGS_BAR); + Math.min(AllGuiTextures.VALUE_SETTINGS_BAR.getWidth() - 1, valueBarWidth - w), 8, zLevel, + AllGuiTextures.VALUE_SETTINGS_BAR); graphics.drawString(font, component, x, y + 1, 0x442000, false); } @@ -242,8 +245,8 @@ public class ValueSettingsScreen extends AbstractSimiScreen { } AllGuiTextures.VALUE_SETTINGS_CURSOR_LEFT.render(graphics, cursorX - 3, cursorY); - UIRenderHelper.drawCropped(graphics, cursorX, cursorY, cursorWidth, 14, - zLevel, AllGuiTextures.VALUE_SETTINGS_CURSOR); + UIRenderHelper.drawCropped(graphics, cursorX, cursorY, cursorWidth, 14, zLevel, + AllGuiTextures.VALUE_SETTINGS_CURSOR); AllGuiTextures.VALUE_SETTINGS_CURSOR_RIGHT.render(graphics, cursorX + cursorWidth, cursorY); graphics.drawString(font, cursorText, cursorX + 2, cursorY + 3, 0x442000, false); @@ -255,10 +258,11 @@ public class ValueSettingsScreen extends AbstractSimiScreen { AllGuiTextures.BRASS_FRAME_BL.render(graphics, x, y + h - 4); AllGuiTextures.BRASS_FRAME_BR.render(graphics, x + w - 4, y + h - 4); int zLevel = 0; - + if (h > 8) { UIRenderHelper.drawStretched(graphics, x, y + 4, 3, h - 8, zLevel, AllGuiTextures.BRASS_FRAME_LEFT); - UIRenderHelper.drawStretched(graphics, x + w - 3, y + 4, 3, h - 8, zLevel, AllGuiTextures.BRASS_FRAME_RIGHT); + UIRenderHelper.drawStretched(graphics, x + w - 3, y + 4, 3, h - 8, zLevel, + AllGuiTextures.BRASS_FRAME_RIGHT); } if (w > 8) { @@ -318,8 +322,8 @@ public class ValueSettingsScreen extends AbstractSimiScreen { ValueSettings closest = getClosestCoordinate((int) pMouseX, (int) pMouseY); // FIXME: value settings may be face-sensitive on future components AllPackets.getChannel() - .sendToServer(new ValueSettingsPacket(pos, closest.row(), closest.value(), null, Direction.UP, - AllKeys.ctrlDown())); + .sendToServer(new ValueSettingsPacket(pos, closest.row(), closest.value(), null, null, Direction.UP, + AllKeys.ctrlDown(), netId)); onClose(); } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/animatedContainer/AnimatedContainerBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/animatedContainer/AnimatedContainerBehaviour.java new file mode 100644 index 0000000000..a58efd8c64 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/animatedContainer/AnimatedContainerBehaviour.java @@ -0,0 +1,107 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.animatedContainer; + +import java.util.function.Consumer; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.gui.menu.MenuBase; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; + +public class AnimatedContainerBehaviour> extends BlockEntityBehaviour { + + public static final BehaviourType> TYPE = new BehaviourType<>(); + + public int openCount; + + private Class menuClass; + private Consumer openChanged; + + public AnimatedContainerBehaviour(SmartBlockEntity be, Class menuClass) { + super(be); + this.menuClass = menuClass; + openCount = 0; + } + + public void onOpenChanged(Consumer openChanged) { + this.openChanged = openChanged; + } + + @Override + public void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (clientPacket) + openCount = compound.getInt("OpenCount"); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + if (clientPacket) + compound.putInt("OpenCount", openCount); + } + + @Override + public void lazyTick() { + updateOpenCount(); + super.lazyTick(); + } + + void updateOpenCount() { + Level level = getWorld(); + if (level.isClientSide) + return; + if (openCount == 0) + return; + + int prevOpenCount = openCount; + openCount = 0; + + for (Player playerentity : level.getEntitiesOfClass(Player.class, new AABB(getPos()).inflate(8))) + if (menuClass.isInstance(playerentity.containerMenu) + && menuClass.cast(playerentity.containerMenu).contentHolder == blockEntity) + openCount++; + + if (prevOpenCount != openCount) { + if (openChanged != null && prevOpenCount == 0 && openCount > 0) + openChanged.accept(true); + if (openChanged != null && prevOpenCount > 0 && openCount == 0) + openChanged.accept(false); + blockEntity.sendData(); + } + } + + public void startOpen(Player player) { + if (player.isSpectator()) + return; + if (getWorld().isClientSide) + return; + if (openCount < 0) + openCount = 0; + openCount++; + if (openCount == 1 && openChanged != null) + openChanged.accept(true); + blockEntity.sendData(); + } + + public void stopOpen(Player player) { + if (player.isSpectator()) + return; + if (getWorld().isClientSide) + return; + openCount--; + if (openCount == 0 && openChanged != null) + openChanged.accept(false); + blockEntity.sendData(); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java index ee72e8c30b..f071791c43 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java @@ -5,9 +5,9 @@ import java.util.List; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.RaycastHelper; +import net.createmod.catnip.data.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java index 39b55ea7c0..4c504547b9 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java @@ -9,17 +9,19 @@ import com.simibubi.create.content.kinetics.crafter.CrafterHelper; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; @@ -31,10 +33,9 @@ public class EdgeInteractionRenderer { public static void tick() { Minecraft mc = Minecraft.getInstance(); HitResult target = mc.hitResult; - if (target == null || !(target instanceof BlockHitResult)) + if (target == null || !(target instanceof BlockHitResult result)) return; - BlockHitResult result = (BlockHitResult) target; ClientLevel world = mc.level; BlockPos pos = result.getBlockPos(); Player player = mc.player; @@ -75,18 +76,18 @@ public class EdgeInteractionRenderer { .scale(.469)) .add(VecHelper.CENTER_OF_ORIGIN); - ValueBox box = new ValueBox(Components.immutableEmpty(), bb, pos).passive(!hit) + ValueBox box = new ValueBox(CommonComponents.EMPTY, bb, pos).passive(!hit) .transform(new EdgeValueBoxTransform(offset)) .wideOutline(); - CreateClient.OUTLINER.showValueBox("edge", box) + Outliner.getInstance().showOutline("edge", box) .highlightFace(face); if (!hit) return; List tip = new ArrayList<>(); - tip.add(Lang.translateDirect("logistics.crafter.connected")); - tip.add(Lang.translateDirect(CrafterHelper.areCraftersConnected(world, pos, pos.relative(closestEdge)) + tip.add(CreateLang.translateDirect("logistics.crafter.connected")); + tip.add(CreateLang.translateDirect(CrafterHelper.areCraftersConnected(world, pos, pos.relative(closestEdge)) ? "logistics.crafter.click_to_separate" : "logistics.crafter.click_to_merge")); CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); @@ -106,13 +107,13 @@ public class EdgeInteractionRenderer { } @Override - public Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(LevelAccessor level, BlockPos pos, BlockState state) { return add; } @Override - public void rotate(BlockState state, PoseStack ms) { - super.rotate(state, ms); + public void rotate(LevelAccessor level, BlockPos pos, BlockState state, PoseStack ms) { + super.rotate(level, pos, state, ms); } } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java index 2b5cffbb79..a1264c2155 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java @@ -18,15 +18,16 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehavio import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.VecHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -51,8 +52,8 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet ValueBoxTransform slotPositioning; boolean showCount; - private FilterItemStack filter; - + protected FilterItemStack filter; + public int count; public boolean upTo; private Predicate predicate; @@ -97,14 +98,14 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet filter = FilterItemStack.of(nbt.getCompound("Filter")); count = nbt.getInt("FilterAmount"); upTo = nbt.getBoolean("UpTo"); - + // Migrate from previous behaviour if (count == 0) { upTo = true; count = filter.item() .getMaxStackSize(); } - + super.read(nbt, clientPacket); } @@ -231,7 +232,7 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet public boolean testHit(Vec3 hit) { BlockState state = blockEntity.getBlockState(); Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); - return slotPositioning.testHit(state, localHit); + return slotPositioning.testHit(getWorld(), getPos(), state, localHit); } public int getAmount() { @@ -261,28 +262,26 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { ItemStack filter = getFilter(hitResult.getDirection()); int maxAmount = (filter.getItem() instanceof FilterItem) ? 64 : filter.getMaxStackSize(); - return new ValueSettingsBoard(Lang.translateDirect("logistics.filter.extracted_amount"), maxAmount, 16, - Lang.translatedOptions("logistics.filter", "up_to", "exactly"), + return new ValueSettingsBoard(CreateLang.translateDirect("logistics.filter.extracted_amount"), maxAmount, 16, + CreateLang.translatedOptions("logistics.filter", "up_to", "exactly"), new ValueSettingsFormatter(this::formatValue)); } public MutableComponent formatValue(ValueSettings value) { if (value.row() == 0 && value.value() == filter.item() .getMaxStackSize()) - return Lang.translateDirect("logistics.filter.any_amount_short"); - return Components.literal(((value.row() == 0) ? "\u2264" : "=") + Math.max(1, value.value())); - } + return CreateLang.translateDirect("logistics.filter.any_amount_short"); + return Component.literal(((value.row() == 0) ? "\u2264" : "=") + Math.max(1, value.value())); + } @Override - public void onShortInteract(Player player, InteractionHand hand, Direction side) { + public void onShortInteract(Player player, InteractionHand hand, Direction side, BlockHitResult hitResult) { Level level = getWorld(); BlockPos pos = getPos(); ItemStack itemInHand = player.getItemInHand(hand); ItemStack toApply = itemInHand.copy(); - if (AllItems.WRENCH.isIn(toApply)) - return; - if (AllBlocks.MECHANICAL_ARM.isIn(toApply)) + if (!canShortInteract(toApply)) return; if (level.isClientSide()) return; @@ -300,11 +299,11 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet toApply.setCount(1); if (!setFilter(side, toApply)) { - player.displayClientMessage(Lang.translateDirect("logistics.filter.invalid_item"), true); + player.displayClientMessage(CreateLang.translateDirect("logistics.filter.invalid_item"), true); AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); return; } - + if (!player.isCreative()) { if (toApply.getItem() instanceof FilterItem) { if (itemInHand.getCount() == 1) @@ -317,13 +316,35 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet level.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .1f); } + public boolean canShortInteract(ItemStack toApply) { + if (AllItems.WRENCH.isIn(toApply)) + return false; + if (AllBlocks.MECHANICAL_ARM.isIn(toApply)) + return false; + return true; + } + public MutableComponent getLabel() { if (customLabel != null) return customLabel; - return Lang.translateDirect( + return CreateLang.translateDirect( recipeFilter ? "logistics.recipe_filter" : fluidFilter ? "logistics.fluid_filter" : "logistics.filter"); } + public MutableComponent getTip() { + return CreateLang + .translateDirect(filter.isEmpty() ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace"); + } + + public MutableComponent getAmountTip() { + return CreateLang.translateDirect("logistics.filter.hold_to_set_amount"); + } + + public MutableComponent getCountLabelForValueBox() { + return Component.literal(isCountVisible() ? upTo && filter.item() + .getMaxStackSize() == count ? "*" : String.valueOf(count) : ""); + } + @Override public String getClipboardKey() { return "Filtering"; @@ -339,6 +360,8 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet @Override public boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate) { + if (!mayInteract(player)) + return false; boolean upstreamResult = ValueSettingsBehaviour.super.readFromClipboard(tag, player, side, simulate); if (!tag.contains("Filter")) return upstreamResult; @@ -371,7 +394,7 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet return true; } - player.displayClientMessage(Lang + player.displayClientMessage(CreateLang .translate("logistics.filter.requires_item_in_inventory", copied.getHoverName() .copy() .withStyle(ChatFormatting.WHITE)) @@ -387,9 +410,23 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet return setFilter(side, copied); } - + public boolean isRecipeFilter() { return recipeFilter; } + @Override + public boolean bypassesInput(ItemStack mainhandItem) { + return false; + } + + @Override + public int netId() { + return 1; + } + + public float getRenderDistance() { + return AllConfigs.client().filterItemRenderDistance.getF(); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringRenderer.java index 2e3878ccb2..f6bed852bd 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringRenderer.java @@ -15,12 +15,11 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox.ItemValueBo import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxRenderer; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.data.Pair; +import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.MultiBufferSource; @@ -31,6 +30,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; @@ -42,120 +42,131 @@ public class FilteringRenderer { public static void tick() { Minecraft mc = Minecraft.getInstance(); HitResult target = mc.hitResult; - if (target == null || !(target instanceof BlockHitResult)) + if (target == null || !(target instanceof BlockHitResult result)) return; - BlockHitResult result = (BlockHitResult) target; ClientLevel world = mc.level; BlockPos pos = result.getBlockPos(); BlockState state = world.getBlockState(pos); - FilteringBehaviour behaviour = BlockEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE); if (mc.player.isShiftKeyDown()) return; - + if (!(world.getBlockEntity(pos) instanceof SmartBlockEntity sbe)) + return; + ItemStack mainhandItem = mc.player.getItemInHand(InteractionHand.MAIN_HAND); - if (behaviour == null) - return; - if (behaviour instanceof SidedFilteringBehaviour) { - behaviour = ((SidedFilteringBehaviour) behaviour).get(result.getDirection()); - if (behaviour == null) - return; + + for (BlockEntityBehaviour b : sbe.getAllBehaviours()) { + if (!(b instanceof FilteringBehaviour behaviour)) + continue; + + if (behaviour instanceof SidedFilteringBehaviour) { + behaviour = ((SidedFilteringBehaviour) behaviour).get(result.getDirection()); + if (behaviour == null) + continue; + } + + if (!behaviour.isActive()) + continue; + if (behaviour.slotPositioning instanceof ValueBoxTransform.Sided) + ((Sided) behaviour.slotPositioning).fromSide(result.getDirection()); + if (!behaviour.slotPositioning.shouldRender(world, pos, state)) + continue; + if (!behaviour.mayInteract(mc.player)) + continue; + + ItemStack filter = behaviour.getFilter(); + boolean isFilterSlotted = filter.getItem() instanceof FilterItem; + boolean showCount = behaviour.isCountVisible(); + Component label = behaviour.getLabel(); + boolean hit = behaviour.slotPositioning.testHit(world, pos, state, target.getLocation() + .subtract(Vec3.atLowerCornerOf(pos))); + + AABB emptyBB = new AABB(Vec3.ZERO, Vec3.ZERO); + AABB bb = isFilterSlotted ? emptyBB.inflate(.45f, .31f, .2f) : emptyBB.inflate(.25f); + + ValueBox box = new ItemValueBox(label, bb, pos, filter, behaviour.getCountLabelForValueBox()); + box.passive(!hit || behaviour.bypassesInput(mainhandItem)); + + Outliner.getInstance() + .showOutline(Pair.of("filter" + behaviour.netId(), pos), box.transform(behaviour.slotPositioning)) + .lineWidth(1 / 64f) + .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) + .highlightFace(result.getDirection()); + + if (!hit) + continue; + + List tip = new ArrayList<>(); + tip.add(label.copy()); + tip.add(behaviour.getTip()); + if (showCount) + tip.add(behaviour.getAmountTip()); + + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); } - if (!behaviour.isActive()) - return; - if (behaviour.slotPositioning instanceof ValueBoxTransform.Sided) - ((Sided) behaviour.slotPositioning).fromSide(result.getDirection()); - if (!behaviour.slotPositioning.shouldRender(state)) - return; - - ItemStack filter = behaviour.getFilter(); - boolean isFilterSlotted = filter.getItem() instanceof FilterItem; - boolean showCount = behaviour.isCountVisible(); - Component label = behaviour.getLabel(); - boolean hit = behaviour.slotPositioning.testHit(state, target.getLocation() - .subtract(Vec3.atLowerCornerOf(pos))); - - AABB emptyBB = new AABB(Vec3.ZERO, Vec3.ZERO); - AABB bb = isFilterSlotted ? emptyBB.inflate(.45f, .31f, .2f) : emptyBB.inflate(.25f); - - ValueBox box = new ItemValueBox(label, bb, pos, filter, showCount ? behaviour.count : -1, behaviour.upTo); - box.passive(!hit || AllBlocks.CLIPBOARD.isIn(mainhandItem)); - - CreateClient.OUTLINER.showValueBox(Pair.of("filter", pos), box.transform(behaviour.slotPositioning)) - .lineWidth(1 / 64f) - .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) - .highlightFace(result.getDirection()); - - if (!hit) - return; - - List tip = new ArrayList<>(); - tip.add(label.copy()); - tip.add(Lang - .translateDirect(filter.isEmpty() ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace")); - if (showCount) - tip.add(Lang.translateDirect("logistics.filter.hold_to_set_amount")); - - CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); } public static void renderOnBlockEntity(SmartBlockEntity be, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { + MultiBufferSource buffer, int light, int overlay) { if (be == null || be.isRemoved()) return; - if (!be.isVirtual()) { - Entity cameraEntity = Minecraft.getInstance().cameraEntity; - if (cameraEntity != null && be.getLevel() == cameraEntity.level()) { - float max = AllConfigs.client().filterItemRenderDistance.getF(); - if (cameraEntity.position() - .distanceToSqr(VecHelper.getCenterOf(be.getBlockPos())) > (max * max)) { - return; + Level level = be.getLevel(); + BlockPos blockPos = be.getBlockPos(); + + for (BlockEntityBehaviour b : be.getAllBehaviours()) { + if (!(b instanceof FilteringBehaviour behaviour)) + continue; + + if (!be.isVirtual()) { + Entity cameraEntity = Minecraft.getInstance().cameraEntity; + if (cameraEntity != null && level == cameraEntity.level()) { + float max = behaviour.getRenderDistance(); + if (cameraEntity.position() + .distanceToSqr(VecHelper.getCenterOf(blockPos)) > (max * max)) { + continue; + } } } - } - FilteringBehaviour behaviour = be.getBehaviour(FilteringBehaviour.TYPE); - if (behaviour == null) - return; - if (!behaviour.isActive()) - return; - if (behaviour.getFilter() - .isEmpty() && !(behaviour instanceof SidedFilteringBehaviour)) - return; + if (!behaviour.isActive()) + continue; + if (behaviour.getFilter() + .isEmpty() && !(behaviour instanceof SidedFilteringBehaviour)) + continue; - ValueBoxTransform slotPositioning = behaviour.slotPositioning; - BlockState blockState = be.getBlockState(); + ValueBoxTransform slotPositioning = behaviour.slotPositioning; + BlockState blockState = be.getBlockState(); - if (slotPositioning instanceof ValueBoxTransform.Sided) { - ValueBoxTransform.Sided sided = (ValueBoxTransform.Sided) slotPositioning; - Direction side = sided.getSide(); - for (Direction d : Iterate.directions) { - ItemStack filter = behaviour.getFilter(d); - if (filter.isEmpty()) - continue; + if (slotPositioning instanceof Sided sided) { + Direction side = sided.getSide(); + for (Direction d : Iterate.directions) { + ItemStack filter = behaviour.getFilter(d); + if (filter.isEmpty()) + continue; - sided.fromSide(d); - if (!slotPositioning.shouldRender(blockState)) - continue; + sided.fromSide(d); + if (!slotPositioning.shouldRender(level, blockPos, blockState)) + continue; + ms.pushPose(); + slotPositioning.transform(level, blockPos, blockState, ms); + if (AllBlocks.CONTRAPTION_CONTROLS.has(blockState)) + ValueBoxRenderer.renderFlatItemIntoValueBox(filter, ms, buffer, light, overlay); + else + ValueBoxRenderer.renderItemIntoValueBox(filter, ms, buffer, light, overlay); + ms.popPose(); + } + sided.fromSide(side); + continue; + } else if (slotPositioning.shouldRender(level, blockPos, blockState)) { ms.pushPose(); - slotPositioning.transform(blockState, ms); - if (AllBlocks.CONTRAPTION_CONTROLS.has(blockState)) - ValueBoxRenderer.renderFlatItemIntoValueBox(filter, ms, buffer, light, overlay); - else - ValueBoxRenderer.renderItemIntoValueBox(filter, ms, buffer, light, overlay); + slotPositioning.transform(level, blockPos, blockState, ms); + ValueBoxRenderer.renderItemIntoValueBox(behaviour.getFilter(), ms, buffer, light, overlay); ms.popPose(); } - sided.fromSide(side); - return; - } else if (slotPositioning.shouldRender(blockState)) { - ms.pushPose(); - slotPositioning.transform(blockState, ms); - ValueBoxRenderer.renderItemIntoValueBox(behaviour.getFilter(), ms, buffer, light, overlay); - ms.popPose(); } } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/SidedFilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/SidedFilteringBehaviour.java index d770f8b367..04f0b45a6b 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/SidedFilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/SidedFilteringBehaviour.java @@ -11,13 +11,15 @@ import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -111,38 +113,36 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { if (!sidedFilters.containsKey(side)) return true; return sidedFilters.get(side) - .test(stack); + .test(stack); } @Override public void destroy() { sidedFilters.values() - .forEach(FilteringBehaviour::destroy); + .forEach(FilteringBehaviour::destroy); super.destroy(); } @Override public ItemRequirement getRequiredItems() { - return sidedFilters.values().stream().reduce( - ItemRequirement.NONE, - (a, b) -> a.union(b.getRequiredItems()), - (a, b) -> a.union(b) - ); + return sidedFilters.values() + .stream() + .reduce(ItemRequirement.NONE, (a, b) -> a.union(b.getRequiredItems()), (a, b) -> a.union(b)); } public void removeFilter(Direction side) { if (!sidedFilters.containsKey(side)) return; sidedFilters.remove(side) - .destroy(); + .destroy(); } - public boolean testHit(Direction direction, Vec3 hit) { + public boolean testHit(LevelAccessor level, BlockPos pos, Direction direction, Vec3 hit) { ValueBoxTransform.Sided sidedPositioning = (Sided) slotPositioning; BlockState state = blockEntity.getBlockState(); Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); return sidedPositioning.fromSide(direction) - .testHit(state, localHit); + .testHit(level, pos, state, localHit); } } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/fluid/SmartFluidTankBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/fluid/SmartFluidTankBehaviour.java index 4b10c7fd14..26740e2c4e 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/fluid/SmartFluidTankBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/fluid/SmartFluidTankBehaviour.java @@ -9,10 +9,10 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import com.simibubi.create.foundation.fluid.SmartFluidTank; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.createmod.catnip.nbt.NBTHelper; +import net.createmod.catnip.animation.LerpedFloat; +import net.createmod.catnip.animation.LerpedFloat.Chaser; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/CapManipulationBehaviourBase.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/CapManipulationBehaviourBase.java index 0dcb74dc4b..b5f8859c46 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/CapManipulationBehaviourBase.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/CapManipulationBehaviourBase.java @@ -2,12 +2,14 @@ package com.simibubi.create.foundation.blockEntity.behaviour.inventory; import javax.annotation.Nullable; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; -import com.simibubi.create.foundation.utility.BlockFace; +import net.createmod.catnip.math.BlockFace; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -21,6 +23,7 @@ public abstract class CapManipulationBehaviourBase targetCapability; + protected Predicate filter; protected boolean simulateNext; protected boolean bypassSided; private boolean findNewNextTick; @@ -32,6 +35,7 @@ public abstract class CapManipulationBehaviourBase capability(); @@ -65,6 +69,12 @@ public abstract class CapManipulationBehaviourBase filter) { + this.filter = filter; + return (S) this; + } + public boolean hasInventory() { return targetCapability.isPresent(); } @@ -122,7 +132,7 @@ public abstract class CapManipulationBehaviourBase capability = capability(); targetCapability = diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollOptionBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollOptionBehaviour.java index 262ff9673b..b3c1c5913c 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollOptionBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollOptionBehaviour.java @@ -5,7 +5,6 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter.ScrollOptionSettingsFormatter; -import com.simibubi.create.foundation.utility.Components; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; @@ -31,10 +30,10 @@ public class ScrollOptionBehaviour & INamedIconOptions> extend @Override public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { - return new ValueSettingsBoard(label, max, 1, ImmutableList.of(Components.literal("Select")), + return new ValueSettingsBoard(label, max, 1, ImmutableList.of(Component.literal("Select")), new ScrollOptionSettingsFormatter(options)); } - + @Override public String getClipboardKey() { return options[0].getClass().getSimpleName(); diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueBehaviour.java index 4af38bb16d..063a4508d8 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueBehaviour.java @@ -12,8 +12,6 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -24,6 +22,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.common.util.FakePlayer; public class ScrollValueBehaviour extends BlockEntityBehaviour implements ValueSettingsBehaviour { @@ -136,7 +135,7 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour implements ValueS public boolean testHit(Vec3 hit) { BlockState state = blockEntity.getBlockState(); Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); - return slotPositioning.testHit(state, localHit); + return slotPositioning.testHit(getWorld(), getPos(), state, localHit); } public void setLabel(Component label) { @@ -157,7 +156,7 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour implements ValueS @Override public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { - return new ValueSettingsBoard(label, max, 10, ImmutableList.of(Components.literal("Value")), + return new ValueSettingsBoard(label, max, 10, ImmutableList.of(Component.literal("Value")), new ValueSettingsFormatter(ValueSettings::format)); } @@ -180,11 +179,10 @@ public class ScrollValueBehaviour extends BlockEntityBehaviour implements ValueS } @Override - public void onShortInteract(Player player, InteractionHand hand, Direction side) { + public void onShortInteract(Player player, InteractionHand hand, Direction side, BlockHitResult hitResult) { if (player instanceof FakePlayer) blockEntity.getBlockState() - .use(getWorld(), player, hand, - new BlockHitResult(VecHelper.getCenterOf(getPos()), side, getPos(), true)); + .use(getWorld(), player, hand, hitResult); } } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueHandler.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueHandler.java index 11b820c1df..82608ccbf0 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueHandler.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueHandler.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; -import com.simibubi.create.foundation.utility.animation.PhysicalFloat; +import net.createmod.catnip.animation.PhysicalFloat; import net.minecraft.client.Minecraft; import net.minecraft.util.Mth; import net.minecraftforge.api.distmarker.Dist; diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueRenderer.java index e4878b173f..77b33fa463 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueRenderer.java @@ -3,7 +3,6 @@ package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllKeys; import com.simibubi.create.CreateClient; @@ -12,9 +11,9 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox.IconValueBox; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox.TextValueBox; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; @@ -33,48 +32,54 @@ public class ScrollValueRenderer { public static void tick() { Minecraft mc = Minecraft.getInstance(); HitResult target = mc.hitResult; - if (target == null || !(target instanceof BlockHitResult)) + if (target == null || !(target instanceof BlockHitResult result)) return; - BlockHitResult result = (BlockHitResult) target; ClientLevel world = mc.level; BlockPos pos = result.getBlockPos(); Direction face = result.getDirection(); + boolean highlightFound = false; - ScrollValueBehaviour behaviour = BlockEntityBehaviour.get(world, pos, ScrollValueBehaviour.TYPE); - if (behaviour == null) + if (!(world.getBlockEntity(pos) instanceof SmartBlockEntity sbe)) return; - if (!behaviour.isActive()) { - CreateClient.OUTLINER.remove(pos); - return; - } - ItemStack mainhandItem = mc.player.getItemInHand(InteractionHand.MAIN_HAND); - boolean clipboard = AllBlocks.CLIPBOARD.isIn(mainhandItem); - if (behaviour.needsWrench && !AllItems.WRENCH.isIn(mainhandItem) && !clipboard) - return; - boolean highlight = behaviour.testHit(target.getLocation()) && !clipboard; - if (behaviour instanceof BulkScrollValueBehaviour && AllKeys.ctrlDown()) { - BulkScrollValueBehaviour bulkScrolling = (BulkScrollValueBehaviour) behaviour; - for (SmartBlockEntity smartBlockEntity : bulkScrolling.getBulk()) { - ScrollValueBehaviour other = smartBlockEntity.getBehaviour(ScrollValueBehaviour.TYPE); - if (other != null) - addBox(world, smartBlockEntity.getBlockPos(), face, other, highlight); + for (BlockEntityBehaviour blockEntityBehaviour : sbe.getAllBehaviours()) { + if (!(blockEntityBehaviour instanceof ScrollValueBehaviour behaviour)) + continue; + + if (!behaviour.isActive()) { + Outliner.getInstance().remove(behaviour); + continue; } - } else - addBox(world, pos, face, behaviour, highlight); - if (!highlight) - return; + ItemStack mainhandItem = mc.player.getItemInHand(InteractionHand.MAIN_HAND); + boolean clipboard = behaviour.bypassesInput(mainhandItem); + if (behaviour.needsWrench && !AllItems.WRENCH.isIn(mainhandItem) && !clipboard) + continue; + boolean highlight = behaviour.testHit(target.getLocation()) && !clipboard && !highlightFound; - List tip = new ArrayList<>(); - tip.add(behaviour.label.copy()); - tip.add(Lang.translateDirect("gui.value_settings.hold_to_edit")); - CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + if (behaviour instanceof BulkScrollValueBehaviour bulkScrolling && AllKeys.ctrlDown()) { + for (SmartBlockEntity smartBlockEntity : bulkScrolling.getBulk()) { + ScrollValueBehaviour other = smartBlockEntity.getBehaviour(ScrollValueBehaviour.TYPE); + if (other != null) + addBox(world, smartBlockEntity.getBlockPos(), face, other, highlight); + } + } else + addBox(world, pos, face, behaviour, highlight); + + if (!highlight) + continue; + + highlightFound = true; + List tip = new ArrayList<>(); + tip.add(behaviour.label.copy()); + tip.add(CreateLang.translateDirect("gui.value_settings.hold_to_edit")); + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + } } protected static void addBox(ClientLevel world, BlockPos pos, Direction face, ScrollValueBehaviour behaviour, - boolean highlight) { + boolean highlight) { AABB bb = new AABB(Vec3.ZERO, Vec3.ZERO).inflate(.5f) .contract(0, 0, -.5f) .move(0, 0, -.125f); @@ -84,13 +89,13 @@ public class ScrollValueRenderer { if (behaviour instanceof ScrollOptionBehaviour) { box = new IconValueBox(label, ((ScrollOptionBehaviour) behaviour).getIconForSelected(), bb, pos); } else { - box = new TextValueBox(label, bb, pos, Components.literal(behaviour.formatValue())); + box = new TextValueBox(label, bb, pos, Component.literal(behaviour.formatValue())); } box.passive(!highlight) .wideOutline(); - CreateClient.OUTLINER.showValueBox(pos, box.transform(behaviour.slotPositioning)) + Outliner.getInstance().showOutline(behaviour, box.transform(behaviour.slotPositioning)) .highlightFace(face); } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/ColoredOverlayBlockEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/ColoredOverlayBlockEntityRenderer.java index 175bbcc760..fadf164279 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/ColoredOverlayBlockEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/ColoredOverlayBlockEntityRenderer.java @@ -1,9 +1,9 @@ package com.simibubi.create.foundation.blockEntity.renderer; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.render.SuperByteBuffer; import dev.engine_room.flywheel.api.visualization.VisualizationManager; +import net.createmod.catnip.render.SuperByteBuffer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java index d9b8d4c699..7351196146 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java @@ -2,8 +2,9 @@ package com.simibubi.create.foundation.blockEntity.renderer; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.ponder.PonderWorld; +import com.simibubi.create.foundation.mixin.accessor.LevelRendererAccessor; +import net.createmod.ponder.api.level.PonderLevel; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; @@ -32,12 +33,13 @@ public abstract class SafeBlockEntityRenderer implements } public boolean shouldCullItem(Vec3 itemPos, Level level) { - if (level instanceof PonderWorld) + if (level instanceof PonderLevel) return false; - Frustum frustum = Minecraft.getInstance().levelRenderer.capturedFrustum != null ? - Minecraft.getInstance().levelRenderer.capturedFrustum : - Minecraft.getInstance().levelRenderer.cullingFrustum; + LevelRendererAccessor accessor = (LevelRendererAccessor) Minecraft.getInstance().levelRenderer; + Frustum frustum = accessor.create$getCapturedFrustum() != null ? + accessor.create$getCapturedFrustum() : + accessor.create$getCullingFrustum(); AABB itemBB = new AABB( itemPos.x - 0.25, diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SmartBlockEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SmartBlockEntityRenderer.java index 041c97d170..80a4f5ecc8 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SmartBlockEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SmartBlockEntityRenderer.java @@ -1,12 +1,21 @@ package com.simibubi.create.foundation.blockEntity.renderer; +import org.joml.Matrix4f; + import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.redstone.link.LinkRenderer; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.network.chat.Component; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.HitResult.Type; +import net.minecraft.world.phys.Vec3; public class SmartBlockEntityRenderer extends SafeBlockEntityRenderer { @@ -20,4 +29,32 @@ public class SmartBlockEntityRenderer extends SafeBl LinkRenderer.renderOnBlockEntity(blockEntity, partialTicks, ms, buffer, light, overlay); } + protected void renderNameplateOnHover(T blockEntity, Component tag, float yOffset, PoseStack ms, + MultiBufferSource buffer, int light) { + Minecraft mc = Minecraft.getInstance(); + if (blockEntity.isVirtual()) + return; + if (mc.player.distanceToSqr(Vec3.atCenterOf(blockEntity.getBlockPos())) > 4096.0f) + return; + HitResult hitResult = mc.hitResult; + if (!(hitResult instanceof BlockHitResult bhr) || bhr.getType() == Type.MISS || !bhr.getBlockPos() + .equals(blockEntity.getBlockPos())) + return; + + float f = yOffset + 0.25f; + ms.pushPose(); + ms.translate(0.5, f, 0.5); + ms.mulPose(mc.getEntityRenderDispatcher() + .cameraOrientation()); + ms.scale(-0.025F, -0.025F, 0.025F); + Matrix4f matrix4f = ms.last() + .pose(); + float f1 = mc.options.getBackgroundOpacity(0.25F); + int j = (int) (f1 * 255.0F) << 24; + float f2 = (float) (-mc.font.width(tag) / 2); + mc.font.drawInBatch(tag, f2, 0, 553648127, false, matrix4f, buffer, Font.DisplayMode.SEE_THROUGH, j, light); + mc.font.drawInBatch(tag, f2, 0, -1, false, matrix4f, buffer, Font.DisplayMode.NORMAL, 0, light); + ms.popPose(); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java b/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java deleted file mode 100644 index e8921fbf78..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.simibubi.create.foundation.config; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.function.Supplier; - -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.common.ForgeConfigSpec.BooleanValue; -import net.minecraftforge.common.ForgeConfigSpec.Builder; -import net.minecraftforge.common.ForgeConfigSpec.ConfigValue; -import net.minecraftforge.common.ForgeConfigSpec.DoubleValue; -import net.minecraftforge.common.ForgeConfigSpec.EnumValue; -import net.minecraftforge.common.ForgeConfigSpec.IntValue; - -public abstract class ConfigBase { - - public ForgeConfigSpec specification; - - protected int depth; - protected List> allValues; - protected List children; - - public void registerAll(final ForgeConfigSpec.Builder builder) { - for (CValue cValue : allValues) - cValue.register(builder); - } - - public void onLoad() { - if (children != null) - children.forEach(ConfigBase::onLoad); - } - - public void onReload() { - if (children != null) - children.forEach(ConfigBase::onReload); - } - - public abstract String getName(); - - @FunctionalInterface - protected static interface IValueProvider> - extends Function { - } - - protected ConfigBool b(boolean current, String name, String... comment) { - return new ConfigBool(name, current, comment); - } - - protected ConfigFloat f(float current, float min, float max, String name, String... comment) { - return new ConfigFloat(name, current, min, max, comment); - } - - protected ConfigFloat f(float current, float min, String name, String... comment) { - return f(current, min, Float.MAX_VALUE, name, comment); - } - - protected ConfigInt i(int current, int min, int max, String name, String... comment) { - return new ConfigInt(name, current, min, max, comment); - } - - protected ConfigInt i(int current, int min, String name, String... comment) { - return i(current, min, Integer.MAX_VALUE, name, comment); - } - - protected ConfigInt i(int current, String name, String... comment) { - return i(current, Integer.MIN_VALUE, Integer.MAX_VALUE, name, comment); - } - - protected > ConfigEnum e(T defaultValue, String name, String... comment) { - return new ConfigEnum<>(name, defaultValue, comment); - } - - protected ConfigGroup group(int depth, String name, String... comment) { - return new ConfigGroup(name, depth, comment); - } - - protected T nested(int depth, Supplier constructor, String... comment) { - T config = constructor.get(); - new ConfigGroup(config.getName(), depth, comment); - new CValue(config.getName(), builder -> { - config.depth = depth; - config.registerAll(builder); - if (config.depth > depth) - builder.pop(config.depth - depth); - return null; - }); - if (children == null) - children = new ArrayList<>(); - children.add(config); - return config; - } - - public class CValue> { - protected ConfigValue value; - protected String name; - private IValueProvider provider; - - public CValue(String name, IValueProvider provider, String... comment) { - this.name = name; - this.provider = builder -> { - addComments(builder, comment); - return provider.apply(builder); - }; - if (allValues == null) - allValues = new ArrayList<>(); - allValues.add(this); - } - - public void addComments(Builder builder, String... comment) { - if (comment.length > 0) { - String[] comments = new String[comment.length + 1]; - comments[0] = "."; - System.arraycopy(comment, 0, comments, 1, comment.length); - builder.comment(comments); - } else - builder.comment("."); - } - - public void register(ForgeConfigSpec.Builder builder) { - value = provider.apply(builder); - } - - public V get() { - return value.get(); - } - - public void set(V value) { - this.value.set(value); - } - - public String getName() { - return name; - } - } - - /** - * Marker for config subgroups - */ - public class ConfigGroup extends CValue { - - private int groupDepth; - private String[] comment; - - public ConfigGroup(String name, int depth, String... comment) { - super(name, builder -> null, comment); - groupDepth = depth; - this.comment = comment; - } - - @Override - public void register(Builder builder) { - if (depth > groupDepth) - builder.pop(depth - groupDepth); - depth = groupDepth; - addComments(builder, comment); - builder.push(getName()); - depth++; - } - - } - - public class ConfigBool extends CValue { - - public ConfigBool(String name, boolean def, String... comment) { - super(name, builder -> builder.define(name, def), comment); - } - } - - public class ConfigEnum> extends CValue> { - - public ConfigEnum(String name, T defaultValue, String[] comment) { - super(name, builder -> builder.defineEnum(name, defaultValue), comment); - } - - } - - public class ConfigFloat extends CValue { - - public ConfigFloat(String name, float current, float min, float max, String... comment) { - super(name, builder -> builder.defineInRange(name, current, min, max), comment); - } - - public float getF() { - return get().floatValue(); - } - } - - public class ConfigInt extends CValue { - - public ConfigInt(String name, int current, int min, int max, String... comment) { - super(name, builder -> builder.defineInRange(name, current, min, max), comment); - } - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java deleted file mode 100644 index 7aaec5bd41..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java +++ /dev/null @@ -1,251 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.function.UnaryOperator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.lwjgl.glfw.GLFW; - -import com.simibubi.create.Create; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.element.TextStencilElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.infrastructure.config.AllConfigs; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.fml.config.ModConfig; - -public class BaseConfigScreen extends ConfigScreen { - - public static final DelegatedStencilElement.ElementRenderer DISABLED_RENDERER = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.BUTTON_DISABLE)); - private static final Map> DEFAULTS = new HashMap<>(); - - static { - DEFAULTS.put(Create.ID, (base) -> base - .withTitles("Client Settings", "World Generation Settings", "Gameplay Settings") - .withSpecs(AllConfigs.client().specification, AllConfigs.common().specification, AllConfigs.server().specification) - ); - } - - /** - * If you are a Create Addon dev and want to change the config labels, - * add a default action here. - * - * Make sure you call either {@link #withSpecs(ForgeConfigSpec, ForgeConfigSpec, ForgeConfigSpec)} - * or {@link #searchForSpecsInModContainer()} - * - * @param modID the modID of your addon/mod - */ - public static void setDefaultActionFor(String modID, UnaryOperator transform) { - if (modID.equals(Create.ID)) - return; - - DEFAULTS.put(modID, transform); - } - - public static BaseConfigScreen forCreate(Screen parent) { - return new BaseConfigScreen(parent); - } - - BoxWidget clientConfigWidget; - BoxWidget commonConfigWidget; - BoxWidget serverConfigWidget; - BoxWidget goBack; - BoxWidget others; - BoxWidget title; - - ForgeConfigSpec clientSpec; - ForgeConfigSpec commonSpec; - ForgeConfigSpec serverSpec; - String clientTitle = "Client Config"; - String commonTitle = "Common Config"; - String serverTitle = "Server Config"; - String modID; - protected boolean returnOnClose; - - public BaseConfigScreen(Screen parent, @Nonnull String modID) { - super(parent); - this.modID = modID; - - if (DEFAULTS.containsKey(modID)) - DEFAULTS.get(modID).apply(this); - else { - this.searchForSpecsInModContainer(); - } - } - - private BaseConfigScreen(Screen parent) { - this(parent, Create.ID); - } - - /** - * If you have static references to your Configs or ConfigSpecs (like Create does in {@link AllConfigs}), - * please use {@link #withSpecs(ForgeConfigSpec, ForgeConfigSpec, ForgeConfigSpec)} instead - */ - public BaseConfigScreen searchForSpecsInModContainer() { - if (!ConfigHelper.hasAnyForgeConfig(this.modID)){ - return this; - } - - try { - clientSpec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.CLIENT, this.modID); - } catch (Exception e) { - Create.LOGGER.debug("Unable to find ClientConfigSpec for mod: " + this.modID); - } - - try { - commonSpec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.COMMON, this.modID); - } catch (Exception e) { - Create.LOGGER.debug("Unable to find CommonConfigSpec for mod: " + this.modID); - } - - try { - serverSpec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.SERVER, this.modID); - } catch (Exception e) { - Create.LOGGER.debug("Unable to find ServerConfigSpec for mod: " + this.modID); - } - - return this; - } - - public BaseConfigScreen withSpecs(@Nullable ForgeConfigSpec client, @Nullable ForgeConfigSpec common, @Nullable ForgeConfigSpec server) { - clientSpec = client; - commonSpec = common; - serverSpec = server; - return this; - } - - public BaseConfigScreen withTitles(@Nullable String client, @Nullable String common, @Nullable String server) { - if (client != null) - clientTitle = client; - - if (common != null) - commonTitle = common; - - if (server != null) - serverTitle = server; - - return this; - } - - @Override - protected void init() { - super.init(); - returnOnClose = true; - - TextStencilElement clientText = new TextStencilElement(font, Components.literal(clientTitle)).centered(true, true); - addRenderableWidget(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16).showingElement(clientText)); - - if (clientSpec != null) { - clientConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, clientSpec))); - clientText.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget)); - } else { - clientConfigWidget.active = false; - clientConfigWidget.updateColorsFromState(); - clientText.withElementRenderer(DISABLED_RENDERER); - } - - TextStencilElement commonText = new TextStencilElement(font, Components.literal(commonTitle)).centered(true, true); - addRenderableWidget(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16).showingElement(commonText)); - - if (commonSpec != null) { - commonConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, commonSpec))); - commonText.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget)); - } else { - commonConfigWidget.active = false; - commonConfigWidget.updateColorsFromState(); - commonText.withElementRenderer(DISABLED_RENDERER); - } - - TextStencilElement serverText = new TextStencilElement(font, Components.literal(serverTitle)).centered(true, true); - addRenderableWidget(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16).showingElement(serverText)); - - if (serverSpec == null) { - serverConfigWidget.active = false; - serverConfigWidget.updateColorsFromState(); - serverText.withElementRenderer(DISABLED_RENDERER); - } else if (minecraft.level == null) { - serverText.withElementRenderer(DISABLED_RENDERER); - serverConfigWidget.getToolTip() - .add(Components.literal("Stored individually per World")); - serverConfigWidget.getToolTip() - .addAll(TooltipHelper.cutTextComponent( - Components.literal( - "Gameplay settings can only be accessed from the in-game menu after joining a World or Server."), - Palette.ALL_GRAY)); - } else { - serverConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, serverSpec))); - serverText.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget)); - } - - TextStencilElement titleText = new TextStencilElement(font, modID.toUpperCase(Locale.ROOT)) - .centered(true, true) - .withElementRenderer((ms, w, h, alpha) -> { - UIRenderHelper.angledGradient(ms, 0, 0, h / 2, h, w / 2, Theme.p(Theme.Key.CONFIG_TITLE_A)); - UIRenderHelper.angledGradient(ms, 0, w / 2, h / 2, h, w / 2, Theme.p(Theme.Key.CONFIG_TITLE_B)); - }); - int boxWidth = width + 10; - int boxHeight = 39; - int boxPadding = 4; - title = new BoxWidget(-5, height / 2 - 110, boxWidth, boxHeight) - //.withCustomBackground(new Color(0x20_000000, true)) - .withBorderColors(Theme.p(Theme.Key.BUTTON_IDLE)) - .withPadding(0, boxPadding) - .rescaleElement(boxWidth / 2f, (boxHeight - 2 * boxPadding) / 2f)//double the text size by telling it the element is only half as big as the available space - .showingElement(titleText.at(0, 7)); - title.active = false; - - addRenderableWidget(title); - - - ConfigScreen.modID = this.modID; - - goBack = new BoxWidget(width / 2 - 134, height / 2, 20, 20).withPadding(2, 2) - .withCallback(() -> linkTo(parent)); - goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil() - .withElementRenderer(BoxWidget.gradientFactory.apply(goBack))); - goBack.getToolTip() - .add(Components.literal("Go Back")); - addRenderableWidget(goBack); - - TextStencilElement othersText = new TextStencilElement(font, Components.literal("Access Configs of other Mods")).centered(true, true); - others = new BoxWidget(width / 2 - 100, height / 2 - 15 + 90, 200, 16).showingElement(othersText); - othersText.withElementRenderer(BoxWidget.gradientFactory.apply(others)); - others.withCallback(() -> linkTo(new ConfigModListScreen(this))); - addRenderableWidget(others); - } - - @Override - protected void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - graphics.drawCenteredString(font, "Access Configs for Mod:", width / 2, height / 2 - 105, Theme.i(Theme.Key.TEXT_ACCENT_STRONG)); - } - - private void linkTo(Screen screen) { - returnOnClose = false; - ScreenOpener.open(screen); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (super.keyPressed(keyCode, scanCode, modifiers)) - return true; - if (keyCode == GLFW.GLFW_KEY_BACKSPACE) { - linkTo(parent); - } - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java b/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java deleted file mode 100644 index 33e715d9c1..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import java.util.Objects; - -import com.simibubi.create.Create; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.network.NetworkEvent; - -public class CConfigureConfigPacket extends SimplePacketBase { - - private String modID; - private String path; - private String value; - - public CConfigureConfigPacket(String modID, String path, T value) { - this.modID = Objects.requireNonNull(modID); - this.path = path; - this.value = serialize(value); - } - - public CConfigureConfigPacket(FriendlyByteBuf buffer) { - this.modID = buffer.readUtf(32767); - this.path = buffer.readUtf(32767); - this.value = buffer.readUtf(32767); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeUtf(modID); - buffer.writeUtf(path); - buffer.writeUtf(value); - } - - @Override - public boolean handle(NetworkEvent.Context context) { - context.enqueueWork(() -> { - try { - ServerPlayer sender = context.getSender(); - if (sender == null || !sender.hasPermissions(2)) - return; - - ForgeConfigSpec spec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.SERVER, modID); - if (spec == null) - return; - ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(path); - ForgeConfigSpec.ConfigValue configValue = spec.getValues().get(path); - - T v = (T) deserialize(configValue.get(), value); - if (!valueSpec.test(v)) - return; - - configValue.set(v); - } catch (Exception e) { - Create.LOGGER.warn("Unable to handle ConfigureConfig Packet. ", e); - } - }); - return true; - } - - public String serialize(T value) { - if (value instanceof Boolean) - return Boolean.toString((Boolean) value); - if (value instanceof Enum) - return ((Enum) value).name(); - if (value instanceof Integer) - return Integer.toString((Integer) value); - if (value instanceof Float) - return Float.toString((Float) value); - if (value instanceof Double) - return Double.toString((Double) value); - - throw new IllegalArgumentException("unknown type " + value + ": " + value.getClass().getSimpleName()); - } - - public static Object deserialize(Object type, String sValue) { - if (type instanceof Boolean) - return Boolean.parseBoolean(sValue); - if (type instanceof Enum) - return Enum.valueOf(((Enum) type).getClass(), sValue); - if (type instanceof Integer) - return Integer.parseInt(sValue); - if (type instanceof Float) - return Float.parseFloat(sValue); - if (type instanceof Double) - return Double.parseDouble(sValue); - - throw new IllegalArgumentException("unknown type " + type + ": " + type.getClass().getSimpleName()); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigAnnotations.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigAnnotations.java deleted file mode 100644 index f52290faef..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigAnnotations.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -public class ConfigAnnotations { - - - /** - * Changes the way the Integer value is display. - */ - public enum IntDisplay implements ConfigAnnotation { - HEX("#"), - ZERO_X("0x"), - ZERO_B("0b"); - - private final String value; - - IntDisplay(String value) { - this.value = value; - } - - @Override - public String getName() { - return "IntDisplay"; - } - - @Override - public String getValue() { - return value; - } - } - - /** - * Indicates to the player that changing this value will require a restart to take full effect - */ - public enum RequiresRestart implements ConfigAnnotation { - CLIENT("client"), - SERVER("server"), - BOTH("both"); - - private final String value; - - RequiresRestart(String value) { - this.value = value; - } - - @Override - public String getName() { - return "RequiresReload"; - } - - @Override - public String getValue() { - return value; - } - } - - /** - * Indicates to the player that changing this value will require them to relog to take full effect - */ - public enum RequiresRelog implements ConfigAnnotation { - TRUE; - - @Override - public String getName() { - return "RequiresRelog"; - } - } - - /** - * Changing a value that is annotated with Execute will cause the player to run the given command automatically. - */ - public static class Execute implements ConfigAnnotation { - - private final String command; - - public static Execute run(String command) { - return new Execute(command); - } - - private Execute(String command) { - this.command = command; - } - - @Override - public String getName() { - return "Execute"; - } - - @Override - public String getValue() { - return command; - } - } - - public interface ConfigAnnotation { - String getName(); - - default String getValue() { - return null; - } - - default String asComment() { - String comment = "[@cui:" + getName(); - String value = getValue(); - if (value != null) { - comment = comment + ":" + value; - } - comment = comment + "]"; - return comment; - } - - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java deleted file mode 100644 index 2a9cc509ae..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import java.util.Arrays; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.infrastructure.config.AllConfigs; - -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.config.IConfigSpec; -import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.fml.util.ObfuscationReflectionHelper; - -public class ConfigHelper { - - public static final Pattern unitPattern = Pattern.compile("\\[(in .*)]"); - public static final Pattern annotationPattern = Pattern.compile("\\[@cui:([^:]*)(?::(.*))?]"); - - public static final Map changes = new HashMap<>(); - private static final LoadingCache> configCache = - CacheBuilder.newBuilder() - .expireAfterAccess(5, TimeUnit.MINUTES) - .build(new CacheLoader>() { - @Override - public EnumMap load(@Nonnull String key) { - return findModConfigsUncached(key); - } - }); - - private static EnumMap findModConfigsUncached(String modID) { - ModContainer modContainer = ModList.get() - .getModContainerById(modID) - .orElseThrow(() -> new IllegalArgumentException("Unable to find ModContainer for id: " + modID)); - EnumMap configs = - ObfuscationReflectionHelper.getPrivateValue(ModContainer.class, modContainer, "configs"); - return Objects.requireNonNull(configs); - } - - public static IConfigSpec findConfigSpecFor(ModConfig.Type type, String modID) { - if (!modID.equals(Create.ID)) - return configCache.getUnchecked(modID) - .get(type) - .getSpec(); - return AllConfigs.byType(type).specification; - } - - @Nullable - public static ForgeConfigSpec findForgeConfigSpecFor(ModConfig.Type type, String modID) { - IConfigSpec spec = findConfigSpecFor(type, modID); - if (spec instanceof ForgeConfigSpec) { - return (ForgeConfigSpec) spec; - } - return null; - } - - public static boolean hasAnyConfig(String modID) { - if (!modID.equals(Create.ID)) - return !configCache.getUnchecked(modID) - .isEmpty(); - return true; - } - - public static boolean hasAnyForgeConfig(String modID) { - if (!modID.equals(Create.ID)) - return configCache.getUnchecked(modID) - .values() - .stream() - .anyMatch(config -> config.getSpec() instanceof ForgeConfigSpec); - return true; - } - - // Directly set a value - public static void setConfigValue(ConfigPath path, String value) throws InvalidValueException { - ForgeConfigSpec spec = findForgeConfigSpecFor(path.getType(), path.getModID()); - if (spec == null) - return; - - List pathList = Arrays.asList(path.getPath()); - ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(pathList); - ForgeConfigSpec.ConfigValue configValue = spec.getValues() - .get(pathList); - T v = (T) CConfigureConfigPacket.deserialize(configValue.get(), value); - if (!valueSpec.test(v)) - throw new InvalidValueException(); - - configValue.set(v); - } - - // Add a value to the current UI's changes list - public static void setValue(String path, ForgeConfigSpec.ConfigValue configValue, T value, - @Nullable Map annotations) { - if (value.equals(configValue.get())) { - changes.remove(path); - } else { - changes.put(path, annotations == null ? new ConfigChange(value) : new ConfigChange(value, annotations)); - } - } - - // Get a value from the current UI's changes list or the config value, if its - // unchanged - public static T getValue(String path, ForgeConfigSpec.ConfigValue configValue) { - ConfigChange configChange = changes.get(path); - if (configChange != null) - // noinspection unchecked - return (T) configChange.value; - else - return configValue.get(); - } - - public static Pair> readMetadataFromComment(List commentLines) { - AtomicReference unit = new AtomicReference<>(); - Map annotations = new HashMap<>(); - - commentLines.removeIf(line -> { - if (line.trim() - .isEmpty()) { - return true; - } - - Matcher matcher = annotationPattern.matcher(line); - if (matcher.matches()) { - String annotation = matcher.group(1); - String aValue = matcher.group(2); - annotations.putIfAbsent(annotation, aValue); - - return true; - } - - matcher = unitPattern.matcher(line); - if (matcher.matches()) { - unit.set(matcher.group(1)); - } - - return false; - }); - - return Pair.of(unit.get(), annotations); - } - - public static class ConfigPath { - private String modID = Create.ID; - private ModConfig.Type type = ModConfig.Type.CLIENT; - private String[] path; - - public static ConfigPath parse(String string) { - ConfigPath cp = new ConfigPath(); - String p = string; - int index = string.indexOf(":"); - if (index >= 0) { - p = string.substring(index + 1); - if (index >= 1) { - cp.modID = string.substring(0, index); - } - } - String[] split = p.split("\\."); - try { - cp.type = ModConfig.Type.valueOf(split[0].toUpperCase(Locale.ROOT)); - } catch (Exception e) { - throw new IllegalArgumentException("path must start with either 'client.', 'common.' or 'server.'"); - } - - cp.path = new String[split.length - 1]; - System.arraycopy(split, 1, cp.path, 0, cp.path.length); - - return cp; - } - - public ConfigPath setID(String modID) { - this.modID = modID; - return this; - } - - public ConfigPath setType(ModConfig.Type type) { - this.type = type; - return this; - } - - public ConfigPath setPath(String[] path) { - this.path = path; - return this; - } - - public String getModID() { - return modID; - } - - public ModConfig.Type getType() { - return type; - } - - public String[] getPath() { - return path; - } - } - - public static class ConfigChange { - Object value; - Map annotations; - - ConfigChange(Object value) { - this.value = value; - } - - ConfigChange(Object value, Map annotations) { - this(value); - this.annotations = new HashMap<>(); - this.annotations.putAll(annotations); - } - } - - public static class InvalidValueException extends Exception { - private static final long serialVersionUID = 1L; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigModListScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigModListScreen.java deleted file mode 100644 index bdca1a273c..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigModListScreen.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import org.lwjgl.glfw.GLFW; - -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.forgespi.language.IModInfo; - -public class ConfigModListScreen extends ConfigScreen { - - ConfigScreenList list; - HintableTextFieldWidget search; - BoxWidget goBack; - List allEntries; - - public ConfigModListScreen(Screen parent) { - super(parent); - } - - @Override - protected void init() { - super.init(); - - int listWidth = Math.min(width - 80, 300); - - list = new ConfigScreenList(minecraft, listWidth, height - 60, 15, height - 45, 40); - list.setLeftPos(this.width / 2 - list.getWidth() / 2); - addRenderableWidget(list); - - allEntries = new ArrayList<>(); - ModList.get().getMods().stream().map(IModInfo::getModId).forEach(id -> allEntries.add(new ModEntry(id, this))); - allEntries.sort((e1, e2) -> { - int empty = (e2.button.active ? 1 : 0) - (e1.button.active ? 1 : 0); - if (empty != 0) - return empty; - - return e1.id.compareToIgnoreCase(e2.id); - }); - list.children().clear(); - list.children().addAll(allEntries); - - goBack = new BoxWidget(width / 2 - listWidth / 2 - 30, height / 2 + 65, 20, 20).withPadding(2, 2) - .withCallback(() -> ScreenOpener.open(parent)); - goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil() - .withElementRenderer(BoxWidget.gradientFactory.apply(goBack))); - goBack.getToolTip() - .add(Components.literal("Go Back")); - addRenderableWidget(goBack); - - search = new HintableTextFieldWidget(font, width / 2 - listWidth / 2, height - 35, listWidth, 20); - search.setResponder(this::updateFilter); - search.setHint("Search..."); - search.moveCursorToStart(); - addRenderableWidget(search); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (super.keyPressed(keyCode, scanCode, modifiers)) - return true; - if (keyCode == GLFW.GLFW_KEY_BACKSPACE) { - ScreenOpener.open(parent); - } - return false; - } - - private void updateFilter(String search) { - list.children().clear(); - allEntries - .stream() - .filter(modEntry -> modEntry.id.contains(search.toLowerCase(Locale.ROOT))) - .forEach(list.children()::add); - - list.setScrollAmount(list.getScrollAmount()); - if (list.children().size() > 0) { - this.search.setTextColor(Theme.i(Theme.Key.TEXT)); - } else { - this.search.setTextColor(Theme.i(Theme.Key.BUTTON_FAIL)); - } - } - - public static class ModEntry extends ConfigScreenList.LabeledEntry { - - protected BoxWidget button; - protected String id; - - public ModEntry(String id, Screen parent) { - super(toHumanReadable(id)); - this.id = id; - - button = new BoxWidget(0, 0, 35, 16) - .showingElement(AllIcons.I_CONFIG_OPEN.asStencil().at(10, 0)); - button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(button))); - - if (ConfigHelper.hasAnyForgeConfig(id)) { - button.withCallback(() -> ScreenOpener.open(new BaseConfigScreen(parent, id))); - } else { - button.active = false; - button.updateColorsFromState(); - button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BaseConfigScreen.DISABLED_RENDERER)); - labelTooltip.add(Components.literal(toHumanReadable(id))); - labelTooltip.addAll(TooltipHelper.cutStringTextComponent("This Mod does not have any configs registered or is not using Forge's config system", Palette.ALL_GRAY)); - } - - listeners.add(button); - } - - public String getId() { - return id; - } - - @Override - public void tick() { - super.tick(); - button.tick(); - } - - @Override - public void render(GuiGraphics graphics, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) { - super.render(graphics, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); - - button.setX(x + width - 108); - button.setY(y + 10); - button.setHeight(height - 20); - button.render(graphics, mouseX, mouseY, partialTicks); - } - - @Override - protected int getLabelWidth(int totalWidth) { - return (int) (totalWidth * labelWidthMult) + 30; - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java deleted file mode 100644 index 7742e3ee96..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.util.TriConsumer; -import org.lwjgl.opengl.GL30; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.gui.element.StencilElement; -import com.simibubi.create.foundation.utility.animation.Force; -import com.simibubi.create.foundation.utility.animation.PhysicalFloat; -import com.simibubi.create.infrastructure.gui.CreateMainMenuScreen; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.client.event.ScreenEvent; - -public abstract class ConfigScreen extends AbstractSimiScreen { - - /* - * - * TODO - * - * reduce number of packets sent to the server when saving a bunch of values - * - * FIXME - * - * tooltips are hidden underneath the scrollbar, if the bar is near the middle - * - */ - - public static final Map> backgrounds = new HashMap<>(); - public static final PhysicalFloat cogSpin = PhysicalFloat.create().withLimit(10f).withDrag(0.3).addForce(new Force.Static(.2f)); - public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().setValue(CogWheelBlock.AXIS, Direction.Axis.Y); - public static String modID = null; - protected final Screen parent; - - public ConfigScreen(Screen parent) { - this.parent = parent; - } - - @Override - public void tick() { - super.tick(); - cogSpin.tick(); - } - - @Override - public void renderBackground(GuiGraphics graphics) { - net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new ScreenEvent.BackgroundRendered(this, graphics)); - } - - @Override - protected void renderWindowBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - if (this.minecraft != null && this.minecraft.level != null) { - //in game - graphics.fill(0, 0, this.width, this.height, 0xb0_282c34); - } else { - //in menus - renderMenuBackground(graphics, partialTicks); - } - - new StencilElement() { - @Override - protected void renderStencil(GuiGraphics graphics) { - renderCog(graphics, partialTicks); - } - - @Override - protected void renderElement(GuiGraphics graphics) { - graphics.fill(-200, -200, 200, 200, 0x60_000000); - } - }.at(width * 0.5f, height * 0.5f, 0).render(graphics); - - super.renderWindowBackground(graphics, mouseX, mouseY, partialTicks); - - } - - @Override - protected void prepareFrame() { - UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer); - RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); - } - - @Override - protected void endFrame() { - UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget()); - } - - @Override - protected void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - } - - @Override - public boolean mouseScrolled(double mouseX, double mouseY, double delta) { - cogSpin.bump(3, -delta * 5); - - return super.mouseScrolled(mouseX, mouseY, delta); - } - - @Override - public boolean isPauseScreen() { - return true; - } - - public static String toHumanReadable(String key) { - String s = key.replaceAll("_", " "); - s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(s)).map(StringUtils::capitalize).collect(Collectors.joining(" ")); - s = StringUtils.normalizeSpace(s); - return s; - } - - /** - * By default ConfigScreens will render the Create Panorama as - * their background when opened from the Main- or ModList-Menu. - * If your addon wants to render something else, please add to the - * backgrounds Map in this Class with your modID as the key. - */ - protected void renderMenuBackground(GuiGraphics graphics, float partialTicks) { - TriConsumer customBackground = backgrounds.get(modID); - if (customBackground != null) { - customBackground.accept(this, graphics, partialTicks); - return; - } - - float elapsedPartials = minecraft.getDeltaFrameTime(); - CreateMainMenuScreen.PANORAMA.render(elapsedPartials, 1); - - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - graphics.blit(CreateMainMenuScreen.PANORAMA_OVERLAY_TEXTURES, 0, 0, this.width, this.height, 0.0F, 0.0F, 16, 128, 16, 128); - - graphics.fill(0, 0, this.width, this.height, 0x90_282c34); - } - - protected void renderCog(GuiGraphics graphics, float partialTicks) { - PoseStack ms = graphics.pose(); - ms.pushPose(); - - ms.translate(-100, 100, -100); - ms.scale(200, 200, 1); - GuiGameElement.of(cogwheelState) - .rotateBlock(22.5, cogSpin.getValue(partialTicks), 22.5) - .render(graphics); - - ms.popPose(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java deleted file mode 100644 index 1831c5d8ac..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.systems.RenderSystem; -import com.simibubi.create.foundation.config.ui.entries.NumberEntry; -import com.simibubi.create.foundation.gui.RemovedGuiUtils; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.TickableGuiEventListener; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.TextStencilElement; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.EditBox; -import net.minecraft.client.gui.components.ObjectSelectionList; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; - -public class ConfigScreenList extends ObjectSelectionList implements TickableGuiEventListener { - - public static EditBox currentText; - - public ConfigScreenList(Minecraft client, int width, int height, int top, int bottom, int elementHeight) { - super(client, width, height, top, bottom, elementHeight); - setRenderBackground(false); - setRenderTopAndBottom(false); - setRenderSelection(false); - currentText = null; - headerHeight = 3; - } - - @Override - public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - Color c = new Color(0x60_000000); - UIRenderHelper.angledGradient(graphics, 90, x0 + width / 2, y0, width, 5, c, Color.TRANSPARENT_BLACK); - UIRenderHelper.angledGradient(graphics, -90, x0 + width / 2, y1, width, 5, c, Color.TRANSPARENT_BLACK); - UIRenderHelper.angledGradient(graphics, 0, x0, y0 + height / 2, height, 5, c, Color.TRANSPARENT_BLACK); - UIRenderHelper.angledGradient(graphics, 180, x1, y0 + height / 2, height, 5, c, Color.TRANSPARENT_BLACK); - - super.render(graphics, mouseX, mouseY, partialTicks); - } - - @Override - protected void renderList(GuiGraphics graphics, int p_239229_, int p_239230_, float p_239231_) { - Window window = minecraft.getWindow(); - double d0 = window.getGuiScale(); - RenderSystem.enableScissor((int) (this.x0 * d0), (int) (window.getHeight() - (this.y1 * d0)), (int) (this.width * d0), (int) (this.height * d0)); - super.renderList(graphics, p_239229_, p_239230_, p_239231_); - RenderSystem.disableScissor(); - } - - @Override - public boolean mouseClicked(double x, double y, int button) { - children().stream().filter(e -> e instanceof NumberEntry).forEach(e -> e.mouseClicked(x, y, button)); - - return super.mouseClicked(x, y, button); - } - - @Override - public int getRowWidth() { - return width - 16; - } - - @Override - protected int getScrollbarPosition() { - return x0 + this.width - 6; - } - - @Override - public void tick() { - /*for(int i = 0; i < getItemCount(); ++i) { - int top = this.getRowTop(i); - int bot = top + itemHeight; - if (bot >= this.y0 && top <= this.y1) - this.getEntry(i).tick(); - }*/ - children().forEach(Entry::tick); - - } - - public boolean search(String query) { - if (query == null || query.isEmpty()) { - setScrollAmount(0); - return true; - } - - String q = query.toLowerCase(Locale.ROOT); - Optional first = children().stream().filter(entry -> { - if (entry.path == null) - return false; - - String[] split = entry.path.split("\\."); - String key = split[split.length - 1].toLowerCase(Locale.ROOT); - return key.contains(q); - }).findFirst(); - - if (!first.isPresent()) { - setScrollAmount(0); - return false; - } - - Entry e = first.get(); - e.annotations.put("highlight", "(:"); - centerScrollOn(e); - return true; - } - - public void bumpCog(float force) { - ConfigScreen.cogSpin.bump(3, force); - } - - public static abstract class Entry extends ObjectSelectionList.Entry implements TickableGuiEventListener { - protected List listeners; - protected Map annotations; - protected String path; - - protected Entry() { - listeners = new ArrayList<>(); - annotations = new HashMap<>(); - } - - @Override - public boolean mouseClicked(double x, double y, int button) { - return getGuiListeners().stream().anyMatch(l -> l.mouseClicked(x, y, button)); - } - - @Override - public boolean keyPressed(int code, int keyPressed_2_, int keyPressed_3_) { - return getGuiListeners().stream().anyMatch(l -> l.keyPressed(code, keyPressed_2_, keyPressed_3_)); - } - - @Override - public boolean charTyped(char ch, int code) { - return getGuiListeners().stream().anyMatch(l -> l.charTyped(ch, code)); - } - - @Override - public void tick() {} - - public List getGuiListeners() { - return listeners; - } - - protected void setEditable(boolean b) {} - - protected boolean isCurrentValueChanged() { - if (path == null) { - return false; - } - return ConfigHelper.changes.containsKey(path); - } - } - - public static class LabeledEntry extends Entry { - - protected static final float labelWidthMult = 0.4f; - - protected TextStencilElement label; - protected List labelTooltip; - protected String unit = null; - protected LerpedFloat differenceAnimation = LerpedFloat.linear().startWithValue(0); - protected LerpedFloat highlightAnimation = LerpedFloat.linear().startWithValue(0); - - public LabeledEntry(String label) { - this.label = new TextStencilElement(Minecraft.getInstance().font, label); - this.label.withElementRenderer((graphics, width, height, alpha) -> UIRenderHelper.angledGradient(graphics, - 0, 0, height / 2, height, width, Theme.p(Theme.Key.TEXT_ACCENT_STRONG))); - labelTooltip = new ArrayList<>(); - } - - public LabeledEntry(String label, String path) { - this(label); - this.path = path; - } - - @Override - public void tick() { - differenceAnimation.tickChaser(); - highlightAnimation.tickChaser(); - super.tick(); - } - - @Override - public void render(GuiGraphics graphics, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) { - if (isCurrentValueChanged()) { - if (differenceAnimation.getChaseTarget() != 1) - differenceAnimation.chase(1, .5f, LerpedFloat.Chaser.EXP); - } else { - if (differenceAnimation.getChaseTarget() != 0) - differenceAnimation.chase(0, .6f, LerpedFloat.Chaser.EXP); - } - - float animation = differenceAnimation.getValue(partialTicks); - if (animation > .1f) { - int offset = (int) (30 * (1 - animation)); - - if (annotations.containsKey(ConfigAnnotations.RequiresRestart.CLIENT.getName())) { - UIRenderHelper.streak(graphics, 180, x + width + 10 + offset, y + height / 2, height - 6, 110, new Color(0x50_601010)); - } else if (annotations.containsKey(ConfigAnnotations.RequiresRelog.TRUE.getName())) { - UIRenderHelper.streak(graphics, 180, x + width + 10 + offset, y + height / 2, height - 6, 110, new Color(0x40_eefb17)); - } - - UIRenderHelper.breadcrumbArrow(graphics, x - 10 - offset, y + 6, 0, -20, 24, -18, new Color(0x70_ffffff), Color.TRANSPARENT_BLACK); - } - - UIRenderHelper.streak(graphics, 0, x - 10, y + height / 2, height - 6, width / 8 * 7, 0xdd_000000); - UIRenderHelper.streak(graphics, 180, x + (int) (width * 1.35f) + 10, y + height / 2, height - 6, width / 8 * 7, 0xdd_000000); - MutableComponent component = label.getComponent(); - Font font = Minecraft.getInstance().font; - if (font.width(component) > getLabelWidth(width) - 10) { - label.withText(font.substrByWidth(component, getLabelWidth(width) - 15).getString() + "..."); - } - if (unit != null) { - int unitWidth = font.width(unit); - graphics.drawString(font, unit, x + getLabelWidth(width) - unitWidth - 5, y + height / 2 + 2, Theme.i(Theme.Key.TEXT_DARKER), false); - label.at(x + 10, y + height / 2 - 10, 0).render(graphics); - } else { - label.at(x + 10, y + height / 2 - 4, 0).render(graphics); - } - - if (annotations.containsKey("highlight")) { - highlightAnimation.startWithValue(1).chase(0, 0.1f, LerpedFloat.Chaser.LINEAR); - annotations.remove("highlight"); - } - - animation = highlightAnimation.getValue(partialTicks); - if (animation > .01f) { - Color highlight = new Color(0xa0_ffffff).scaleAlpha(animation); - UIRenderHelper.streak(graphics, 0, x - 10, y + height / 2, height - 6, 5, highlight); - UIRenderHelper.streak(graphics, 180, x + width, y + height / 2, height - 6, 5, highlight); - UIRenderHelper.streak(graphics, 90, x + width / 2 - 5, y + 3, width + 10, 5, highlight); - UIRenderHelper.streak(graphics, -90, x + width / 2 - 5, y + height - 3, width + 10, 5, highlight); - } - - - if (mouseX > x && mouseX < x + getLabelWidth(width) && mouseY > y + 5 && mouseY < y + height - 5) { - List tooltip = getLabelTooltip(); - if (tooltip.isEmpty()) - return; - - RenderSystem.disableScissor(); - Screen screen = Minecraft.getInstance().screen; - RemovedGuiUtils.drawHoveringText(graphics, tooltip, mouseX, mouseY, screen.width, screen.height, 700, font); - GlStateManager._enableScissorTest(); - } - } - - public List getLabelTooltip() { - return labelTooltip; - } - - protected int getLabelWidth(int totalWidth) { - return totalWidth; - } - - // TODO 1.17 - @Override - public Component getNarration() { - return Components.immutableEmpty(); - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigTextField.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigTextField.java deleted file mode 100644 index 4386a79a2a..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigTextField.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import net.minecraft.client.gui.Font; - -public class ConfigTextField extends HintableTextFieldWidget { - - public ConfigTextField(Font font, int x, int y, int width, int height) { - super(font, x, y, width, height); - } - - @Override - public boolean mouseClicked(double x, double y, int button) { - if (!isMouseOver(x, y)) - setFocused(false); - return super.mouseClicked(x, y, button); - } - - @Override - public void onClick(double pMouseX, double pMouseY) { - super.onClick(pMouseX, pMouseY); - setFocused(true); - } - - @Override - public void setFocused(boolean focus) { - super.setFocused(focus); - - if (!focus) { - if (ConfigScreenList.currentText == this) - ConfigScreenList.currentText = null; - - return; - } - - if (ConfigScreenList.currentText != null && ConfigScreenList.currentText != this) - ConfigScreenList.currentText.setFocused(false); - - ConfigScreenList.currentText = this; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/HintableTextFieldWidget.java b/src/main/java/com/simibubi/create/foundation/config/ui/HintableTextFieldWidget.java deleted file mode 100644 index 52d20cc7f0..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/HintableTextFieldWidget.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import org.lwjgl.glfw.GLFW; - -import com.mojang.blaze3d.platform.InputConstants; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.EditBox; - -public class HintableTextFieldWidget extends EditBox { - - protected Font font; - protected String hint; - - public HintableTextFieldWidget(Font font, int x, int y, int width, int height) { - super(font, x, y, width, height, Components.immutableEmpty()); - this.font = font; - } - - public void setHint(String hint) { - this.hint = hint; - } - - @Override - public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.renderWidget(graphics, mouseX, mouseY, partialTicks); - - if (hint == null || hint.isEmpty()) - return; - - if (!getValue().isEmpty()) - return; - - graphics.drawString(font, hint, getX() + 5, this.getY() + (this.height - 8) / 2, Theme.c(Theme.Key.TEXT).scaleAlpha(.75f).getRGB(), false); - } - - @Override - public boolean mouseClicked(double x, double y, int button) { - if (!isMouseOver(x, y)) - return false; - - if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { - setValue(""); - return true; - } else - return super.mouseClicked(x, y, button); - } - - @Override - public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) { - InputConstants.Key mouseKey = InputConstants.getKey(code, p_keyPressed_2_); - if (Minecraft.getInstance().options.keyInventory.isActiveAndMatches(mouseKey)) { - return true; - } - - return super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java deleted file mode 100644 index d33db3ce20..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java +++ /dev/null @@ -1,470 +0,0 @@ -package com.simibubi.create.foundation.config.ui; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.lwjgl.glfw.GLFW; - -import com.electronwill.nightconfig.core.AbstractConfig; -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import com.google.common.collect.Lists; -import com.simibubi.create.AllPackets; -import com.simibubi.create.foundation.config.ui.ConfigScreenList.LabeledEntry; -import com.simibubi.create.foundation.config.ui.entries.BooleanEntry; -import com.simibubi.create.foundation.config.ui.entries.EnumEntry; -import com.simibubi.create.foundation.config.ui.entries.NumberEntry; -import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry; -import com.simibubi.create.foundation.config.ui.entries.ValueEntry; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.ConfirmationScreen; -import com.simibubi.create.foundation.gui.ConfirmationScreen.Response; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.FormattedText; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.fml.config.ModConfig; - -public class SubMenuConfigScreen extends ConfigScreen { - - public final ModConfig.Type type; - protected ForgeConfigSpec spec; - protected UnmodifiableConfig configGroup; - protected ConfigScreenList list; - - protected BoxWidget resetAll; - protected BoxWidget saveChanges; - protected BoxWidget discardChanges; - protected BoxWidget goBack; - protected BoxWidget serverLocked; - protected HintableTextFieldWidget search; - protected int listWidth; - protected String title; - protected Set highlights = new HashSet<>(); - - public static SubMenuConfigScreen find(ConfigHelper.ConfigPath path) { - // TODO 1.17: can be null - ForgeConfigSpec spec = ConfigHelper.findForgeConfigSpecFor(path.getType(), path.getModID()); - UnmodifiableConfig values = spec.getValues(); - BaseConfigScreen base = new BaseConfigScreen(null, path.getModID()); - SubMenuConfigScreen screen = new SubMenuConfigScreen(base, "root", path.getType(), spec, values); - List remainingPath = Lists.newArrayList(path.getPath()); - - path: while (!remainingPath.isEmpty()) { - String next = remainingPath.remove(0); - for (Map.Entry entry : values.valueMap().entrySet()) { - String key = entry.getKey(); - Object obj = entry.getValue(); - if (!key.equalsIgnoreCase(next)) - continue; - - if (!(obj instanceof AbstractConfig)) { - //highlight entry - screen.highlights.add(path.getPath()[path.getPath().length - 1]); - continue; - } - - values = (UnmodifiableConfig) obj; - screen = new SubMenuConfigScreen(screen, toHumanReadable(key), path.getType(), spec, values); - continue path; - } - - break; - } - - ConfigScreen.modID = path.getModID(); - return screen; - } - - public SubMenuConfigScreen(Screen parent, String title, ModConfig.Type type, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) { - super(parent); - this.type = type; - this.spec = configSpec; - this.title = title; - this.configGroup = configGroup; - } - - public SubMenuConfigScreen(Screen parent, ModConfig.Type type, ForgeConfigSpec configSpec) { - super(parent); - this.type = type; - this.spec = configSpec; - this.title = "root"; - this.configGroup = configSpec.getValues(); - } - - protected void clearChanges() { - ConfigHelper.changes.clear(); - list.children() - .stream() - .filter(e -> e instanceof ValueEntry) - .forEach(e -> ((ValueEntry) e).onValueChange()); - } - - protected void saveChanges() { - UnmodifiableConfig values = spec.getValues(); - ConfigHelper.changes.forEach((path, change) -> { - ForgeConfigSpec.ConfigValue configValue = values.get(path); - configValue.set(change.value); - - if (type == ModConfig.Type.SERVER) { - AllPackets.getChannel().sendToServer(new CConfigureConfigPacket<>(ConfigScreen.modID, path, change.value)); - } - - String command = change.annotations.get("Execute"); - if (minecraft.player != null && command != null && command.startsWith("/")) { - minecraft.player.connection.sendCommand(command.substring(1)); - } - }); - clearChanges(); - } - - protected void resetConfig(UnmodifiableConfig values) { - values.valueMap().forEach((key, obj) -> { - if (obj instanceof AbstractConfig) { - resetConfig((UnmodifiableConfig) obj); - } else if (obj instanceof ForgeConfigSpec.ConfigValue) { - ForgeConfigSpec.ConfigValue configValue = (ForgeConfigSpec.ConfigValue) obj; - ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw((List) configValue.getPath()); - - List comments = new ArrayList<>(); - - if (valueSpec.getComment() != null) - comments.addAll(Arrays.asList(valueSpec.getComment().split("\n"))); - - Pair> metadata = ConfigHelper.readMetadataFromComment(comments); - - ConfigHelper.setValue(String.join(".", configValue.getPath()), configValue, valueSpec.getDefault(), metadata.getSecond()); - } - }); - - list.children() - .stream() - .filter(e -> e instanceof ValueEntry) - .forEach(e -> ((ValueEntry) e).onValueChange()); - } - - @Override - protected void init() { - super.init(); - - listWidth = Math.min(width - 80, 300); - - int yCenter = height / 2; - int listL = this.width / 2 - listWidth / 2; - int listR = this.width / 2 + listWidth / 2; - - resetAll = new BoxWidget(listR + 10, yCenter - 25, 20, 20) - .withPadding(2, 2) - .withCallback((x, y) -> - new ConfirmationScreen() - .centered() - .withText(FormattedText.of("Resetting all settings of the " + type.toString() + " config. Are you sure?")) - .withAction(success -> { - if (success) - resetConfig(spec.getValues()); - }) - .open(this) - ); - - resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll))); - resetAll.getToolTip().add(Components.literal("Reset All")); - resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all settings to their default value.", Palette.ALL_GRAY)); - - saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20) - .withPadding(2, 2) - .withCallback((x, y) -> { - if (ConfigHelper.changes.isEmpty()) - return; - - ConfirmationScreen confirm = new ConfirmationScreen() - .centered() - .withText(FormattedText.of("Saving " + ConfigHelper.changes.size() + " changed value" + (ConfigHelper.changes.size() != 1 ? "s" : "") + "")) - .withAction(success -> { - if (success) - saveChanges(); - }); - - addAnnotationsToConfirm(confirm).open(this); - }); - saveChanges.showingElement(AllIcons.I_CONFIG_SAVE.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(saveChanges))); - saveChanges.getToolTip().add(Components.literal("Save Changes")); - saveChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to save your current changes.", Palette.ALL_GRAY)); - - discardChanges = new BoxWidget(listL - 30, yCenter + 5, 20, 20) - .withPadding(2, 2) - .withCallback((x, y) -> { - if (ConfigHelper.changes.isEmpty()) - return; - - new ConfirmationScreen() - .centered() - .withText(FormattedText.of("Discarding " + ConfigHelper.changes.size() + " unsaved change" + (ConfigHelper.changes.size() != 1 ? "s" : "") + "")) - .withAction(success -> { - if (success) - clearChanges(); - }) - .open(this); - }); - discardChanges.showingElement(AllIcons.I_CONFIG_DISCARD.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(discardChanges))); - discardChanges.getToolTip().add(Components.literal("Discard Changes")); - discardChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to discard all the changes you made.", Palette.ALL_GRAY)); - - goBack = new BoxWidget(listL - 30, yCenter + 65, 20, 20) - .withPadding(2, 2) - .withCallback(this::attemptBackstep); - goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(goBack))); - goBack.getToolTip().add(Components.literal("Go Back")); - - addRenderableWidget(resetAll); - addRenderableWidget(saveChanges); - addRenderableWidget(discardChanges); - addRenderableWidget(goBack); - - list = new ConfigScreenList(minecraft, listWidth, height - 80, 35, height - 45, 40); - list.setLeftPos(this.width / 2 - list.getWidth() / 2); - - addRenderableWidget(list); - - search = new ConfigTextField(font, width / 2 - listWidth / 2, height - 35, listWidth, 20); - search.setResponder(this::updateFilter); - search.setHint("Search..."); - search.moveCursorToStart(); - addRenderableWidget(search); - - configGroup.valueMap().forEach((key, obj) -> { - String humanKey = toHumanReadable(key); - - if (obj instanceof AbstractConfig) { - SubMenuEntry entry = new SubMenuEntry(this, humanKey, spec, (UnmodifiableConfig) obj); - entry.path = key; - list.children().add(entry); - if (configGroup.valueMap() - .size() == 1) - ScreenOpener.open( - new SubMenuConfigScreen(parent, humanKey, type, spec, (UnmodifiableConfig) obj)); - - } else if (obj instanceof ForgeConfigSpec.ConfigValue) { - ForgeConfigSpec.ConfigValue configValue = (ForgeConfigSpec.ConfigValue) obj; - ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath()); - Object value = configValue.get(); - ConfigScreenList.Entry entry = null; - - if (value instanceof Boolean) { - entry = new BooleanEntry(humanKey, (ForgeConfigSpec.ConfigValue) configValue, valueSpec); - } else if (value instanceof Enum) { - entry = new EnumEntry(humanKey, (ForgeConfigSpec.ConfigValue>) configValue, valueSpec); - } else if (value instanceof Number) { - entry = NumberEntry.create(value, humanKey, configValue, valueSpec); - } - - if (entry == null) - entry = new LabeledEntry("Impl missing - " + configValue.get().getClass().getSimpleName() + " " + humanKey + " : " + value); - - if (highlights.contains(key)) - entry.annotations.put("highlight", ":)"); - - list.children().add(entry); - } - }); - - Collections.sort(list.children(), - (e, e2) -> { - int group = (e2 instanceof SubMenuEntry ? 1 : 0) - (e instanceof SubMenuEntry ? 1 : 0); - if (group == 0 && e instanceof LabeledEntry && e2 instanceof LabeledEntry) { - LabeledEntry le = (LabeledEntry) e; - LabeledEntry le2 = (LabeledEntry) e2; - return le.label.getComponent() - .getString() - .compareTo(le2.label.getComponent() - .getString()); - } - return group; - }); - - list.search(highlights.stream().findFirst().orElse("")); - - //extras for server configs - if (type != ModConfig.Type.SERVER) - return; - if (minecraft.hasSingleplayerServer()) - return; - - boolean canEdit = minecraft != null && minecraft.player != null && minecraft.player.hasPermissions(2); - - Couple red = Theme.p(Theme.Key.BUTTON_FAIL); - Couple green = Theme.p(Theme.Key.BUTTON_SUCCESS); - - DelegatedStencilElement stencil = new DelegatedStencilElement(); - - serverLocked = new BoxWidget(listR + 10, yCenter + 5, 20, 20) - .withPadding(2, 2) - .showingElement(stencil); - - if (!canEdit) { - list.children().forEach(e -> e.setEditable(false)); - resetAll.active = false; - stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_LOCKED.render(ms, 0, 0)); - stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, red)); - serverLocked.withBorderColors(red); - serverLocked.getToolTip().add(Components.literal("Locked").withStyle(ChatFormatting.BOLD)); - serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You do not have enough permissions to edit the server config. You can still look at the current values here though.", Palette.ALL_GRAY)); - } else { - stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.render(ms, 0, 0)); - stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, green)); - serverLocked.withBorderColors(green); - serverLocked.getToolTip().add(Components.literal("Unlocked").withStyle(ChatFormatting.BOLD)); - serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You have enough permissions to edit the server config. Changes you make here will be synced with the server when you save them.", Palette.ALL_GRAY)); - } - - addRenderableWidget(serverLocked); - } - - @Override - protected void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.renderWindow(graphics, mouseX, mouseY, partialTicks); - - int x = width / 2; - graphics.drawCenteredString(minecraft.font, ConfigScreen.modID + " > " + type.toString() - .toLowerCase(Locale.ROOT) + " > " + title, x, 15, Theme.i(Theme.Key.TEXT)); - } - - @Override - protected void renderWindowForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.renderWindowForeground(graphics, mouseX, mouseY, partialTicks); - } - - @Override - public void resize(@Nonnull Minecraft client, int width, int height) { - double scroll = list.getScrollAmount(); - init(client, width, height); - list.setScrollAmount(scroll); - } - - @Nullable - @Override - public GuiEventListener getFocused() { - if (ConfigScreenList.currentText != null) - return ConfigScreenList.currentText; - - return super.getFocused(); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (super.keyPressed(keyCode, scanCode, modifiers)) - return true; - - if (Screen.hasControlDown()) { - if (keyCode == GLFW.GLFW_KEY_F) { - search.setFocused(true); - } - } - - if (keyCode == GLFW.GLFW_KEY_BACKSPACE) { - attemptBackstep(); - } - - return false; - } - - private void updateFilter(String search) { - if (list.search(search)) { - this.search.setTextColor(Theme.i(Theme.Key.TEXT)); - } else { - this.search.setTextColor(Theme.i(Theme.Key.BUTTON_FAIL)); - } - } - - private void attemptBackstep() { - if (ConfigHelper.changes.isEmpty() || !(parent instanceof BaseConfigScreen)) { - ScreenOpener.open(parent); - return; - } - - showLeavingPrompt(success -> { - if (success == Response.Cancel) - return; - if (success == Response.Confirm) - saveChanges(); - ConfigHelper.changes.clear(); - ScreenOpener.open(parent); - }); - } - - @Override - public void onClose() { - if (ConfigHelper.changes.isEmpty()) { - super.onClose(); - return; - } - - showLeavingPrompt(success -> { - if (success == Response.Cancel) - return; - if (success == Response.Confirm) - saveChanges(); - ConfigHelper.changes.clear(); - super.onClose(); - }); - } - - public void showLeavingPrompt(Consumer action) { - ConfirmationScreen screen = new ConfirmationScreen() - .centered() - .withThreeActions(action) - .addText(FormattedText.of("Leaving with " + ConfigHelper.changes.size() + " unsaved change" - + (ConfigHelper.changes.size() != 1 ? "s" : "") + " for this config")); - - addAnnotationsToConfirm(screen).open(this); - } - - private ConfirmationScreen addAnnotationsToConfirm(ConfirmationScreen screen) { - AtomicBoolean relog = new AtomicBoolean(false); - AtomicBoolean restart = new AtomicBoolean(false); - ConfigHelper.changes.values().forEach(change -> { - if (change.annotations.containsKey(ConfigAnnotations.RequiresRelog.TRUE.getName())) - relog.set(true); - - if (change.annotations.containsKey(ConfigAnnotations.RequiresRestart.CLIENT.getName())) - restart.set(true); - }); - - if (relog.get()) { - screen.addText(FormattedText.of(" ")); - screen.addText(FormattedText.of("At least one changed value will require you to relog to take full effect")); - } - - if (restart.get()) { - screen.addText(FormattedText.of(" ")); - screen.addText(FormattedText.of("At least one changed value will require you to restart your game to take full effect")); - } - - return screen; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/BooleanEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/BooleanEntry.java deleted file mode 100644 index 40da79c955..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/BooleanEntry.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.foundation.config.ui.entries; - -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.RenderElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.common.ForgeConfigSpec; - -public class BooleanEntry extends ValueEntry { - - RenderElement enabled; - RenderElement disabled; - BoxWidget button; - - public BooleanEntry(String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { - super(label, value, spec); - - enabled = AllIcons.I_CONFIRM.asStencil() - .withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.BUTTON_SUCCESS))) - .at(10, 0); - - disabled = AllIcons.I_DISABLE.asStencil() - .withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.BUTTON_FAIL))) - .at(10, 0); - - button = new BoxWidget().showingElement(enabled) - .withCallback(() -> setValue(!getValue())); - - listeners.add(button); - onReset(); - } - - @Override - protected void setEditable(boolean b) { - super.setEditable(b); - button.active = b; - } - - @Override - public void tick() { - super.tick(); - button.tick(); - } - - @Override - public void render(GuiGraphics graphics, int index, int y, int x, int width, int height, int mouseX, int mouseY, - boolean p_230432_9_, float partialTicks) { - super.render(graphics, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); - - button.setX(x + width - 80 - resetWidth); - button.setY(y + 10); - button.setWidth(35); - button.setHeight(height - 20); - button.render(graphics, mouseX, mouseY, partialTicks); - } - - @Override - public void onValueChange(Boolean newValue) { - super.onValueChange(newValue); - button.showingElement(newValue ? enabled : disabled); - bumpCog(newValue ? 15f : -16f); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java deleted file mode 100644 index a9fda1d3d7..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.simibubi.create.foundation.config.ui.entries; - -import java.util.Locale; - -import com.simibubi.create.foundation.config.ui.ConfigScreen; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.BoxElement; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.element.TextStencilElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.common.ForgeConfigSpec; - -public class EnumEntry extends ValueEntry> { - - protected static final int cycleWidth = 34; - - protected TextStencilElement valueText; - protected BoxWidget cycleLeft; - protected BoxWidget cycleRight; - - public EnumEntry(String label, ForgeConfigSpec.ConfigValue> value, ForgeConfigSpec.ValueSpec spec) { - super(label, value, spec); - - valueText = new TextStencilElement(Minecraft.getInstance().font, "YEP").centered(true, true); - valueText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, - height, width, Theme.p(Theme.Key.TEXT))); - - DelegatedStencilElement l = AllIcons.I_CONFIG_PREV.asStencil(); - cycleLeft = new BoxWidget(0, 0, cycleWidth + 8, 16) - .withCustomBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) - .showingElement(l) - .withCallback(() -> cycleValue(-1)); - l.withElementRenderer(BoxWidget.gradientFactory.apply(cycleLeft)); - - DelegatedStencilElement r = AllIcons.I_CONFIG_NEXT.asStencil(); - cycleRight = new BoxWidget(0, 0, cycleWidth + 8, 16) - .withCustomBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) - .showingElement(r) - .withCallback(() -> cycleValue(1)); - r.at(cycleWidth - 8, 0); - r.withElementRenderer(BoxWidget.gradientFactory.apply(cycleRight)); - - listeners.add(cycleLeft); - listeners.add(cycleRight); - - onReset(); - } - - protected void cycleValue(int direction) { - Enum e = getValue(); - Enum[] options = e.getDeclaringClass() - .getEnumConstants(); - e = options[Math.floorMod(e.ordinal() + direction, options.length)]; - setValue(e); - bumpCog(direction * 15f); - } - - @Override - protected void setEditable(boolean b) { - super.setEditable(b); - cycleLeft.active = b; - cycleLeft.animateGradientFromState(); - cycleRight.active = b; - cycleRight.animateGradientFromState(); - } - - @Override - public void tick() { - super.tick(); - cycleLeft.tick(); - cycleRight.tick(); - } - - @Override - public void render(GuiGraphics graphics, int index, int y, int x, int width, int height, int mouseX, int mouseY, - boolean p_230432_9_, float partialTicks) { - super.render(graphics, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); - - cycleLeft.setX(x + getLabelWidth(width) + 4); - cycleLeft.setY(y + 10); - cycleLeft.render(graphics, mouseX, mouseY, partialTicks); - - valueText.at(cycleLeft.getX() + cycleWidth - 8, y + 10, 200) - .withBounds(width - getLabelWidth(width) - 2 * cycleWidth - resetWidth - 4, 16) - .render(graphics); - - cycleRight.setX(x + width - cycleWidth * 2 - resetWidth + 10); - cycleRight.setY(y + 10); - cycleRight.render(graphics, mouseX, mouseY, partialTicks); - - new BoxElement() - .withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) - .flatBorder(0x01_000000) - .withBounds(48, 6) - .at(cycleLeft.getX() + 22, cycleLeft.getY() + 5) - .render(graphics); - } - - @Override - public void onValueChange(Enum newValue) { - super.onValueChange(newValue); - valueText.withText(ConfigScreen.toHumanReadable(newValue.name().toLowerCase(Locale.ROOT))); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/NumberEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/NumberEntry.java deleted file mode 100644 index 38da03522f..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/NumberEntry.java +++ /dev/null @@ -1,246 +0,0 @@ -package com.simibubi.create.foundation.config.ui.entries; - -import java.lang.reflect.Field; -import java.util.Locale; -import java.util.function.Function; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.config.ui.ConfigTextField; -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.TextStencilElement; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.EditBox; -import net.minecraft.network.chat.MutableComponent; -import net.minecraftforge.common.ForgeConfigSpec; - -public abstract class NumberEntry extends ValueEntry { - - protected int minOffset = 0, maxOffset = 0; - protected TextStencilElement minText = null, maxText = null; - protected EditBox textField; - - @Nullable - public static NumberEntry create(Object type, String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { - if (type instanceof Integer) { - return new IntegerEntry(label, (ForgeConfigSpec.ConfigValue) value, spec); - } else if (type instanceof Float) { - return new FloatEntry(label, (ForgeConfigSpec.ConfigValue) value, spec); - } else if (type instanceof Double) { - return new DoubleEntry(label, (ForgeConfigSpec.ConfigValue) value, spec); - } - - return null; - } - - public NumberEntry(String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { - super(label, value, spec); - textField = new ConfigTextField(Minecraft.getInstance().font, 0, 0, 200, 20); - if (this instanceof IntegerEntry && annotations.containsKey("IntDisplay")) { - String intDisplay = annotations.get("IntDisplay"); - int intValue = (Integer) getValue(); - String textValue; - switch (intDisplay) { - case "#": - textValue = "#" + Integer.toHexString(intValue).toUpperCase(Locale.ROOT); - break; - case "0x": - textValue = "0x" + Integer.toHexString(intValue).toUpperCase(Locale.ROOT); - break; - case "0b": - textValue = "0b" + Integer.toBinaryString(intValue); - break; - default: - textValue = String.valueOf(intValue); - } - textField.setValue(textValue); - } else { - textField.setValue(String.valueOf(getValue())); - } - textField.setTextColor(Theme.i(Theme.Key.TEXT)); - - Object range = spec.getRange(); - try { - Field minField = range.getClass().getDeclaredField("min"); - Field maxField = range.getClass().getDeclaredField("max"); - minField.setAccessible(true); - maxField.setAccessible(true); - T min = (T) minField.get(range); - T max = (T) maxField.get(range); - - Font font = Minecraft.getInstance().font; - if (min.doubleValue() > getTypeMin().doubleValue()) { - MutableComponent t = Components.literal(formatBound(min) + " < "); - minText = new TextStencilElement(font, t).centered(true, false); - minText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.p(Theme.Key.TEXT_DARKER))); - minOffset = font.width(t); - } - if (max.doubleValue() < getTypeMax().doubleValue()) { - MutableComponent t = Components.literal(" < " + formatBound(max)); - maxText = new TextStencilElement(font, t).centered(true, false); - maxText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.p(Theme.Key.TEXT_DARKER))); - maxOffset = font.width(t); - } - } catch (NoSuchFieldException | IllegalAccessException | ClassCastException | NullPointerException ignored) { - - } - - textField.setResponder(s -> { - try { - T number = getParser().apply(s); - if (!spec.test(number)) - throw new IllegalArgumentException(); - - textField.setTextColor(Theme.i(Theme.Key.TEXT)); - setValue(number); - - } catch (IllegalArgumentException ignored) { - textField.setTextColor(Theme.i(Theme.Key.BUTTON_FAIL)); - } - }); - - textField.moveCursorToStart(); - listeners.add(textField); - onReset(); - } - - protected String formatBound(T bound) { - String sci = String.format("%.2E", bound.doubleValue()); - String str = String.valueOf(bound); - return sci.length() < str.length() ? sci : str; - } - - protected abstract T getTypeMin(); - - protected abstract T getTypeMax(); - - protected abstract Function getParser(); - - @Override - protected void setEditable(boolean b) { - super.setEditable(b); - textField.setEditable(b); - } - - @Override - public void onValueChange(T newValue) { - super.onValueChange(newValue); - - try { - T current = getParser().apply(textField.getValue()); - if (!current.equals(newValue)) { - textField.setValue(String.valueOf(newValue)); - } - } catch (IllegalArgumentException ignored) {} - } - - @Override - public void tick() { - super.tick(); - textField.tick(); - } - - @Override - public void render(GuiGraphics graphics, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) { - super.render(graphics, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); - - textField.setX(x + width - 82 - resetWidth); - textField.setY(y + 8); - textField.setWidth(Math.min(width - getLabelWidth(width) - resetWidth - minOffset - maxOffset, 40)); - textField.setHeight(20); - textField.render(graphics, mouseX, mouseY, partialTicks); - - if (minText != null) - minText - .at(textField.getX() - minOffset, textField.getY(), 0) - .withBounds(minOffset, textField.getHeight()) - .render(graphics); - - if (maxText != null) - maxText - .at(textField.getX() + textField.getWidth(), textField.getY(), 0) - .withBounds(maxOffset, textField.getHeight()) - .render(graphics); - } - - public static class IntegerEntry extends NumberEntry { - - public IntegerEntry(String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { - super(label, value, spec); - } - - @Override - protected Integer getTypeMin() { - return Integer.MIN_VALUE; - } - - @Override - protected Integer getTypeMax() { - return Integer.MAX_VALUE; - } - - @Override - protected Function getParser() { - return (string) -> { - if (string.startsWith("#")) { - return Integer.parseUnsignedInt(string.substring(1), 16); - } else if (string.startsWith("0x")) { - return Integer.parseUnsignedInt(string.substring(2), 16); - } else if (string.startsWith("0b")) { - return Integer.parseUnsignedInt(string.substring(2), 2); - } else { - return Integer.parseInt(string); - } - }; - } - } - - public static class FloatEntry extends NumberEntry { - - public FloatEntry(String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { - super(label, value, spec); - } - - @Override - protected Float getTypeMin() { - return -Float.MAX_VALUE; - } - - @Override - protected Float getTypeMax() { - return Float.MAX_VALUE; - } - - @Override - protected Function getParser() { - return Float::parseFloat; - } - } - - public static class DoubleEntry extends NumberEntry { - - public DoubleEntry(String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { - super(label, value, spec); - } - - @Override - protected Double getTypeMin() { - return (double) -Float.MAX_VALUE; - } - - @Override - protected Double getTypeMax() { - return (double) Float.MAX_VALUE; - } - - @Override - protected Function getParser() { - return Double::parseDouble; - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/SubMenuEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/SubMenuEntry.java deleted file mode 100644 index 2d340c0140..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/SubMenuEntry.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.foundation.config.ui.entries; - -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import com.simibubi.create.foundation.config.ui.ConfigScreenList; -import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.common.ForgeConfigSpec; - -public class SubMenuEntry extends ConfigScreenList.LabeledEntry { - - protected BoxWidget button; - - public SubMenuEntry(SubMenuConfigScreen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) { - super(label); - - button = new BoxWidget(0, 0, 35, 16) - .showingElement(AllIcons.I_CONFIG_OPEN.asStencil().at(10, 0)) - .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config))); - button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(button))); - - listeners.add(button); - } - - @Override - public void tick() { - super.tick(); - button.tick(); - } - - @Override - public void render(GuiGraphics graphics, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) { - super.render(graphics, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); - - button.setX(x + width - 108); - button.setY(y + 10); - button.setHeight(height - 20); - button.render(graphics, mouseX, mouseY, partialTicks); - } - - @Override - protected int getLabelWidth(int totalWidth) { - return (int) (totalWidth * labelWidthMult) + 30; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java deleted file mode 100644 index 98d138f00e..0000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.simibubi.create.foundation.config.ui.entries; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import javax.annotation.Nonnull; - -import com.google.common.base.Predicates; -import com.simibubi.create.foundation.config.ui.ConfigAnnotations; -import com.simibubi.create.foundation.config.ui.ConfigHelper; -import com.simibubi.create.foundation.config.ui.ConfigScreen; -import com.simibubi.create.foundation.config.ui.ConfigScreenList; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Pair; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.common.ForgeConfigSpec; - -public class ValueEntry extends ConfigScreenList.LabeledEntry { - - protected static final int resetWidth = 28;//including 6px offset on either side - - protected ForgeConfigSpec.ConfigValue value; - protected ForgeConfigSpec.ValueSpec spec; - protected BoxWidget resetButton; - protected boolean editable = true; - - public ValueEntry(String label, ForgeConfigSpec.ConfigValue value, ForgeConfigSpec.ValueSpec spec) { - super(label); - this.value = value; - this.spec = spec; - this.path = String.join(".", value.getPath()); - - resetButton = new BoxWidget(0, 0, resetWidth - 12, 16) - .showingElement(AllIcons.I_CONFIG_RESET.asStencil()) - .withCallback(() -> { - setValue((T) spec.getDefault()); - this.onReset(); - }); - resetButton.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(resetButton))); - - listeners.add(resetButton); - - List path = value.getPath(); - labelTooltip.add(Components.literal(label).withStyle(ChatFormatting.WHITE)); - String comment = spec.getComment(); - if (comment == null || comment.isEmpty()) - return; - - List commentLines = new ArrayList<>(Arrays.asList(comment.split("\n"))); - - - Pair> metadata = ConfigHelper.readMetadataFromComment(commentLines); - if (metadata.getFirst() != null) { - unit = metadata.getFirst(); - } - if (metadata.getSecond() != null && !metadata.getSecond().isEmpty()) { - annotations.putAll(metadata.getSecond()); - } - // add comment to tooltip - labelTooltip.addAll(commentLines.stream() - .filter(Predicates.not(s -> s.startsWith("Range"))) - .filter(s -> !s.equals(".")) - .map(Components::literal) - .flatMap(stc -> TooltipHelper.cutTextComponent(stc, Palette.ALL_GRAY) - .stream()) - .collect(Collectors.toList())); - - if (annotations.containsKey(ConfigAnnotations.RequiresRelog.TRUE.getName())) - labelTooltip.addAll(TooltipHelper.cutStringTextComponent("Changing this value will require a _relog_ to take full effect", Palette.GRAY_AND_GOLD)); - - if (annotations.containsKey(ConfigAnnotations.RequiresRestart.CLIENT.getName())) - labelTooltip.addAll(TooltipHelper.cutStringTextComponent("Changing this value will require a _restart_ to take full effect", Palette.GRAY_AND_RED)); - - labelTooltip.add(Components.literal(ConfigScreen.modID + ":" + path.get(path.size() - 1)).withStyle(ChatFormatting.DARK_GRAY)); - } - - @Override - protected void setEditable(boolean b) { - editable = b; - resetButton.active = editable && !isCurrentValueDefault(); - resetButton.animateGradientFromState(); - } - - @Override - public void tick() { - super.tick(); - resetButton.tick(); - } - - @Override - public void render(GuiGraphics graphics, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) { - super.render(graphics, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks); - - resetButton.setX(x + width - resetWidth + 6); - resetButton.setY(y + 10); - resetButton.render(graphics, mouseX, mouseY, partialTicks); - } - - @Override - protected int getLabelWidth(int totalWidth) { - return (int) (totalWidth * labelWidthMult) + 30; - } - - public void setValue(@Nonnull T value) { - ConfigHelper.setValue(path, this.value, value, annotations); - onValueChange(value); - } - - @Nonnull - public T getValue() { - return ConfigHelper.getValue(path, this.value); - } - - protected boolean isCurrentValueDefault() { - return spec.getDefault().equals(getValue()); - } - - public void onReset() { - onValueChange(getValue()); - } - - public void onValueChange() { - onValueChange(getValue()); - } - public void onValueChange(T newValue) { - resetButton.active = editable && !isCurrentValueDefault(); - resetButton.animateGradientFromState(); - } - - protected void bumpCog() {bumpCog(10f);} - protected void bumpCog(float force) { - if (list != null && list instanceof ConfigScreenList) - ((ConfigScreenList) list).bumpCog(force); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/data/AssetLookup.java b/src/main/java/com/simibubi/create/foundation/data/AssetLookup.java index 4cbc165440..48c11a94ad 100644 --- a/src/main/java/com/simibubi/create/foundation/data/AssetLookup.java +++ b/src/main/java/com/simibubi/create/foundation/data/AssetLookup.java @@ -28,7 +28,8 @@ public class AssetLookup { String... suffix) { String string = "/block"; for (String suf : suffix) - string += "_" + suf; + if (!suf.isEmpty()) + string += "_" + suf; final String location = "block/" + ctx.getName() + string; return prov.models() .getExistingFile(prov.modLoc(location)); diff --git a/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java b/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java index e29e0dbeba..7aa8238027 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java @@ -25,13 +25,13 @@ import com.simibubi.create.content.fluids.pipes.EncasedPipeBlock; import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pointing; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; import com.tterrag.registrate.util.nullness.NonNullBiConsumer; import com.tterrag.registrate.util.nullness.NonnullType; +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.Pointing; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; @@ -77,7 +77,7 @@ public class BlockStateGen { boolean customItem) { return (c, p) -> horizontalAxisBlock(c, p, getBlockModel(customItem, c, p)); } - + public static NonNullBiConsumer, RegistrateBlockstateProvider> simpleCubeAll( String path) { return (c, p) -> p.simpleBlock(c.get(), p.models() diff --git a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java index 6edc369674..49809df8a6 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -1,7 +1,8 @@ package com.simibubi.create.foundation.data; -import static com.simibubi.create.AllInteractionBehaviours.interactionBehaviour; -import static com.simibubi.create.AllMovementBehaviours.movementBehaviour; +import static com.simibubi.create.Create.REGISTRATE; +import static com.simibubi.create.api.behaviour.interaction.MovingInteractionBehaviour.interactionBehaviour; +import static com.simibubi.create.api.behaviour.movement.MovementBehaviour.movementBehaviour; import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock; import static com.simibubi.create.foundation.data.CreateRegistrate.casingConnectivity; import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; @@ -9,6 +10,7 @@ import static com.simibubi.create.foundation.data.TagGen.axeOrPickaxe; import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.function.Supplier; @@ -18,6 +20,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.Create; +import com.simibubi.create.api.stress.BlockStressValues; import com.simibubi.create.content.contraptions.behaviour.DoorMovingInteraction; import com.simibubi.create.content.contraptions.behaviour.TrapdoorMovingInteraction; import com.simibubi.create.content.contraptions.piston.MechanicalPistonGenerator; @@ -29,12 +32,16 @@ import com.simibubi.create.content.decoration.encasing.CasingBlock; import com.simibubi.create.content.decoration.encasing.EncasedCTBehaviour; import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorMovementBehaviour; -import com.simibubi.create.content.kinetics.BlockStressDefaults; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogCTBehaviour; import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogwheelBlock; import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedShaftBlock; +import com.simibubi.create.content.logistics.box.PackageItem; +import com.simibubi.create.content.logistics.box.PackageStyles.PackageStyle; +import com.simibubi.create.content.logistics.packager.PackagerGenerator; +import com.simibubi.create.content.logistics.tableCloth.TableClothBlockItem; +import com.simibubi.create.content.logistics.tableCloth.TableClothModel; import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock.Shape; import com.simibubi.create.content.logistics.tunnel.BeltTunnelItem; @@ -43,18 +50,26 @@ import com.simibubi.create.content.trains.bogey.StandardBogeyBlock; import com.simibubi.create.foundation.block.ItemUseOverrides; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.simibubi.create.foundation.item.ItemDescription; +import com.simibubi.create.infrastructure.config.CStress; import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.builders.ItemBuilder; +import com.tterrag.registrate.providers.RegistrateRecipeProvider; import com.tterrag.registrate.util.DataIngredient; +import com.tterrag.registrate.util.nullness.NonNullSupplier; import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.core.registries.Registries; import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.data.recipes.ShapelessRecipeBuilder; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; import net.minecraft.tags.ItemTags; +import net.minecraft.tags.TagKey; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Rarity; import net.minecraft.world.level.ItemLike; @@ -70,14 +85,15 @@ import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.LootTable.Builder; import net.minecraft.world.level.storage.loot.entries.LootItem; -import net.minecraft.world.level.storage.loot.functions.CopyNameFunction; import net.minecraft.world.level.storage.loot.functions.CopyNbtFunction; import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; + import net.minecraftforge.client.model.generators.ConfiguredModel; import net.minecraftforge.client.model.generators.ModelFile; +import net.minecraftforge.common.Tags; public class BuilderTransformers { @@ -94,7 +110,6 @@ public class BuilderTransformers { .build(); } - @SuppressWarnings("deprecation") public static NonNullUnaryOperator> bogey() { return b -> b.initialProperties(SharedProperties::softMetal) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) @@ -103,7 +118,8 @@ public class BuilderTransformers { .blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models() .getExistingFile(p.modLoc("block/track/bogey/top")))) .loot((p, l) -> p.dropOther(l, AllBlocks.RAILWAY_CASING.get())) - .onRegister(block -> AbstractBogeyBlock.registerStandardBogey(RegisteredObjects.getKeyOrThrow(block))); + .onRegister( + block -> AbstractBogeyBlock.registerStandardBogey(CatnipServices.REGISTRIES.getKeyOrThrow(block))); } public static NonNullUnaryOperator> copycat() { @@ -211,7 +227,7 @@ public class BuilderTransformers { Supplier drop) { return b.initialProperties(SharedProperties::stone) .properties(BlockBehaviour.Properties::noOcclusion) - .transform(BlockStressDefaults.setNoImpact()) + .transform(CStress.setNoImpact()) .loot((p, lb) -> p.dropOther(lb, drop.get())); } @@ -220,7 +236,7 @@ public class BuilderTransformers { .blockstate((c, p) -> p.horizontalBlock(c.get(), p.models() .getExistingFile(p.modLoc("block/cuckoo_clock/block")))) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setImpact(1.0)) + .transform(CStress.setImpact(1)) .item() .transform(ModelGen.customItemModel("cuckoo_clock", "item")); } @@ -284,7 +300,7 @@ public class BuilderTransformers { .texture("3", p.modLoc("block/valve_handle/valve_handle_" + variant))); }) .tag(AllBlockTags.BRITTLE.tag, AllBlockTags.VALVE_HANDLES.tag) - .transform(BlockStressDefaults.setGeneratorSpeed(ValveHandleBlock::getSpeedRange)) + .onRegister(BlockStressValues.setGeneratorSpeed(32)) .onRegister(ItemUseOverrides::addBlock) .item() .tag(AllItemTags.VALVE_HANDLES.tag) @@ -365,7 +381,7 @@ public class BuilderTransformers { .properties(p -> p.noOcclusion()) .blockstate(new MechanicalPistonGenerator(type)::generate) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .item() .transform(ModelGen.customItemModel("mechanical_piston", type.getSerializedName(), "item")); } @@ -426,7 +442,7 @@ public class BuilderTransformers { return b -> b.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .transform(pickaxeOnly()) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setImpact(4.0)) + .transform(CStress.setImpact(4.0)) .loot((lt, block) -> { Builder builder = LootTable.lootTable(); LootItemCondition.Builder survivesExplosion = ExplosionCondition.survivesExplosion(); @@ -460,4 +476,82 @@ public class BuilderTransformers { .build(); } + public static ItemBuilder packageItem(PackageStyle style) { + String size = "_" + style.width() + "x" + style.height(); + return REGISTRATE.item(style.getItemId() + .getPath(), p -> new PackageItem(p, style)) + .properties(p -> p.stacksTo(1)) + .tag(AllItemTags.PACKAGES.tag) + .model((c, p) -> { + if (style.rare()) + p.withExistingParent(c.getName(), p.modLoc("item/package/custom" + size)) + .texture("2", p.modLoc("item/package/" + style.type())); + else + p.withExistingParent(c.getName(), p.modLoc("item/package/" + style.type() + size)); + }) + .lang((style.rare() ? "Rare" + : style.type() + .substring(0, 1) + .toUpperCase(Locale.ROOT) + + style.type() + .substring(1)) + + " Package"); + } + + public static NonNullUnaryOperator> tableCloth(String name, + NonNullSupplier initialProps, boolean dyed) { + return b -> { + TagKey soundTag = dyed ? BlockTags.COMBINATION_STEP_SOUND_BLOCKS : BlockTags.INSIDE_STEP_SOUND_BLOCKS; + + ItemBuilder> item = b.initialProperties(initialProps) + .addLayer(() -> RenderType::cutoutMipped) + .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() + .withExistingParent(name + "_table_cloth", p.modLoc("block/table_cloth/block")) + .texture("0", p.modLoc("block/table_cloth/" + name)))) + .onRegister(CreateRegistrate.blockModel(() -> TableClothModel::new)) + .tag(AllBlockTags.TABLE_CLOTHS.tag, soundTag) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "block.create.table_cloth")) + .item(TableClothBlockItem::new); + + if (dyed) + item.tag(AllItemTags.DYED_TABLE_CLOTHS.tag); + + return item.model((c, p) -> p.withExistingParent(name + "_table_cloth", p.modLoc("block/table_cloth/item")) + .texture("0", p.modLoc("block/table_cloth/" + name))) + .tag(AllItemTags.TABLE_CLOTHS.tag) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get()) + .requires(c.get()) + .unlockedBy("has_" + c.getName(), RegistrateRecipeProvider.has(c.get())) + .save(p, Create.asResource("crafting/logistics/" + c.getName() + "_clear"))) + .build(); + }; + } + + public static NonNullUnaryOperator> packager() { + return b -> b.initialProperties(SharedProperties::softMetal) + .properties(p -> p.noOcclusion()) + .properties(p -> p.isRedstoneConductor(($1, $2, $3) -> false)) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE) + .sound(SoundType.NETHERITE_BLOCK)) + .transform(pickaxeOnly()) + .addLayer(() -> RenderType::cutoutMipped) + .blockstate(new PackagerGenerator()::generate) + .item() + .model(AssetLookup::customItemModel) + .build(); + } + + public static NonNullUnaryOperator> palettesIronBlock() { + return b -> b.initialProperties(SharedProperties::softMetal) + .properties(p -> p.mapColor(MapColor.COLOR_GRAY) + .sound(SoundType.NETHERITE_BLOCK) + .requiresCorrectToolForDrops()) + .transform(pickaxeOnly()) + .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() + .cubeColumn(c.getName(), p.modLoc("block/" + c.getName()), p.modLoc("block/" + c.getName() + "_top")))) + .tag(AllBlockTags.WRENCH_PICKUP.tag) + .recipe((c, p) -> p.stonecutting(DataIngredient.tag(Tags.Items.INGOTS_IRON), RecipeCategory.BUILDING_BLOCKS, + c::get, 2)) + .simpleItem(); + } } diff --git a/src/main/java/com/simibubi/create/foundation/data/ChainedDataProvider.java b/src/main/java/com/simibubi/create/foundation/data/ChainedDataProvider.java deleted file mode 100644 index 20275af25a..0000000000 --- a/src/main/java/com/simibubi/create/foundation/data/ChainedDataProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.foundation.data; - -import java.util.concurrent.CompletableFuture; - -import net.minecraft.data.CachedOutput; -import net.minecraft.data.DataProvider; - -@Deprecated(forRemoval = true) -public class ChainedDataProvider implements DataProvider { - - private DataProvider mainProvider; - private DataProvider addedProvider; - - public ChainedDataProvider(DataProvider mainProvider, DataProvider addedProvider) { - this.mainProvider = mainProvider; - this.addedProvider = addedProvider; - } - - @Override - public CompletableFuture run(CachedOutput pOutput) { - return mainProvider.run(pOutput) - .thenCompose(s -> addedProvider.run(pOutput)); - } - - @Override - public String getName() { - return mainProvider.getName() + " with " + addedProvider.getName(); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateBlockEntityBuilder.java b/src/main/java/com/simibubi/create/foundation/data/CreateBlockEntityBuilder.java index 8f61275bdc..32d9859ff7 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateBlockEntityBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateBlockEntityBuilder.java @@ -6,17 +6,21 @@ import java.util.function.Supplier; import javax.annotation.Nullable; -import com.simibubi.create.Create; +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplayTarget; +import com.simibubi.create.api.registry.CreateRegistries; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BlockEntityBuilder; import com.tterrag.registrate.builders.BuilderCallback; import com.tterrag.registrate.util.OneTimeEventReceiver; +import com.tterrag.registrate.util.entry.RegistryEntry; import com.tterrag.registrate.util.nullness.NonNullSupplier; import dev.engine_room.flywheel.lib.visualization.SimpleBlockEntityVisualizer; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.util.NonNullPredicate; import net.minecraftforge.fml.DistExecutor; @@ -32,12 +36,12 @@ public class CreateBlockEntityBuilder extends BlockEnt new ArrayList<>(); public static BlockEntityBuilder create(AbstractRegistrate owner, P parent, - String name, BuilderCallback callback, BlockEntityFactory factory) { + String name, BuilderCallback callback, BlockEntityFactory factory) { return new CreateBlockEntityBuilder<>(owner, parent, name, callback, factory); } protected CreateBlockEntityBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, - BlockEntityFactory factory) { + BlockEntityFactory factory) { super(owner, parent, name, callback, factory); } @@ -56,6 +60,22 @@ public class CreateBlockEntityBuilder extends BlockEnt return super.createEntry(); } + public CreateBlockEntityBuilder displaySource(RegistryEntry source) { + this.onRegisterAfter( + CreateRegistries.DISPLAY_SOURCE, + type -> DisplaySource.BY_BLOCK_ENTITY.add(type, source.get()) + ); + return this; + } + + public CreateBlockEntityBuilder displayTarget(RegistryEntry target) { + this.onRegisterAfter( + CreateRegistries.DISPLAY_TARGET, + type -> DisplayTarget.BY_BLOCK_ENTITY.register(type, target.get()) + ); + return this; + } + public CreateBlockEntityBuilder visual( NonNullSupplier> visualFactory) { return visual(visualFactory, true); @@ -81,7 +101,7 @@ public class CreateBlockEntityBuilder extends BlockEnt } protected void registerVisualizer() { - OneTimeEventReceiver.addModListener(Create.REGISTRATE, FMLClientSetupEvent.class, $ -> { + OneTimeEventReceiver.addModListener(getOwner(), FMLClientSetupEvent.class, $ -> { var visualFactory = this.visualFactory; if (visualFactory != null) { NonNullPredicate renderNormally = this.renderNormally; diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java b/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java index 944508939c..38a39b3217 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java @@ -3,7 +3,6 @@ package com.simibubi.create.foundation.data; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import com.simibubi.create.Create; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BuilderCallback; import com.tterrag.registrate.builders.EntityBuilder; @@ -14,6 +13,7 @@ import dev.engine_room.flywheel.lib.visualization.SimpleEntityVisualizer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.util.NonNullPredicate; import net.minecraftforge.fml.DistExecutor; @@ -54,7 +54,7 @@ public class CreateEntityBuilder extends EntityBuilder { + OneTimeEventReceiver.addModListener(getOwner(), FMLClientSetupEvent.class, $ -> { var visualFactory = this.visualFactory; if (visualFactory != null) { NonNullPredicate renderNormally = this.renderNormally; diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java index 349d60918b..b15dfa53a6 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java @@ -13,12 +13,17 @@ import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; import com.simibubi.create.CreateClient; +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.api.behaviour.display.DisplayTarget; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.registry.CreateRegistries; +import com.simibubi.create.api.registry.registrate.SimpleBuilder; import com.simibubi.create.content.decoration.encasing.CasingConnectivity; import com.simibubi.create.content.fluids.VirtualFluid; import com.simibubi.create.foundation.block.connected.CTModel; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; import com.simibubi.create.foundation.item.TooltipModifier; -import com.simibubi.create.foundation.utility.RegisteredObjects; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.BlockEntityBuilder.BlockEntityFactory; @@ -29,6 +34,7 @@ import com.tterrag.registrate.util.nullness.NonNullConsumer; import com.tterrag.registrate.util.nullness.NonNullFunction; import com.tterrag.registrate.util.nullness.NonNullSupplier; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; @@ -43,6 +49,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockBehaviour.Properties; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; @@ -99,13 +106,16 @@ public class CreateRegistrate extends AbstractRegistrate { @Override protected RegistryEntry accept(String name, ResourceKey> type, - Builder builder, NonNullSupplier creator, - NonNullFunction, ? extends RegistryEntry> entryFactory) { + Builder builder, NonNullSupplier creator, + NonNullFunction, ? extends RegistryEntry> entryFactory) { RegistryEntry entry = super.accept(name, type, builder, creator, entryFactory); - if (type.equals(Registries.ITEM)) { - if (currentTooltipModifierFactory != null) { - TooltipModifier.REGISTRY.registerDeferred(entry.getId(), currentTooltipModifierFactory); - } + if (type.equals(Registries.ITEM) && currentTooltipModifierFactory != null) { + // grab the factory here for the lambda, it can change between now and registration + Function factory = currentTooltipModifierFactory; + this.addRegisterCallback(name, Registries.ITEM, item -> { + TooltipModifier modifier = factory.apply(item); + TooltipModifier.REGISTRY.register(item, modifier); + }); } if (currentTab != null) { TAB_LOOKUP.put(entry, currentTab); @@ -115,36 +125,62 @@ public class CreateRegistrate extends AbstractRegistrate { @Override public CreateBlockEntityBuilder blockEntity(String name, - BlockEntityFactory factory) { + BlockEntityFactory factory) { return blockEntity(self(), name, factory); } @Override public CreateBlockEntityBuilder blockEntity(P parent, String name, - BlockEntityFactory factory) { + BlockEntityFactory factory) { return (CreateBlockEntityBuilder) entry(name, (callback) -> CreateBlockEntityBuilder.create(this, parent, name, callback, factory)); } @Override public CreateEntityBuilder entity(String name, - EntityType.EntityFactory factory, MobCategory classification) { + EntityType.EntityFactory factory, MobCategory classification) { return this.entity(self(), name, factory, classification); } @Override public CreateEntityBuilder entity(P parent, String name, - EntityType.EntityFactory factory, MobCategory classification) { + EntityType.EntityFactory factory, MobCategory classification) { return (CreateEntityBuilder) this.entry(name, (callback) -> { return CreateEntityBuilder.create(this, parent, name, callback, factory, classification); }); } + // custom types + + public > SimpleBuilder, T, CreateRegistrate> mountedItemStorage(String name, Supplier supplier) { + return this.entry(name, callback -> new SimpleBuilder<>( + this, this, name, callback, CreateRegistries.MOUNTED_ITEM_STORAGE_TYPE, supplier + ).byBlock(MountedItemStorageType.REGISTRY)); + } + + public > SimpleBuilder, T, CreateRegistrate> mountedFluidStorage(String name, Supplier supplier) { + return this.entry(name, callback -> new SimpleBuilder<>( + this, this, name, callback, CreateRegistries.MOUNTED_FLUID_STORAGE_TYPE, supplier + ).byBlock(MountedFluidStorageType.REGISTRY)); + } + + public SimpleBuilder displaySource(String name, Supplier supplier) { + return this.entry(name, callback -> new SimpleBuilder<>( + this, this, name, callback, CreateRegistries.DISPLAY_SOURCE, supplier + ).byBlock(DisplaySource.BY_BLOCK).byBlockEntity(DisplaySource.BY_BLOCK_ENTITY)); + } + + public SimpleBuilder displayTarget(String name, Supplier supplier) { + return this.entry(name, callback -> new SimpleBuilder<>( + this, this, name, callback, CreateRegistries.DISPLAY_TARGET, supplier + ).byBlock(DisplayTarget.BY_BLOCK).byBlockEntity(DisplayTarget.BY_BLOCK_ENTITY)); + } + /* Palettes */ public BlockBuilder paletteStoneBlock(String name, - NonNullFunction factory, NonNullSupplier propertiesFrom, boolean worldGenStone, - boolean hasNaturalVariants) { + NonNullFunction factory, NonNullSupplier propertiesFrom, boolean worldGenStone, + boolean hasNaturalVariants) { BlockBuilder builder = super.block(name, factory).initialProperties(propertiesFrom) .transform(pickaxeOnly()) .blockstate(hasNaturalVariants ? BlockStateGen.naturalStoneTypeBlock(name) : (c, p) -> { @@ -165,35 +201,35 @@ public class CreateRegistrate extends AbstractRegistrate { } public BlockBuilder paletteStoneBlock(String name, NonNullSupplier propertiesFrom, - boolean worldGenStone, boolean hasNaturalVariants) { + boolean worldGenStone, boolean hasNaturalVariants) { return paletteStoneBlock(name, Block::new, propertiesFrom, worldGenStone, hasNaturalVariants); } /* Fluids */ public FluidBuilder virtualFluid(String name, - FluidBuilder.FluidTypeFactory typeFactory, NonNullFunction sourceFactory, - NonNullFunction flowingFactory) { + FluidBuilder.FluidTypeFactory typeFactory, NonNullFunction sourceFactory, + NonNullFunction flowingFactory) { return entry(name, c -> new VirtualFluidBuilder<>(self(), self(), name, c, new ResourceLocation(getModid(), "fluid/" + name + "_still"), new ResourceLocation(getModid(), "fluid/" + name + "_flow"), typeFactory, sourceFactory, flowingFactory)); } public FluidBuilder virtualFluid(String name, - ResourceLocation still, ResourceLocation flow, FluidBuilder.FluidTypeFactory typeFactory, - NonNullFunction sourceFactory, NonNullFunction flowingFactory) { + ResourceLocation still, ResourceLocation flow, FluidBuilder.FluidTypeFactory typeFactory, + NonNullFunction sourceFactory, NonNullFunction flowingFactory) { return entry(name, c -> new VirtualFluidBuilder<>(self(), self(), name, c, still, flow, typeFactory, sourceFactory, flowingFactory)); } public FluidBuilder virtualFluid(String name) { return entry(name, - c -> new VirtualFluidBuilder(self(), self(), name, c, + c -> new VirtualFluidBuilder<>(self(), self(), name, c, new ResourceLocation(getModid(), "fluid/" + name + "_still"), new ResourceLocation(getModid(), "fluid/" + name + "_flow"), CreateRegistrate::defaultFluidType, VirtualFluid::createSource, VirtualFluid::createFlowing)); } public FluidBuilder virtualFluid(String name, ResourceLocation still, - ResourceLocation flow) { + ResourceLocation flow) { return entry(name, c -> new VirtualFluidBuilder<>(self(), self(), name, c, still, flow, CreateRegistrate::defaultFluidType, VirtualFluid::createSource, VirtualFluid::createFlowing)); } @@ -203,13 +239,13 @@ public class CreateRegistrate extends AbstractRegistrate { } public FluidBuilder standardFluid(String name, - FluidBuilder.FluidTypeFactory typeFactory) { + FluidBuilder.FluidTypeFactory typeFactory) { return fluid(name, new ResourceLocation(getModid(), "fluid/" + name + "_still"), new ResourceLocation(getModid(), "fluid/" + name + "_flow"), typeFactory); } public static FluidType defaultFluidType(FluidType.Properties properties, ResourceLocation stillTexture, - ResourceLocation flowingTexture) { + ResourceLocation flowingTexture) { return new FluidType(properties) { @Override public void initializeClient(Consumer consumer) { @@ -256,28 +292,28 @@ public class CreateRegistrate extends AbstractRegistrate { @OnlyIn(Dist.CLIENT) private static void registerCasingConnectivity(T entry, - BiConsumer consumer) { + BiConsumer consumer) { consumer.accept(entry, CreateClient.CASING_CONNECTIVITY); } @OnlyIn(Dist.CLIENT) private static void registerBlockModel(Block entry, - Supplier> func) { + Supplier> func) { CreateClient.MODEL_SWAPPER.getCustomBlockModels() - .register(RegisteredObjects.getKeyOrThrow(entry), func.get()); + .register(CatnipServices.REGISTRIES.getKeyOrThrow(entry), func.get()); } @OnlyIn(Dist.CLIENT) private static void registerItemModel(Item entry, - Supplier> func) { + Supplier> func) { CreateClient.MODEL_SWAPPER.getCustomItemModels() - .register(RegisteredObjects.getKeyOrThrow(entry), func.get()); + .register(CatnipServices.REGISTRIES.getKeyOrThrow(entry), func.get()); } @OnlyIn(Dist.CLIENT) private static void registerCTBehviour(Block entry, Supplier behaviorSupplier) { ConnectedTextureBehaviour behavior = behaviorSupplier.get(); CreateClient.MODEL_SWAPPER.getCustomBlockModels() - .register(RegisteredObjects.getKeyOrThrow(entry), model -> new CTModel(model, behavior)); + .register(CatnipServices.REGISTRIES.getKeyOrThrow(entry), model -> new CTModel(model, behavior)); } } diff --git a/src/main/java/com/simibubi/create/foundation/data/LangEntry.java b/src/main/java/com/simibubi/create/foundation/data/LangEntry.java deleted file mode 100644 index 83b2cb4c01..0000000000 --- a/src/main/java/com/simibubi/create/foundation/data/LangEntry.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.simibubi.create.foundation.data; - -import com.tterrag.registrate.AbstractRegistrate; -import com.tterrag.registrate.providers.ProviderType; - -/** - * @deprecated Use {@link AbstractRegistrate#addRawLang} or {@link AbstractRegistrate#addDataGenerator} with {@link ProviderType#LANG} instead. - */ -public class LangEntry { - static final String ENTRY_FORMAT = "\t\"%s\": %s,\n"; - - private String key; - private String value; - - LangEntry(String key, String value) { - this.key = key; - this.value = value; - } - - @Override - public String toString() { - return String.format(ENTRY_FORMAT, key, LangMerger.GSON.toJson(value, String.class)); - } - -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/foundation/data/LangMerger.java b/src/main/java/com/simibubi/create/foundation/data/LangMerger.java deleted file mode 100644 index 8cdb56bb06..0000000000 --- a/src/main/java/com/simibubi/create/foundation/data/LangMerger.java +++ /dev/null @@ -1,222 +0,0 @@ -package com.simibubi.create.foundation.data; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -import org.apache.commons.lang3.mutable.MutableBoolean; -import org.apache.commons.lang3.mutable.MutableObject; - -import com.google.common.hash.HashCode; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonObject; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.ponder.PonderScene; -import com.tterrag.registrate.AbstractRegistrate; -import com.tterrag.registrate.providers.ProviderType; - -import net.minecraft.Util; -import net.minecraft.data.CachedOutput; -import net.minecraft.data.DataProvider; -import net.minecraft.data.PackOutput; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.GsonHelper; - -/** - * @deprecated Use {@link AbstractRegistrate#addRawLang} or {@link AbstractRegistrate#addDataGenerator} with {@link ProviderType#LANG} instead. - */ -@Deprecated(forRemoval = true) -public class LangMerger implements DataProvider { - - static final Gson GSON = new GsonBuilder().setPrettyPrinting() - .disableHtmlEscaping() - .create(); - private static final String CATEGORY_HEADER = - "\t\"_\": \"->------------------------] %s [------------------------<-\","; - - private final String modid; - private final String displayName; - private final LangPartial[] langPartials; - - private List mergedLangData; - private List langIgnore; - private PackOutput output; - - public LangMerger(PackOutput output, String modid, String displayName, - T[] allLangPartials) { - this.output = output; - this.modid = modid; - this.displayName = displayName; - this.langPartials = allLangPartials; - this.mergedLangData = new ArrayList<>(); - this.langIgnore = new ArrayList<>(); - populateLangIgnore(); - } - - protected void populateLangIgnore() { - // Key prefixes added here will NOT be transferred to lang templates - langIgnore.add("create.ponder.debug_"); // Ponder debug scene text - langIgnore.add("create.gui.chromatic_projector"); - } - - private boolean shouldIgnore(String key) { - for (String string : langIgnore) - if (key.startsWith(string)) - return true; - return false; - } - - @Override - public String getName() { - return displayName + "'s lang merger"; - } - - @Override - public CompletableFuture run(CachedOutput pOutput) { - Path path = output.createPathProvider(PackOutput.Target.RESOURCE_PACK, "lang") - .json(new ResourceLocation(modid, "en_us")); - - return CompletableFuture.runAsync(() -> { - try { - collectExistingEntries(path); - collectEntries(); - if (mergedLangData.isEmpty()) - return; - save(pOutput, mergedLangData, path, - "Merging en_us.json with hand-written lang entries..."); - - } catch (IOException ioexception) { - LOGGER.error("Failed to run LangMerger", ioexception); - } - - }, Util.backgroundExecutor()); - } - - private void collectExistingEntries(Path path) throws IOException { - if (!Files.exists(path)) { - Create.LOGGER.warn("Nothing to merge! It appears no lang was generated before me."); - return; - } - - try (BufferedReader reader = Files.newBufferedReader(path)) { - JsonObject jsonobject = GsonHelper.fromJson(GSON, reader, JsonObject.class); - - /* - * Erase additional sections from previous lang in case registrate did not - * create a new one (this assumes advancements to be the first section after - * game elements) - */ - Set keysToRemove = new HashSet<>(); - MutableBoolean startErasing = new MutableBoolean(); - jsonobject.entrySet() - .stream() - .forEachOrdered(entry -> { - String key = entry.getKey(); - if (key.startsWith("advancement")) - startErasing.setTrue(); - if (startErasing.isFalse()) - return; - keysToRemove.add(key); - }); - jsonobject.remove("_"); - keysToRemove.forEach(jsonobject::remove); - - addAll("Game Elements", jsonobject); - reader.close(); - } - } - - protected void addAll(String header, JsonObject jsonobject) { - if (jsonobject == null) - return; - header = String.format(CATEGORY_HEADER, header); - - writeData("\n"); - writeData(header); - writeData("\n\n"); - - MutableObject previousKey = new MutableObject<>(""); - jsonobject.entrySet() - .stream() - .forEachOrdered(entry -> { - String key = entry.getKey(); - if (shouldIgnore(key)) - return; - String value = entry.getValue() - .getAsString(); - if (!previousKey.getValue() - .isEmpty() && shouldAddLineBreak(key, previousKey.getValue())) - writeData("\n"); - writeEntry(key, value); - previousKey.setValue(key); - }); - - writeData("\n"); - } - - private void writeData(String data) { - mergedLangData.add(data); - } - - private void writeEntry(String key, String value) { - mergedLangData.add(new LangEntry(key, value)); - } - - protected boolean shouldAddLineBreak(String key, String previousKey) { - // Always put tooltips and ponder scenes in their own paragraphs - if (key.endsWith(".tooltip")) - return true; - if (key.startsWith(modid + ".ponder") && key.endsWith(PonderScene.TITLE_KEY)) - return true; - - key = key.replaceFirst("\\.", ""); - previousKey = previousKey.replaceFirst("\\.", ""); - - String[] split = key.split("\\."); - String[] split2 = previousKey.split("\\."); - if (split.length == 0 || split2.length == 0) - return false; - - // Start new paragraph if keys before second point do not match - return !split[0].equals(split2[0]); - } - - private void collectEntries() { - for (LangPartial partial : langPartials) - addAll(partial.getDisplayName(), partial.provide() - .getAsJsonObject()); - } - - private void save(CachedOutput cache, List dataIn, Path target, String message) throws IOException { - ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); - Writer writer = new OutputStreamWriter(bytearrayoutputstream, StandardCharsets.UTF_8); - writer.append(createString(dataIn)); - writer.close(); - - CachedOutput.NO_CACHE.writeIfNeeded(target, bytearrayoutputstream.toByteArray(), HashCode.fromInt(0)); - Create.LOGGER.info(message); - } - - protected String createString(List data) { - StringBuilder builder = new StringBuilder(); - builder.append("{\n"); - data.forEach(builder::append); - builder.append("\t\"_\": \"Thank you for translating ") - .append(displayName) - .append("!\"\n\n"); - builder.append("}"); - return builder.toString(); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/data/LangPartial.java b/src/main/java/com/simibubi/create/foundation/data/LangPartial.java deleted file mode 100644 index 303e0f6d79..0000000000 --- a/src/main/java/com/simibubi/create/foundation/data/LangPartial.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.simibubi.create.foundation.data; - -import com.google.gson.JsonElement; -import com.simibubi.create.foundation.utility.FilesHelper; -import com.tterrag.registrate.AbstractRegistrate; -import com.tterrag.registrate.providers.ProviderType; - -/** - * @deprecated Use {@link AbstractRegistrate#addRawLang} or {@link AbstractRegistrate#addDataGenerator} with {@link ProviderType#LANG} instead. - */ -@Deprecated(forRemoval = true) -public interface LangPartial { - String getDisplayName(); - - JsonElement provide(); - - static JsonElement fromResource(String namespace, String fileName) { - String path = "assets/" + namespace + "/lang/default/" + fileName + ".json"; - JsonElement element = FilesHelper.loadJsonResource(path); - if (element == null) - throw new IllegalStateException(String.format("Could not find default lang file: %s", path)); - return element; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/data/MetalBarsGen.java b/src/main/java/com/simibubi/create/foundation/data/MetalBarsGen.java index 3dc5b325d6..e5128ccc55 100644 --- a/src/main/java/com/simibubi/create/foundation/data/MetalBarsGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/MetalBarsGen.java @@ -9,7 +9,6 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert import java.util.function.Supplier; import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.Create; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; import com.tterrag.registrate.util.DataIngredient; @@ -24,6 +23,7 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.IronBarsBlock; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.material.MapColor; + import net.minecraftforge.client.model.generators.ModelFile; public class MetalBarsGen { @@ -112,7 +112,7 @@ public class MetalBarsGen { } private static ModelFile barsSubModel(RegistrateBlockstateProvider p, String name, String suffix, - boolean specialEdge) { + boolean specialEdge) { ResourceLocation barsTexture = p.modLoc("block/bars/" + name + "_bars"); ResourceLocation edgeTexture = specialEdge ? p.modLoc("block/bars/" + name + "_bars_edge") : barsTexture; return p.models() @@ -123,7 +123,7 @@ public class MetalBarsGen { } public static BlockEntry createBars(String name, boolean specialEdge, - Supplier ingredient, MapColor color) { + Supplier ingredient, MapColor color) { return REGISTRATE.block(name + "_bars", IronBarsBlock::new) .addLayer(() -> RenderType::cutoutMipped) .initialProperties(() -> Blocks.IRON_BARS) @@ -136,9 +136,7 @@ public class MetalBarsGen { .item() .model((c, p) -> { ResourceLocation barsTexture = p.modLoc("block/bars/" + name + "_bars"); - p.withExistingParent(c.getName(), Create.asResource("item/bars")) - .texture("bars", barsTexture) - .texture("edge", specialEdge ? p.modLoc("block/bars/" + name + "_bars_edge") : barsTexture); + p.generated(c, barsTexture); }) .recipe((c, p) -> p.stonecutting(ingredient.get(), RecipeCategory.DECORATIONS, c::get, 4)) .build() diff --git a/src/main/java/com/simibubi/create/foundation/data/RuntimeDataGenerator.java b/src/main/java/com/simibubi/create/foundation/data/RuntimeDataGenerator.java new file mode 100644 index 0000000000..20de67e4ac --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/RuntimeDataGenerator.java @@ -0,0 +1,156 @@ +package com.simibubi.create.foundation.data; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.jetbrains.annotations.ApiStatus; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import com.simibubi.create.Create; +import com.simibubi.create.content.kinetics.saw.CuttingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; +import com.simibubi.create.foundation.pack.DynamicPack; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagEntry; +import net.minecraft.tags.TagFile; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; + +@ApiStatus.Internal +public class RuntimeDataGenerator { + private static final Pattern STRIPPED_WOODS_REGEX = Pattern.compile("stripped_(\\w*)_(log|wood|stem|hyphae)"); + private static final Pattern NON_STRIPPED_WOODS_REGEX = Pattern.compile("(?!stripped_)([a-z]+)_(log|wood|stem|hyphae)"); + private static final Multimap TAGS = HashMultimap.create(); + private static final Object2ObjectOpenHashMap JSON_FILES = new Object2ObjectOpenHashMap<>(); + + public static void insertIntoPack(DynamicPack dynamicPack) { + for (ResourceLocation itemId : BuiltInRegistries.ITEM.keySet()) + cuttingRecipes(itemId); + + Create.LOGGER.info("Created {} recipes which will be injected into the game", JSON_FILES.size()); + JSON_FILES.forEach(dynamicPack::put); + + Create.LOGGER.info("Created {} tags which will be injected into the game", TAGS.size()); + for (Map.Entry> tags : TAGS.asMap().entrySet()) { + TagFile tagFile = new TagFile(new ArrayList<>(tags.getValue()), false); + dynamicPack.put(tags.getKey().withPrefix("tags/items/"), TagFile.CODEC.encodeStart(JsonOps.INSTANCE, tagFile).result().orElseThrow()); + } + + JSON_FILES.clear(); + JSON_FILES.trim(); + TAGS.clear(); + } + + // logs/woods -> stripped variants + // logs/woods both stripped and non stripped -> planks + // planks -> stairs, slabs, fences, fence gates, doors, trapdoors, pressure plates, buttons and signs + private static void cuttingRecipes(ResourceLocation itemId) { + String path = itemId.getPath(); + + Matcher match = STRIPPED_WOODS_REGEX.matcher(path); + boolean hasFoundMatch = match.find(); + + // Last ditch attempt. Try to find logs without stripped variants + boolean noStrippedVariant = false; + if (!hasFoundMatch && !BuiltInRegistries.ITEM.containsKey(itemId.withPrefix("stripped_"))) { + match = NON_STRIPPED_WOODS_REGEX.matcher(path); + hasFoundMatch = match.find(); + noStrippedVariant = true; + } + + if (hasFoundMatch) { + String type = match.group(2); + ResourceLocation matched = itemId.withPath(match.group(1)); + ResourceLocation base = matched.withSuffix("_"); + ResourceLocation nonStrippedId = base.withSuffix(type); + ResourceLocation planksId = base.withSuffix("planks"); + ResourceLocation stairsId = base.withSuffix("stairs"); + ResourceLocation slabId = base.withSuffix("slab"); + ResourceLocation fenceId = base.withSuffix("fence"); + ResourceLocation fenceGateId = base.withSuffix("fence_gate"); + ResourceLocation doorId = base.withSuffix("door"); + ResourceLocation trapdoorId = base.withSuffix("trapdoor"); + ResourceLocation pressurePlateId = base.withSuffix("pressure_plate"); + ResourceLocation buttonId = base.withSuffix("button"); + ResourceLocation signId = base.withSuffix("sign"); + + if (!noStrippedVariant) { + simpleWoodRecipe(nonStrippedId, itemId); + simpleWoodRecipe(itemId, planksId, 6); + } else if (BuiltInRegistries.ITEM.containsKey(planksId)) { + ResourceLocation tag = Create.asResource("runtime_generated/compat/" + itemId.getNamespace() + "/" + matched.getPath()); + insertIntoTag(tag, itemId); + insertIntoTag(tag, nonStrippedId); + + simpleWoodRecipe(TagKey.create(Registries.ITEM, tag), planksId, 6); + } + + if (!path.contains("_wood") && !path.contains("_hyphae") && BuiltInRegistries.ITEM.containsKey(planksId)) { + simpleWoodRecipe(planksId, stairsId); + simpleWoodRecipe(planksId, slabId, 2); + simpleWoodRecipe(planksId, fenceId); + simpleWoodRecipe(planksId, fenceGateId); + simpleWoodRecipe(planksId, doorId); + simpleWoodRecipe(planksId, trapdoorId); + simpleWoodRecipe(planksId, pressurePlateId); + simpleWoodRecipe(planksId, buttonId); + simpleWoodRecipe(planksId, signId); + } + } + } + + private static void insertIntoTag(ResourceLocation tag, ResourceLocation itemId) { + if (BuiltInRegistries.ITEM.containsKey(itemId)) + TAGS.put(tag, TagEntry.optionalElement(itemId)); + } + + private static void simpleWoodRecipe(ResourceLocation inputId, ResourceLocation outputId) { + simpleWoodRecipe(inputId, outputId, 1); + } + + private static void simpleWoodRecipe(ResourceLocation inputId, ResourceLocation outputId, int amount) { + if (BuiltInRegistries.ITEM.containsKey(outputId)) { + new Builder<>(inputId.getNamespace(), CuttingRecipe::new, inputId.getPath(), outputId.getPath()) + .require(BuiltInRegistries.ITEM.get(inputId)) + .output(BuiltInRegistries.ITEM.get(outputId), amount) + .duration(50) + .build(); + } + } + + private static void simpleWoodRecipe(TagKey inputTag, ResourceLocation outputId, int amount) { + if (BuiltInRegistries.ITEM.containsKey(outputId)) { + new Builder<>(inputTag.location().getNamespace(), CuttingRecipe::new, "tag_" + inputTag.location().getPath(), outputId.getPath()) + .require(inputTag) + .output(BuiltInRegistries.ITEM.get(outputId), amount) + .duration(50) + .build(); + } + } + + private static class Builder> extends ProcessingRecipeBuilder { + public Builder(String modid, ProcessingRecipeBuilder.ProcessingRecipeFactory factory, String from, String to) { + super(factory, Create.asResource("runtime_generated/compat/" + modid + "/" + from + "_to_" + to)); + } + + @Override + public T build() { + T t = super.build(); + DataGenResult result = new DataGenResult<>(t, Collections.emptyList()); + JSON_FILES.put(result.getId().withPrefix("recipes/"), result.serializeRecipe()); + return t; + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/data/TagGen.java b/src/main/java/com/simibubi/create/foundation/data/TagGen.java index 3b24b32d68..4cb1545e95 100644 --- a/src/main/java/com/simibubi/create/foundation/data/TagGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/TagGen.java @@ -1,5 +1,6 @@ package com.simibubi.create.foundation.data; +import java.util.List; import java.util.function.Function; import java.util.stream.Stream; @@ -21,8 +22,6 @@ import net.minecraft.tags.TagKey; import net.minecraft.world.item.BlockItem; import net.minecraft.world.level.block.Block; -import java.util.List; - public class TagGen { public static NonNullFunction, BlockBuilder> axeOrPickaxe() { return b -> b.tag(BlockTags.MINEABLE_WITH_AXE) diff --git a/src/main/java/com/simibubi/create/foundation/data/WindowGen.java b/src/main/java/com/simibubi/create/foundation/data/WindowGen.java index a51f5aef18..9a98bd6bd2 100644 --- a/src/main/java/com/simibubi/create/foundation/data/WindowGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/WindowGen.java @@ -16,6 +16,8 @@ import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; import com.simibubi.create.foundation.block.connected.GlassPaneCTBehaviour; import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour; +import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.builders.ItemBuilder; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; import com.tterrag.registrate.providers.RegistrateRecipeProvider; @@ -32,6 +34,7 @@ import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; @@ -40,6 +43,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour.Properties; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.WoodType; import net.minecraft.world.level.material.MapColor; +import net.minecraftforge.client.model.generators.ConfiguredModel; import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.common.Tags; @@ -65,12 +69,37 @@ public class WindowGen { return woodenWindowBlock(woodType, planksBlock, () -> RenderType::cutoutMipped, false); } + public static BlockBuilder randomisedWindowBlock(String name, + Supplier ingredient, Supplier> renderType, boolean translucent, + Supplier color) { + ResourceLocation end_texture = Create.asResource(palettesDir() + name + "_end"); + ResourceLocation side_texture = Create.asResource(palettesDir() + name); + Function ends = i -> Create.asResource(palettesDir() + name + "_" + i + "_end"); + return windowBlock(name, ingredient, null, renderType, translucent, n -> end_texture, n -> side_texture, color) + .blockstate((c, p) -> p.simpleBlock(c.get(), ConfiguredModel.builder() + .modelFile(p.models() + .cubeColumn(c.getName() + "_1", side_texture, ends.apply(1))) + .nextModel() + .modelFile(p.models() + .cubeColumn(c.getName() + "_2", side_texture, ends.apply(2))) + .nextModel() + .modelFile(p.models() + .cubeColumn(c.getName() + "_3", side_texture, ends.apply(3))) + .nextModel() + .modelFile(p.models() + .cubeColumn(c.getName() + "_4", side_texture, ends.apply(4))) + .build())) + .item() + .model((c, p) -> p.cubeColumn(c.getName(), side_texture, ends.apply(1))) + .build(); + } + public static BlockEntry customWindowBlock(String name, Supplier ingredient, Supplier ct, Supplier> renderType, boolean translucent, Supplier color) { NonNullFunction end_texture = n -> Create.asResource(palettesDir() + name + "_end"); NonNullFunction side_texture = n -> Create.asResource(palettesDir() + n); - return windowBlock(name, ingredient, ct, renderType, translucent, end_texture, side_texture, color); + return windowBlock(name, ingredient, ct, renderType, translucent, end_texture, side_texture, color).register(); } public static BlockEntry woodenWindowBlock(WoodType woodType, Block planksBlock, @@ -81,15 +110,17 @@ public class WindowGen { $ -> new ResourceLocation("block/" + woodName + "_planks"); NonNullFunction side_texture = n -> Create.asResource(palettesDir() + n); return windowBlock(name, () -> planksBlock, () -> AllSpriteShifts.getWoodenWindow(woodType), renderType, - translucent, end_texture, side_texture, planksBlock::defaultMapColor); + translucent, end_texture, side_texture, planksBlock::defaultMapColor).register(); } - public static BlockEntry windowBlock(String name, Supplier ingredient, - Supplier ct, Supplier> renderType, boolean translucent, + public static BlockBuilder windowBlock(String name, + Supplier ingredient, Supplier ct, + Supplier> renderType, boolean translucent, NonNullFunction endTexture, NonNullFunction sideTexture, Supplier color) { return REGISTRATE.block(name, p -> new WindowBlock(p, translucent)) - .onRegister(connectedTextures(() -> new HorizontalCTBehaviour(ct.get()))) + .onRegister(ct == null ? $ -> { + } : connectedTextures(() -> new HorizontalCTBehaviour(ct.get()))) .addLayer(renderType) .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, c.get(), 2) .pattern(" # ") @@ -105,8 +136,7 @@ public class WindowGen { .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() .cubeColumn(c.getName(), sideTexture.apply(c.getName()), endTexture.apply(c.getName())))) .tag(BlockTags.IMPERMEABLE) - .simpleItem() - .register(); + .simpleItem(); } public static BlockEntry framedGlass(String name, @@ -135,14 +165,16 @@ public class WindowGen { ResourceLocation itemSideTexture = Create.asResource(palettesDir() + name); ResourceLocation topTexture = Create.asResource(palettesDir() + "framed_glass_pane_top"); Supplier> renderType = () -> RenderType::cutoutMipped; - return connectedGlassPane(name, parent, ctshift, sideTexture, itemSideTexture, topTexture, renderType); + return connectedGlassPane(name, parent, ctshift, sideTexture, itemSideTexture, topTexture, renderType, true) + .register(); } - public static BlockEntry customWindowPane(String name, Supplier parent, - Supplier ctshift, Supplier> renderType) { + public static BlockBuilder customWindowPane(String name, + Supplier parent, Supplier ctshift, + Supplier> renderType) { ResourceLocation topTexture = Create.asResource(palettesDir() + name + "_pane_top"); ResourceLocation sideTexture = Create.asResource(palettesDir() + name); - return connectedGlassPane(name, parent, ctshift, sideTexture, sideTexture, topTexture, renderType); + return connectedGlassPane(name, parent, ctshift, sideTexture, sideTexture, topTexture, renderType, false); } public static BlockEntry woodenWindowPane(WoodType woodType, @@ -157,7 +189,7 @@ public class WindowGen { ResourceLocation topTexture = new ResourceLocation("block/" + woodName + "_planks"); ResourceLocation sideTexture = Create.asResource(palettesDir() + name); return connectedGlassPane(name, parent, () -> AllSpriteShifts.getWoodenWindow(woodType), sideTexture, - sideTexture, topTexture, renderType); + sideTexture, topTexture, renderType, false).register(); } public static BlockEntry standardGlassPane(String name, Supplier parent, @@ -165,14 +197,14 @@ public class WindowGen { NonNullBiConsumer, RegistrateBlockstateProvider> stateProvider = (c, p) -> p.paneBlock(c.get(), sideTexture, topTexture); return glassPane(name, parent, sideTexture, topTexture, GlassPaneBlock::new, renderType, $ -> { - }, stateProvider); + }, stateProvider, true).register(); } - private static BlockEntry connectedGlassPane(String name, Supplier parent, - Supplier ctshift, ResourceLocation sideTexture, ResourceLocation itemSideTexture, - ResourceLocation topTexture, Supplier> renderType) { - NonNullConsumer connectedTextures = - connectedTextures(() -> new GlassPaneCTBehaviour(ctshift.get())); + private static BlockBuilder connectedGlassPane(String name, + Supplier parent, Supplier ctshift, ResourceLocation sideTexture, + ResourceLocation itemSideTexture, ResourceLocation topTexture, Supplier> renderType, boolean colorless) { + NonNullConsumer connectedTextures = ctshift == null ? $ -> { + } : connectedTextures(() -> new GlassPaneCTBehaviour(ctshift.get())); String CGPparents = "block/connected_glass_pane/"; String prefix = name + "_pane_"; @@ -188,7 +220,7 @@ public class WindowGen { noSideAlt.apply(p)); return glassPane(name, parent, itemSideTexture, topTexture, ConnectedGlassPaneBlock::new, renderType, - connectedTextures, stateProvider); + connectedTextures, stateProvider, colorless); } private static Function getPaneModelProvider(String CGPparents, @@ -199,34 +231,50 @@ public class WindowGen { .texture("edge", topTexture); } - private static BlockEntry glassPane(String name, Supplier parent, - ResourceLocation sideTexture, ResourceLocation topTexture, NonNullFunction factory, - Supplier> renderType, NonNullConsumer connectedTextures, - NonNullBiConsumer, RegistrateBlockstateProvider> stateProvider) { + private static BlockBuilder glassPane(String name, + Supplier parent, ResourceLocation sideTexture, ResourceLocation topTexture, + NonNullFunction factory, Supplier> renderType, + NonNullConsumer connectedTextures, + NonNullBiConsumer, RegistrateBlockstateProvider> stateProvider, boolean colorless) { name += "_pane"; - - return REGISTRATE.block(name, factory) + + + ItemBuilder> itemBuilder = REGISTRATE.block(name, factory) .onRegister(connectedTextures) .addLayer(renderType) .initialProperties(() -> Blocks.GLASS_PANE) .properties(p -> p.mapColor(parent.get() .defaultMapColor())) .blockstate(stateProvider) - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, c.get(), 16) - .pattern("###") - .pattern("###") - .define('#', parent.get()) - .unlockedBy("has_ingredient", RegistrateRecipeProvider.has(parent.get())) - .save(p::accept)) - .tag(Tags.Blocks.GLASS_PANES) + .recipe((c, p) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, c.get(), 16) + .pattern("###") + .pattern("###") + .define('#', parent.get()) + .unlockedBy("has_ingredient", RegistrateRecipeProvider.has(parent.get())) + .save(p::accept); + if (colorless) + p.stonecutting(DataIngredient.tag(Tags.Items.GLASS_PANES_COLORLESS), RecipeCategory.BUILDING_BLOCKS, + c::get); + }) .loot((t, g) -> t.dropWhenSilkTouch(g)) - .item() - .tag(Tags.Items.GLASS_PANES) - .model((c, p) -> p.withExistingParent(c.getName(), Create.asResource("item/pane")) - .texture("pane", sideTexture) - .texture("edge", topTexture)) - .build() - .register(); + .item(); + + if (colorless) + itemBuilder.tag(Tags.Items.GLASS_PANES, Tags.Items.GLASS_PANES_COLORLESS); + else + itemBuilder.tag(Tags.Items.GLASS_PANES); + + BlockBuilder blockBuilder = itemBuilder + .model((c, p) -> p.generated(c, sideTexture)) + .build(); + + if (colorless) + blockBuilder.tag(Tags.Blocks.GLASS_PANES, Tags.Blocks.GLASS_PANES_COLORLESS); + else + blockBuilder.tag(Tags.Blocks.GLASS_PANES); + + return blockBuilder; } private static String palettesDir() { diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CompatMetals.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CompatMetals.java index bb1b7ea54e..7f2d27cc53 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CompatMetals.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CompatMetals.java @@ -8,7 +8,7 @@ import static com.simibubi.create.foundation.data.recipe.Mods.MEK; import static com.simibubi.create.foundation.data.recipe.Mods.OREGANIZED; import static com.simibubi.create.foundation.data.recipe.Mods.TH; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; public enum CompatMetals { ALUMINUM(IE, IC2), @@ -32,7 +32,7 @@ public enum CompatMetals { public String getName() { return name; } - + public String getName(Mods mod) { if (this == ALUMINUM && mod == IC2) // include in mods.builder if this happens again return "aluminium"; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java index d3bfc77368..cba414b013 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java @@ -91,6 +91,14 @@ public abstract class CreateRecipeProvider extends RecipeProvider { static ItemLike andesiteCasing() { return AllBlocks.ANDESITE_CASING.get(); } + + static ItemLike vault() { + return AllBlocks.ITEM_VAULT.get(); + } + + static ItemLike stockLink() { + return AllBlocks.STOCK_LINK.get(); + } static TagKey brass() { return AllTags.forgeItemTag("ingots/brass"); @@ -123,6 +131,10 @@ public abstract class CreateRecipeProvider extends RecipeProvider { static ItemLike brassCasing() { return AllBlocks.BRASS_CASING.get(); } + + static ItemLike cardboard() { + return AllItems.CARDBOARD.get(); + } static ItemLike railwayCasing() { return AllBlocks.RAILWAY_CASING.get(); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java index ff3a04de4a..dee08e788a 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java @@ -20,8 +20,8 @@ import com.simibubi.create.AllTags; import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes; import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; -import com.simibubi.create.foundation.utility.Lang; +import net.createmod.catnip.lang.Lang; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; @@ -402,7 +402,21 @@ public class CrushingRecipeGen extends ProcessingRecipeGen { .output(0.75f, Mods.AET, "ambrosium_shard", 1) .output(0.125f, Mods.AET, "holystone", 1) .output(0.75f, AllItems.EXP_NUGGET.get()) - .whenModLoaded(Mods.AET.getId())) + .whenModLoaded(Mods.AET.getId())), + + // IE + + IE_COKE_DUST = create(Mods.IE.recipeId("coal_coke"), b -> b.duration(200) + .require(Mods.IE, "coal_coke").output(Mods.IE, "dust_coke") + .whenModLoaded(Mods.IE.getId())), + + IE_COKE_BLOCK = create(Mods.IE.recipeId("coke_block"), b -> b.duration(200) + .require(Mods.IE, "coke").output(1, Mods.IE.asResource("dust_coke"), 9) + .whenModLoaded(Mods.IE.getId())), + + IE_SLAG_GRAVEL = create(Mods.IE.recipeId("slag"), b -> b.duration(200) + .require(Mods.IE, "slag").output(Mods.IE, "slag_gravel") + .whenModLoaded(Mods.IE.getId())); ; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java index 3d2cde96bd..d469f59474 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java @@ -1,47 +1,26 @@ package com.simibubi.create.foundation.data.recipe; +import java.util.Objects; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllTags; +import com.simibubi.create.foundation.data.recipe.CreateRecipeProvider.GeneratedRecipe; import net.minecraft.data.PackOutput; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import java.util.Objects; - @SuppressWarnings("unused") public class CuttingRecipeGen extends ProcessingRecipeGen { GeneratedRecipe - - ANDESITE_ALLOY = create(I::andesiteAlloy, b -> b.duration(200) - .output(AllBlocks.SHAFT.get(), 6)), + ANDESITE_ALLOY = create(I::andesiteAlloy, b -> b.duration(200) + .output(AllBlocks.SHAFT.get(), 6)), BAMBOO_PLANKS = create(() -> Blocks.BAMBOO_PLANKS, b -> b.duration(20) .output(Blocks.BAMBOO_MOSAIC, 1)), - - OAK_WOOD = stripAndMakePlanks(Blocks.OAK_WOOD, Blocks.STRIPPED_OAK_WOOD, Blocks.OAK_PLANKS), - SPRUCE_WOOD = stripAndMakePlanks(Blocks.SPRUCE_WOOD, Blocks.STRIPPED_SPRUCE_WOOD, Blocks.SPRUCE_PLANKS), - BIRCH_WOOD = stripAndMakePlanks(Blocks.BIRCH_WOOD, Blocks.STRIPPED_BIRCH_WOOD, Blocks.BIRCH_PLANKS), - JUNGLE_WOOD = stripAndMakePlanks(Blocks.JUNGLE_WOOD, Blocks.STRIPPED_JUNGLE_WOOD, Blocks.JUNGLE_PLANKS), - ACACIA_WOOD = stripAndMakePlanks(Blocks.ACACIA_WOOD, Blocks.STRIPPED_ACACIA_WOOD, Blocks.ACACIA_PLANKS), - CHERRY_WOOD = stripAndMakePlanks(Blocks.CHERRY_WOOD, Blocks.STRIPPED_CHERRY_WOOD, Blocks.CHERRY_PLANKS), - DARK_OAK_WOOD = stripAndMakePlanks(Blocks.DARK_OAK_WOOD, Blocks.STRIPPED_DARK_OAK_WOOD, Blocks.DARK_OAK_PLANKS), - MANGROVE_WOOD = stripAndMakePlanks(Blocks.MANGROVE_WOOD, Blocks.STRIPPED_MANGROVE_WOOD, Blocks.MANGROVE_PLANKS), - CRIMSON_WOOD = stripAndMakePlanks(Blocks.CRIMSON_HYPHAE, Blocks.STRIPPED_CRIMSON_HYPHAE, Blocks.CRIMSON_PLANKS), - WARPED_WOOD = stripAndMakePlanks(Blocks.WARPED_HYPHAE, Blocks.STRIPPED_WARPED_HYPHAE, Blocks.WARPED_PLANKS), - - OAK_LOG = stripAndMakePlanks(Blocks.OAK_LOG, Blocks.STRIPPED_OAK_LOG, Blocks.OAK_PLANKS), - SPRUCE_LOG = stripAndMakePlanks(Blocks.SPRUCE_LOG, Blocks.STRIPPED_SPRUCE_LOG, Blocks.SPRUCE_PLANKS), - BIRCH_LOG = stripAndMakePlanks(Blocks.BIRCH_LOG, Blocks.STRIPPED_BIRCH_LOG, Blocks.BIRCH_PLANKS), - JUNGLE_LOG = stripAndMakePlanks(Blocks.JUNGLE_LOG, Blocks.STRIPPED_JUNGLE_LOG, Blocks.JUNGLE_PLANKS), - ACACIA_LOG = stripAndMakePlanks(Blocks.ACACIA_LOG, Blocks.STRIPPED_ACACIA_LOG, Blocks.ACACIA_PLANKS), - CHERRY_LOG = stripAndMakePlanks(Blocks.CHERRY_LOG, Blocks.STRIPPED_CHERRY_LOG, Blocks.CHERRY_PLANKS), - DARK_OAK_LOG = stripAndMakePlanks(Blocks.DARK_OAK_LOG, Blocks.STRIPPED_DARK_OAK_LOG, Blocks.DARK_OAK_PLANKS), - MANGROVE_LOG = stripAndMakePlanks(Blocks.MANGROVE_LOG, Blocks.STRIPPED_MANGROVE_LOG, Blocks.MANGROVE_PLANKS), BAMBOO_BLOCK = stripAndMakePlanks(Blocks.BAMBOO_BLOCK, Blocks.STRIPPED_BAMBOO_BLOCK, Blocks.BAMBOO_PLANKS, 3), - CRIMSON_LOG = stripAndMakePlanks(Blocks.CRIMSON_STEM, Blocks.STRIPPED_CRIMSON_STEM, Blocks.CRIMSON_PLANKS), - WARPED_LOG = stripAndMakePlanks(Blocks.WARPED_STEM, Blocks.STRIPPED_WARPED_STEM, Blocks.WARPED_PLANKS), /* * Mod compat @@ -50,122 +29,12 @@ public class CuttingRecipeGen extends ProcessingRecipeGen { // Ars Nouveau (all logs yield the same plank) ARS_N = cuttingCompat(Mods.ARS_N, "blue_archwood", "purple_archwood", "green_archwood", "red_archwood"), - // Botania (stripped prefix is offset) - BTN = cuttingCompat(Mods.BTN, "livingwood", "dreamwood"), - BTN_2 = stripAndMakePlanks(Mods.BTN, "glimmering_livingwood_log", "glimmering_stripped_livingwood_log", - "livingwood_planks"), - BTN_3 = stripAndMakePlanks(Mods.BTN, "glimmering_livingwood", "glimmering_stripped_livingwood", - "livingwood_planks"), - BTN_4 = stripAndMakePlanks(Mods.BTN, "glimmering_dreamwood_log", "glimmering_stripped_dreamwood_log", - "dreamwood_planks"), - BTN_5 = - stripAndMakePlanks(Mods.BTN, "glimmering_dreamwood", "glimmering_stripped_dreamwood", "dreamwood_planks"), - - // Forbidden Arcanus - FA = cuttingCompat(Mods.FA, "aurum"), - - // Hexcasting (stripped is a suffix here) - HEX = cuttingCompat(Mods.HEX, "edified"), - - // Integrated Dynamics (stripped is a suffix here also) - ID = cuttingCompat(Mods.ID, "menril"), - - // Oh The Biomes You'll Go - BYG = - cuttingCompat(Mods.BYG, "aspen", "baobab", "blue_enchanted", "cika", "cypress", "ebony", "ether", - "fir", "green_enchanted", "holly", "jacaranda", "lament", "mahogany", "maple", "nightshade", - "palm", "pine", "rainbow_eucalyptus", "redwood", "skyris", "willow", "witch_hazel", "zelkova"), - BYG_2 = stripAndMakePlanks(Mods.BYG, "bulbis_stem", "stripped_bulbis_stem", "bulbis_planks"), - BYG_3 = stripAndMakePlanks(Mods.BYG, "bulbis_wood", "stripped_bulbis_wood", "bulbis_planks"), - BYG_4 = stripAndMakePlanks(Mods.BYG, null, "imparius_stem", "imparius_planks"), - BYG_5 = stripAndMakePlanks(Mods.BYG, null, "imparius_hyphae", "imparius_planks"), - BYG_6 = stripAndMakePlanks(Mods.BYG, null, "fungal_imparius_stem", "imparius_planks"), - BYG_7 = stripAndMakePlanks(Mods.BYG, null, "fungal_imparius_hyphae", "imparius_planks"), - BYG_8 = stripAndMakePlanks(Mods.BYG, "palo_verde_log", "stripped_palo_verde_log", null), - BYG_9 = stripAndMakePlanks(Mods.BYG, "palo_verde_wood", "stripped_palo_verde_wood", null), - - // Silent Gear - SG = cuttingCompat(Mods.SG, "netherwood"), - - // Twilight Forest - TF = cuttingCompat(Mods.TF, "twilight_oak", "canopy", "mangrove", "dark", "time", "transformation", "mining", - "sorting"), - - // Tinkers Construct - TIC = cuttingCompat(Mods.TIC, "greenheart", "skyroot", "bloodshroom"), - - // Architects palette - AP = cuttingCompat(Mods.AP, "twisted"), - - // Quark - Q = cuttingCompat(Mods.Q, "azalea", "blossom", "ancient"), - - // Ecologics - ECO = cuttingCompat(Mods.ECO, "coconut", "walnut", "azalea"), - ECO_2 = stripAndMakePlanks(Mods.ECO, "flowering_azalea_log", "stripped_azalea_log", null), - ECO_3 = stripAndMakePlanks(Mods.ECO, "flowering_azalea_wood", "stripped_azalea_wood", null), - - // Biomes O' Plenty - BOP = cuttingCompat(Mods.BOP, "fir", "redwood", "mahogany", "jacaranda", "palm", "willow", "dead", - "magic", "umbran", "hellbark"), - - // Blue Skies (crystallized does not have stripped variants) - BSK = cuttingCompat(Mods.BSK, "bluebright", "starlit", "frostbright", "lunar", "dusk", "maple"), - BSK_2 = stripAndMakePlanks(Mods.BSK, null, "crystallized_log", "crystallized_planks"), - BSK_3 = stripAndMakePlanks(Mods.BSK, null, "crystallized_wood", "crystallized_planks"), - - // Atmospheric - ATM = cuttingCompat(Mods.ATM, "aspen", "kousa", "yucca", "morado"), - ATM_2 = stripAndMakePlanks(Mods.ATM, "grimwood", "stripped_grimwood", "grimwood_planks"), - ATM_3 = stripAndMakePlanks(Mods.ATM, "rosewood", "stripped_rosewood", "rosewood_planks"), - ATM_4 = cuttingCompatLogOnly(Mods.ATM, "grimwood", "rosewood"), - - // Autumnity - AUTUM = cuttingCompat(Mods.AUTUM, "maple"), - AUTUM_2 = stripAndMakePlanks(Mods.AUTUM, "sappy_maple_wood", "sappy_maple_log", "maple_planks"), - - // Endergetic - ENDERGETIC = stripAndMakePlanks(Mods.ENDER, "poise_stem", "stripped_poise_stem", "poise_planks"), - - // Upgrade Aquatic - UA = cuttingCompat(Mods.UA, "river"), - UA_2 = stripAndMakePlanks(Mods.UA, "driftwood", "stripped_driftwood", "driftwood_planks"), - UA_3 = cuttingCompatLogOnly(Mods.UA, "driftwood"), - - //Vault Hunters - VH = cuttingCompatLogOnly(Mods.VH, "wooden", "overgrown_wooden", "driftwood", "chromatic"), - - // Nether's Exoticism - NE = cuttingCompat(Mods.NE, "ramboutan"), // This actually errors until they fix their id typo - NE_2 = cuttingCompatLogOnly(Mods.NE, "jabuticaba"), - // Regions Unexplored - RU = cuttingCompat(Mods.RU, "baobab", "blackwood", "brimwood", "cobalt", "cypress", "dead", "eucalyptus", "joshua", - "kapok", "larch", "magnolia", "maple","mauve", "palm", "pine", "redwood", "socotra", "willow"), - RU_2 = stripAndMakePlanks(Mods.RU, "blue_bioshroom_stem", "stripped_blue_bioshroom_stem", "blue_bioshroom_planks"), - RU_3 = stripAndMakePlanks(Mods.RU, "blue_bioshroom_hyphae", "stripped_blue_bioshroom_hyphae", "blue_bioshroom_planks"), - RU_4 = stripAndMakePlanks(Mods.RU, "green_bioshroom_stem", "stripped_green_bioshroom_stem", "green_bioshroom_planks"), - RU_5 = stripAndMakePlanks(Mods.RU, "green_bioshroom_hyphae", "stripped_green_bioshroom_hyphae", "green_bioshroom_planks"), - RU_6 = stripAndMakePlanks(Mods.RU, "pink_bioshroom_stem", "stripped_pink_bioshroom_stem", "pink_bioshroom_planks"), - RU_7 = stripAndMakePlanks(Mods.RU, "pink_bioshroom_hyphae", "stripped_pink_bioshroom_hyphae", "pink_bioshroom_planks"), - RU_8 = stripAndMakePlanks(Mods.RU, "yellow_bioshroom_stem", "stripped_yellow_bioshroom_stem", "yellow_bioshroom_planks"), - RU_9 = stripAndMakePlanks(Mods.RU, "yellow_bioshroom_hyphae", "stripped_yellow_bioshroom_hyphae", "yellow_bioshroom_planks"), - RU_10 = stripAndMakePlanks(Mods.RU, null, "alpha_log", "alpha_planks"), - RU_11 = stripAndMakePlanks(Mods.RU, "brimwood_log_magma", "stripped_brimwood", null), - RU_12 = stripAndMakePlanks(Mods.RU, "ashen_log", "stripped_dead_log", null), - RU_13 = stripAndMakePlanks(Mods.RU, "ashen_wood", "stripped_dead_wood", null), RU_14 = stripOnlyDiffModId(Mods.RU, "silver_birch_log", Mods.MC, "stripped_birch_log"), RU_15 = stripOnlyDiffModId(Mods.RU, "silver_birch_wood", Mods.MC, "stripped_birch_wood"), - - // Environmental - ENV = cuttingCompat(Mods.ENV, "willow", "cherry", "wisteria"), - - // Windswept - WSP = cuttingCompat(Mods.WSP, "holly", "chestnut"), - - // Good Ending - GOOD = cuttingCompat(Mods.GOOD, "muddy_oak", "cypress") - + + // IE + IE_WIRES = ieWires("copper", "electrum", "aluminum", "steel", "lead") ; GeneratedRecipe stripAndMakePlanks(Block wood, Block stripped, Block planks) { @@ -235,6 +104,15 @@ public class CuttingRecipeGen extends ProcessingRecipeGen { return null; } + GeneratedRecipe ieWires(String... metals) { + for (String metal : metals) + create(Mods.IE.recipeId("wire_" + metal), b -> b.duration(50) + .require(AllTags.forgeItemTag("plates/" + metal)) + .output(1, Mods.IE, "wire_" + metal, 2) + .whenModLoaded(Mods.IE.getId())); + return null; + } + public CuttingRecipeGen(PackOutput output) { super(output); } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/DeployingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/DeployingRecipeGen.java index 3f6a3f31a9..041241f398 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/DeployingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/DeployingRecipeGen.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.data.recipe; +import java.util.ArrayList; +import java.util.List; import java.util.function.Supplier; import com.simibubi.create.AllBlocks; @@ -8,6 +10,7 @@ import com.simibubi.create.foundation.block.CopperBlockSet; import com.simibubi.create.foundation.block.CopperBlockSet.Variant; import net.minecraft.data.PackOutput; +import net.minecraft.tags.ItemTags; import net.minecraft.world.item.Items; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Blocks; @@ -50,19 +53,50 @@ public class DeployingRecipeGen extends ProcessingRecipeGen { CCS3 = addWax(() -> Blocks.WAXED_WEATHERED_CUT_COPPER_SLAB, () -> Blocks.WEATHERED_CUT_COPPER_SLAB), CCS4 = addWax(() -> Blocks.WAXED_OXIDIZED_CUT_COPPER_SLAB, () -> Blocks.OXIDIZED_CUT_COPPER_SLAB); + GeneratedRecipe + + CB_OX = oxidizationChain(List.of(() -> Blocks.COPPER_BLOCK, () -> Blocks.EXPOSED_COPPER, () -> Blocks.WEATHERED_COPPER, () -> Blocks.OXIDIZED_COPPER)), + CCB_OX = oxidizationChain(List.of(() -> Blocks.CUT_COPPER, () -> Blocks.EXPOSED_CUT_COPPER, () -> Blocks.WEATHERED_CUT_COPPER, () -> Blocks.OXIDIZED_CUT_COPPER)), + CCST_OX = oxidizationChain(List.of(() -> Blocks.CUT_COPPER_STAIRS, () -> Blocks.EXPOSED_CUT_COPPER_STAIRS, () -> Blocks.WEATHERED_CUT_COPPER_STAIRS, () -> Blocks.OXIDIZED_CUT_COPPER_STAIRS)), + CCS_OX = oxidizationChain(List.of(() -> Blocks.CUT_COPPER_SLAB, () -> Blocks.EXPOSED_CUT_COPPER_SLAB, () -> Blocks.WEATHERED_CUT_COPPER_SLAB, () -> Blocks.OXIDIZED_CUT_COPPER_SLAB)); + public GeneratedRecipe copperChain(CopperBlockSet set) { - for (Variant variant : set.getVariants()) - for (WeatherState state : WeatherState.values()) + for (Variant variant : set.getVariants()) { + List> chain = new ArrayList<>(4); + + for (WeatherState state : WeatherState.values()) { addWax(set.get(variant, state, true)::get, set.get(variant, state, false)::get); + chain.add(set.get(variant, state, false)::get); + } + + oxidizationChain(chain); + } return null; } public GeneratedRecipe addWax(Supplier waxed, Supplier nonWaxed) { + createWithDeferredId(idWithSuffix(nonWaxed, "_from_removing_wax"), b -> b.require(waxed.get()) + .require(ItemTags.AXES) + .toolNotConsumed() + .output(nonWaxed.get())); + return createWithDeferredId(idWithSuffix(waxed, "_from_adding_wax"), b -> b.require(nonWaxed.get()) .require(Items.HONEYCOMB_BLOCK) .toolNotConsumed() .output(waxed.get())); } + + public GeneratedRecipe oxidizationChain(List> chain) { + for (int i = 0; i < chain.size() - 1; i++) { + Supplier to = chain.get(i); + Supplier from = chain.get(i + 1); + createWithDeferredId(idWithSuffix(to, "_from_deoxidising"), b -> b.require(from.get()) + .require(ItemTags.AXES) + .toolNotConsumed() + .output(to.get())); + } + return null; + } public DeployingRecipeGen(PackOutput output) { super(output); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java index 583f5ab66a..4e76c97f9f 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.data.recipe; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllTags; import com.simibubi.create.AllTags.AllFluidTags; import com.simibubi.create.content.fluids.potion.PotionFluidHandler; @@ -88,7 +89,15 @@ public class FillingRecipeGen extends ProcessingRecipeGen { VMP_CURSED_GRASS = create(Mods.VMP.recipeId("cursed_grass"), b -> b.require(Fluids.WATER, 500) .require(Mods.VMP, "cursed_earth") .output(Mods.VMP, "cursed_grass") - .whenModLoaded(Mods.VMP.getId())); + .whenModLoaded(Mods.VMP.getId())), + + // IE + + IE_TREATED_WOOD = create(Mods.IE.recipeId("treated_wood_in_spout"), + b -> b.require(AllTags.forgeFluidTag("creosote"), 125) + .require(I.planks()) + .output(Mods.IE, "treated_wood_horizontal") + .whenModLoaded(Mods.IE.getId())); ; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/HauntingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/HauntingRecipeGen.java index e9f02396ca..864ca1e941 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/HauntingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/HauntingRecipeGen.java @@ -5,8 +5,8 @@ import java.util.function.Supplier; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.data.PackOutput; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.Items; @@ -62,8 +62,8 @@ public class HauntingRecipeGen extends ProcessingRecipeGen { } public GeneratedRecipe convert(Supplier input, Supplier result) { - return create(Create.asResource(RegisteredObjects.getKeyOrThrow(result.get() - .asItem()) + return create(Create.asResource(CatnipServices.REGISTRIES.getKeyOrThrow(result.get() + .asItem()) .getPath()), p -> p.withItemIngredients(input.get()) .output(result.get())); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/ItemApplicationRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/ItemApplicationRecipeGen.java index cb09352630..ecd66971f9 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/ItemApplicationRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/ItemApplicationRecipeGen.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.data.recipe; import java.util.function.Supplier; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllTags.AllItemTags; @@ -10,9 +11,15 @@ import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.ItemLike; +import net.minecraftforge.common.Tags.Items; public class ItemApplicationRecipeGen extends ProcessingRecipeGen { + GeneratedRecipe BOUND_CARDBOARD_BLOCK = create("bound_cardboard_inworld", + b -> b.require(AllBlocks.CARDBOARD_BLOCK.asItem()) + .require(Items.STRING) + .output(AllBlocks.BOUND_CARDBOARD_BLOCK.asStack())); + GeneratedRecipe ANDESITE = woodCasing("andesite", I::andesiteAlloy, I::andesiteCasing); GeneratedRecipe COPPER = woodCasingTag("copper", I::copper, I::copperCasing); GeneratedRecipe BRASS = woodCasingTag("brass", I::brass, I::brassCasing); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java b/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java index 0c55256765..f63b74167e 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java @@ -5,10 +5,10 @@ import java.util.List; import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.AxeItem; @@ -34,7 +34,7 @@ public class LogStrippingFakeRecipes { ItemStack axe = new ItemStack(Items.IRON_AXE); axe.hideTooltipPart(TooltipPart.MODIFIERS); - axe.setHoverName(Lang.translateDirect("recipe.item_application.any_axe") + axe.setHoverName(CreateLang.translateDirect("recipe.item_application.any_axe") .withStyle(style -> style.withItalic(false))); ITagManager tags = ForgeRegistries.ITEMS.tags(); tags.getTag(ItemTags.LOGS) @@ -58,7 +58,7 @@ public class LogStrippingFakeRecipes { } private static ManualApplicationRecipe create(Item fromItem, Item toItem, ItemStack axe) { - ResourceLocation rn = RegisteredObjects.getKeyOrThrow(toItem); + ResourceLocation rn = CatnipServices.REGISTRIES.getKeyOrThrow(toItem); return new ProcessingRecipeBuilder<>(ManualApplicationRecipe::new, new ResourceLocation(rn.getNamespace(), rn.getPath() + "_via_vanilla_stripping")).require(fromItem) .require(Ingredient.of(axe)) diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java index b398a31eef..c2875f2aa0 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeBuilder.java @@ -15,8 +15,8 @@ import com.google.common.collect.Sets; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -112,7 +112,7 @@ public class MechanicalCraftingRecipeBuilder { * Builds this recipe into a {@link FinishedRecipe}. */ public void build(Consumer p_200464_1_) { - this.build(p_200464_1_, RegisteredObjects.getKeyOrThrow(this.result)); + this.build(p_200464_1_, CatnipServices.REGISTRIES.getKeyOrThrow(this.result)); } /** @@ -120,7 +120,7 @@ public class MechanicalCraftingRecipeBuilder { * {@link #build(Consumer)} if save is the same as the ID for the result. */ public void build(Consumer p_200466_1_, String p_200466_2_) { - ResourceLocation resourcelocation = RegisteredObjects.getKeyOrThrow(this.result); + ResourceLocation resourcelocation = CatnipServices.REGISTRIES.getKeyOrThrow(this.result); if ((new ResourceLocation(p_200466_2_)).equals(resourcelocation)) { throw new IllegalStateException("Shaped Recipe " + p_200466_2_ + " should remove its 'save' argument"); } else { @@ -209,7 +209,7 @@ public class MechanicalCraftingRecipeBuilder { p_218610_1_.add("key", jsonobject); JsonObject jsonobject1 = new JsonObject(); - jsonobject1.addProperty("item", RegisteredObjects.getKeyOrThrow(this.result) + jsonobject1.addProperty("item", CatnipServices.REGISTRIES.getKeyOrThrow(this.result) .toString()); if (this.count > 1) jsonobject1.addProperty("count", this.count); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java index 5d676b7c00..5c606d1648 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MechanicalCraftingRecipeGen.java @@ -6,8 +6,8 @@ import com.google.common.base.Supplier; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; @@ -41,7 +41,7 @@ public class MechanicalCraftingRecipeGen extends CreateRecipeProvider { .patternLine(" P ") .patternLine(" B ") .patternLine(" O ")), - + EXTENDO_GRIP = create(AllItems.EXTENDO_GRIP::get).returns(1) .recipe(b -> b.key('L', Ingredient.of(I.brass())) .key('R', I.precisionMechanism()) @@ -98,8 +98,8 @@ public class MechanicalCraftingRecipeGen extends CreateRecipeProvider { return register(consumer -> { MechanicalCraftingRecipeBuilder b = builder.apply(MechanicalCraftingRecipeBuilder.shapedRecipe(result.get(), amount)); - ResourceLocation location = Create.asResource("mechanical_crafting/" + RegisteredObjects.getKeyOrThrow(result.get() - .asItem()) + ResourceLocation location = Create.asResource("mechanical_crafting/" + CatnipServices.REGISTRIES.getKeyOrThrow(result.get() + .asItem()) .getPath() + suffix); b.build(consumer, location); }); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java index c8534f278b..5a55108ee0 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.data.recipe; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.content.processing.recipe.HeatCondition; import com.simibubi.create.foundation.recipe.BlockTagIngredient; @@ -62,6 +63,14 @@ public class MixingRecipeGen extends ProcessingRecipeGen { MUD = create("mud_by_mixing", b -> b.require(BlockTagIngredient.create(BlockTags.CONVERTABLE_TO_MUD)) .require(Fluids.WATER, 250) .output(Blocks.MUD, 1)), + + PULP = create("cardboard_pulp", b -> b + .require(AllItemTags.PULPIFIABLE.tag) + .require(AllItemTags.PULPIFIABLE.tag) + .require(AllItemTags.PULPIFIABLE.tag) + .require(AllItemTags.PULPIFIABLE.tag) + .require(Fluids.WATER, 250) + .output(AllItems.PULP, 1)), // AE2 diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java index cfea98ed8d..1766b28529 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.data.recipe; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllTags; import net.minecraft.data.PackOutput; import net.minecraft.world.item.Items; @@ -26,13 +27,16 @@ public class PressingRecipeGen extends ProcessingRecipeGen { BRASS = create("brass_ingot", b -> b.require(I.brass()) .output(AllItems.BRASS_SHEET.get())), + CARDBOARD = create("cardboard", b -> b.require(AllItems.PULP) + .output(AllItems.CARDBOARD.get())), + // Atmospheric ATM = moddedPaths(Mods.ATM, "crustose"), // Better End Forge BEF = moddedPaths(Mods.BEF, "amber_moss", "cave_moss", "chorus_nylium", "crystal_moss", - "end_moss", "end_myclium", "jungle_moss", "pink_moss", "shadow_grass"), + "end_moss", "end_mycelium", "jungle_moss", "pink_moss", "shadow_grass"), // Environmental ENV_MYCELIUM = create("compat/environmental/mycelium_path", b -> b.require(Blocks.MYCELIUM) .output(Mods.ENV, "mycelium_path") @@ -86,6 +90,10 @@ public class PressingRecipeGen extends ProcessingRecipeGen { .output(Mods.RU, "silt_dirt_path") .whenModLoaded(Mods.RU.getId())), + // IE + + IE_PLATES = iePlates("aluminum", "lead", "silver", "nickel", "uranium", "constantan", "electrum", "steel"), + // Vampirism VMP_CURSED_PATH = moddedPaths(Mods.VMP, "cursed_earth"), @@ -104,6 +112,14 @@ public class PressingRecipeGen extends ProcessingRecipeGen { return null; } + GeneratedRecipe iePlates(String... metals) { + for (String metal : metals) + create(Mods.IE.recipeId("plate_" + metal), b -> b.require(AllTags.forgeItemTag("ingots/" + metal)) + .output(Mods.IE, "plate_" + metal) + .whenModLoaded(Mods.IE.getId())); + return null; + } + GeneratedRecipe moddedCompacting(Mods mod, String input, String output) { return create("compat/" + mod.getId() + "/" + output, b -> b.require(mod, input) .output(mod, output) diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java index 47022ed605..1cca44c041 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java @@ -11,8 +11,8 @@ import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer; import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataGenerator; import net.minecraft.data.DataProvider; @@ -74,7 +74,7 @@ public abstract class ProcessingRecipeGen extends CreateRecipeProvider { ItemLike itemLike = singleIngredient.get(); transform .apply(new ProcessingRecipeBuilder<>(serializer.getFactory(), - new ResourceLocation(namespace, RegisteredObjects.getKeyOrThrow(itemLike.asItem()) + new ResourceLocation(namespace, CatnipServices.REGISTRIES.getKeyOrThrow(itemLike.asItem()) .getPath())).withItemIngredients(Ingredient.of(itemLike))) .build(c); }; @@ -127,8 +127,8 @@ public abstract class ProcessingRecipeGen extends CreateRecipeProvider { protected Supplier idWithSuffix(Supplier item, String suffix) { return () -> { - ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(item.get() - .asItem()); + ResourceLocation registryName = CatnipServices.REGISTRIES.getKeyOrThrow(item.get() + .asItem()); return Create.asResource(registryName.getPath() + suffix); }; } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java index eb0c5ab9e3..b5eeb05efa 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java @@ -14,6 +14,8 @@ import java.util.ArrayList; import java.util.List; import java.util.function.UnaryOperator; +import org.jetbrains.annotations.NotNull; + import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.gson.JsonArray; @@ -26,11 +28,11 @@ import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.Create; import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes; -import com.simibubi.create.foundation.utility.RegisteredObjects; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.ItemEntry; import com.tterrag.registrate.util.entry.ItemProviderEntry; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.data.PackOutput; import net.minecraft.data.recipes.FinishedRecipe; @@ -59,8 +61,6 @@ import net.minecraftforge.common.crafting.conditions.ICondition; import net.minecraftforge.common.crafting.conditions.ModLoadedCondition; import net.minecraftforge.common.crafting.conditions.NotCondition; -import org.jetbrains.annotations.NotNull; - @SuppressWarnings("unused") public class StandardRecipeGen extends CreateRecipeProvider { @@ -116,6 +116,26 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("CCC") .pattern("CCC")), + CARDBOARD_BLOCK = create(AllBlocks.CARDBOARD_BLOCK).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('C', I.cardboard()) + .pattern("CC") + .pattern("CC")), + + BOUND_CARDBOARD_BLOCK = create(AllBlocks.BOUND_CARDBOARD_BLOCK).returns(1) + .unlockedBy(I::cardboard) + .viaShapeless(b -> b.requires(AllBlocks.CARDBOARD_BLOCK.get()) + .requires(Items.STRING)), + + CARDBOARD_FROM_BLOCK = create(AllItems.CARDBOARD).withSuffix("_from_block") + .returns(4) + .unlockedBy(I::cardboard) + .viaShapeless(b -> b.requires(AllBlocks.CARDBOARD_BLOCK.get())), + + CARDBOARD_FROM_BOUND_BLOCK = create(AllItems.CARDBOARD).withSuffix("_from_bound_block") + .returns(4) + .unlockedBy(I::cardboard) + .viaShapeless(b -> b.requires(AllBlocks.BOUND_CARDBOARD_BLOCK.get())), + BRASS_COMPACTING = metalCompacting(ImmutableList.of(AllItems.BRASS_NUGGET, AllItems.BRASS_INGOT, AllBlocks.BRASS_BLOCK), ImmutableList.of(I::brassNugget, I::brass, I::brassBlock)), @@ -146,6 +166,14 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("L") .pattern("N")), + TRANSMITTER = create(AllItems.TRANSMITTER).unlockedByTag(I::copper) + .viaShaped(b -> b.define('L', I.copperSheet()) + .define('N', Items.LIGHTNING_ROD) + .define('R', I.redstone()) + .pattern(" N ") + .pattern("LLL") + .pattern(" R ")), + ROSE_QUARTZ = create(AllItems.ROSE_QUARTZ).unlockedBy(() -> Items.REDSTONE) .viaShapeless(b -> b.requires(Tags.Items.GEMS_QUARTZ) .requires(Ingredient.of(I.redstone()), 8)), @@ -174,6 +202,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern(" L ")), TOOLBOX_DYEING = createSpecial(AllRecipeTypes.TOOLBOX_DYEING::getSerializer, "crafting", "toolbox_dyeing"), + ITEM_COPYING = createSpecial(AllRecipeTypes.ITEM_COPYING::getSerializer, "crafting", "item_copying"), MINECART_COUPLING = create(AllItems.MINECART_COUPLING).unlockedBy(I::andesiteAlloy) .viaShaped(b -> b.define('E', I.andesiteAlloy()) @@ -231,6 +260,11 @@ public class StandardRecipeGen extends CreateRecipeProvider { .define('A', I.brassNugget()) .pattern("ASA")), + PACKAGE_FILTER = create(AllItems.PACKAGE_FILTER).unlockedByTag(I::zinc) + .viaShaped(b -> b.define('S', ItemTags.WOOL) + .define('A', I.zincNugget()) + .pattern("ASA")), + BRASS_HAND = create(AllItems.BRASS_HAND).unlockedByTag(I::brass) .viaShaped(b -> b.define('A', I.andesiteAlloy()) .define('B', I.brassSheet()) @@ -806,10 +840,10 @@ public class StandardRecipeGen extends CreateRecipeProvider { VERTICAL_GEARBOX = create(AllItems.VERTICAL_GEARBOX).unlockedBy(I::cog) .viaShaped(b -> b.define('C', I.cog()) - .define('B', I.andesiteCasing()) - .pattern("C C") - .pattern(" B ") - .pattern("C C")), + .define('B', I.andesiteCasing()) + .pattern("C C") + .pattern(" B ") + .pattern("C C")), GEARBOX_CYCLE = conversionCycle(ImmutableList.of(AllBlocks.GEARBOX, AllItems.VERTICAL_GEARBOX)), @@ -825,6 +859,12 @@ public class StandardRecipeGen extends CreateRecipeProvider { .requires(I.ironNugget()) .requires(I.ironNugget()) .requires(I.ironNugget())), + + ENCASED_CHAIN_DRIVE_ZINC = create(AllBlocks.ENCASED_CHAIN_DRIVE).withSuffix("_from_zinc").unlockedBy(I::andesiteCasing) + .viaShapeless(b -> b.requires(I.andesiteCasing()) + .requires(I.zincNugget()) + .requires(I.zincNugget()) + .requires(I.zincNugget())), FLYWHEEL = create(AllBlocks.FLYWHEEL).unlockedByTag(I::brass) .viaShaped(b -> b.define('C', I.brass()) @@ -892,6 +932,14 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("AIA") .pattern(" C ")), + CHAIN_CONVEYOR = create(AllBlocks.CHAIN_CONVEYOR).unlockedBy(I::andesiteCasing) + .returns(2) + .viaShaped(b -> b.define('C', I.andesiteCasing()) + .define('A', I.largeCog()) + .pattern(" C ") + .pattern("CAC") + .pattern(" C ")), + SEQUENCED_GEARSHIFT = create(AllBlocks.SEQUENCED_GEARSHIFT).unlockedBy(I::brassCasing) .viaShapeless(b -> b.requires(I.brassCasing()) .requires(I.cog()) @@ -977,6 +1025,14 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("RCT") .pattern("SSS")), + PULSE_TIMER = create(AllBlocks.PULSE_TIMER).unlockedByTag(I::redstone) + .viaShaped(b -> b.define('T', Blocks.REDSTONE_TORCH) + .define('C', I.brassSheet()) + .define('R', Items.AMETHYST_SHARD) + .define('S', I.stone()) + .pattern("RCT") + .pattern("SSS")), + POWERED_TOGGLE_LATCH = create(AllBlocks.POWERED_TOGGLE_LATCH).unlockedByTag(I::redstone) .viaShaped(b -> b.define('T', Blocks.REDSTONE_TORCH) .define('C', Blocks.LEVER) @@ -995,19 +1051,74 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("SSS")), REDSTONE_LINK = create(AllBlocks.REDSTONE_LINK).returns(2) - .unlockedBy(I::brassCasing) - .viaShaped(b -> b.define('C', Blocks.REDSTONE_TORCH) - .define('S', I.brassCasing()) + .unlockedBy(I::andesiteCasing) + .viaShaped(b -> b.define('C', AllItems.TRANSMITTER) + .define('S', I.andesiteCasing()) .pattern("C") .pattern("S")), + ITEM_HATCH = create(AllBlocks.ITEM_HATCH).unlockedBy(I::andesiteAlloy) + .viaShapeless(b -> b.requires(I.andesiteAlloy()) + .requires(Items.IRON_TRAPDOOR)), + + PACKAGER = create(AllBlocks.PACKAGER).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('C', I.iron()) + .define('A', AllBlocks.CARDBOARD_BLOCK) + .define('R', I.redstone()) + .pattern(" C ") + .pattern("CAC") + .pattern("RCR")), + + PACKAGER_CYCLE = conversionCycle(ImmutableList.of(AllBlocks.PACKAGER, AllBlocks.REPACKAGER)), + + PACKAGE_FROGPORT = create(AllBlocks.PACKAGE_FROGPORT).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('C', I.andesiteAlloy()) + .define('B', Tags.Items.SLIMEBALLS) + .define('A', I.vault()) + .pattern("B") + .pattern("A") + .pattern("C")), + + STOCK_LINK = create(AllBlocks.STOCK_LINK).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('C', AllItems.TRANSMITTER.get()) + .define('B', I.vault()) + .pattern("C") + .pattern("B")), + + STOCK_TICKER = create(AllBlocks.STOCK_TICKER).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('C', Tags.Items.GLASS) + .define('B', I.gold()) + .define('A', I.stockLink()) + .pattern("C") + .pattern("A") + .pattern("B")), + + REDSTONE_REQUESTER = create(AllBlocks.REDSTONE_REQUESTER).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('C', I.redstone()) + .define('B', I.iron()) + .define('A', I.stockLink()) + .pattern("C") + .pattern("A") + .pattern("B")), + + FACTORY_GAUGE = create(AllBlocks.FACTORY_GAUGE).unlockedBy(I::stockLink) + .returns(2) + .viaShapeless(b -> b.requires(I.stockLink()) + .requires(I.precisionMechanism())), + + DESK_BELL = create(AllBlocks.DESK_BELL).unlockedBy(I::andesiteCasing) + .viaShapeless(b -> b.requires(I.andesiteCasing()) + .requires(I.goldSheet())), + + LOGISTICS_LINK_CLEAR = clearData(AllBlocks.STOCK_LINK), STOCK_TICKER_CLEAR = clearData(AllBlocks.STOCK_TICKER), + REDSTONE_REQUESTER_CLEAR = clearData(AllBlocks.REDSTONE_REQUESTER), + FACTORY_PANEL_CLEAR = clearData(AllBlocks.FACTORY_GAUGE), + DISPLAY_LINK = create(AllBlocks.DISPLAY_LINK).unlockedBy(I::brassCasing) - .viaShaped(b -> b.define('C', Blocks.REDSTONE_TORCH) - .define('A', I.copperSheet()) + .viaShaped(b -> b.define('C', AllItems.TRANSMITTER.get()) .define('S', I.brassCasing()) .pattern("C") - .pattern("S") - .pattern("A")) + .pattern("S")) ; @@ -1064,6 +1175,14 @@ public class StandardRecipeGen extends CreateRecipeProvider { .viaShapeless(b -> b.requires(I.wheatFlour()) .requires(Items.WATER_BUCKET)), + CHAIN_FROM_ZINC = create(() -> Items.CHAIN).withSuffix("_from_zinc") + .unlockedByTag(I::zinc) + .viaShaped(b -> b.define('C', I.zinc()) + .define('S', I.zincNugget()) + .pattern("S") + .pattern("C") + .pattern("S")), + CLIPBOARD = create(AllBlocks.CLIPBOARD).unlockedBy(I::andesiteAlloy) .viaShaped(b -> b.define('G', I.planks()) .define('P', Items.PAPER) @@ -1074,6 +1193,36 @@ public class StandardRecipeGen extends CreateRecipeProvider { CLIPBOARD_CLEAR = clearData(AllBlocks.CLIPBOARD), SCHEDULE_CLEAR = clearData(AllItems.SCHEDULE), FILTER_CLEAR = clearData(AllItems.FILTER), ATTRIBUTE_FILTER_CLEAR = clearData(AllItems.ATTRIBUTE_FILTER), + PACKAGE_FILTER_CLEAR = clearData(AllItems.PACKAGE_FILTER), + + CARDBOARD_SWORD = create(AllItems.CARDBOARD_SWORD).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('P', I.cardboard()) + .define('S', Tags.Items.RODS_WOODEN) + .pattern("P") + .pattern("P") + .pattern("S")), + + CARDBOARD_HELMET = create(AllItems.CARDBOARD_HELMET).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('P', I.cardboard()) + .pattern("PPP") + .pattern("P P")), + + CARDBOARD_CHESTPLATE = create(AllItems.CARDBOARD_CHESTPLATE).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('P', I.cardboard()) + .pattern("P P") + .pattern("PPP") + .pattern("PPP")), + + CARDBOARD_LEGGINGS = create(AllItems.CARDBOARD_LEGGINGS).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('P', I.cardboard()) + .pattern("PPP") + .pattern("P P") + .pattern("P P")), + + CARDBOARD_BOOTS = create(AllItems.CARDBOARD_BOOTS).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('P', I.cardboard()) + .pattern("P P") + .pattern("P P")), DIVING_HELMET = create(AllItems.COPPER_DIVING_HELMET).unlockedByTag(I::copper) .viaShaped(b -> b.define('G', Tags.Items.GLASS) @@ -1112,6 +1261,24 @@ public class StandardRecipeGen extends CreateRecipeProvider { .viaShapeless(b -> b.requires(AllItems.DOUGH.get()) .requires(Tags.Items.DYES_LIME)), + BOOK = create(() -> Items.BOOK).unlockedBy(I::cardboard) + .viaShapeless(b -> b.requires(I.cardboard()) + .requires(Items.PAPER) + .requires(Items.PAPER) + .requires(Items.PAPER)), + + NAME_TAG = create(() -> Items.NAME_TAG).unlockedBy(I::cardboard) + .viaShapeless(b -> b.requires(Tags.Items.DYES_BLACK) + .requires(Tags.Items.STRING) + .requires(I.cardboard())), + + ITEM_FRAME = create(() -> Items.ITEM_FRAME).unlockedBy(I::cardboard) + .viaShaped(b -> b.define('S', Tags.Items.RODS_WOODEN) + .define('P', I.cardboard()) + .pattern("SSS") + .pattern("SPS") + .pattern("SSS")), + TREE_FERTILIZER = create(AllItems.TREE_FERTILIZER).returns(2) .unlockedBy(() -> Items.BONE_MEAL) .viaShapeless(b -> b.requires(Ingredient.of(ItemTags.SMALL_FLOWERS), 2) @@ -1119,17 +1286,19 @@ public class StandardRecipeGen extends CreateRecipeProvider { Items.FIRE_CORAL)) .requires(Items.BONE_MEAL)), - NETHERITE_DIVING_HELMET = - create(AllItems.NETHERITE_DIVING_HELMET).viaNetheriteSmithing(AllItems.COPPER_DIVING_HELMET::get, I::netherite), + NETHERITE_DIVING_HELMET = create(AllItems.NETHERITE_DIVING_HELMET) + .viaNetheriteSmithing(AllItems.COPPER_DIVING_HELMET::get, I::netherite), NETHERITE_BACKTANK = create(AllItems.NETHERITE_BACKTANK).viaNetheriteSmithing(AllItems.COPPER_BACKTANK::get, I::netherite), - NETHERITE_DIVING_BOOTS = - create(AllItems.NETHERITE_DIVING_BOOTS).viaNetheriteSmithing(AllItems.COPPER_DIVING_BOOTS::get, I::netherite), + NETHERITE_DIVING_BOOTS = create(AllItems.NETHERITE_DIVING_BOOTS) + .viaNetheriteSmithing(AllItems.COPPER_DIVING_BOOTS::get, I::netherite), NETHERITE_DIVING_HELMET_2 = create(AllItems.NETHERITE_DIVING_HELMET).withSuffix("_from_netherite") - .viaNetheriteSmithing(() -> Items.NETHERITE_HELMET, () -> Ingredient.of(AllItems.COPPER_DIVING_HELMET.get())), + .viaNetheriteSmithing(() -> Items.NETHERITE_HELMET, + () -> Ingredient.of(AllItems.COPPER_DIVING_HELMET.get())), NETHERITE_BACKTANK_2 = create(AllItems.NETHERITE_BACKTANK).withSuffix("_from_netherite") - .viaNetheriteSmithing(() -> Items.NETHERITE_CHESTPLATE, () -> Ingredient.of(AllItems.COPPER_BACKTANK.get())), + .viaNetheriteSmithing(() -> Items.NETHERITE_CHESTPLATE, + () -> Ingredient.of(AllItems.COPPER_BACKTANK.get())), NETHERITE_DIVING_BOOTS_2 = create(AllItems.NETHERITE_DIVING_BOOTS).withSuffix("_from_netherite") .viaNetheriteSmithing(() -> Items.NETHERITE_BOOTS, () -> Ingredient.of(AllItems.COPPER_DIVING_BOOTS.get())) @@ -1183,7 +1352,8 @@ public class StandardRecipeGen extends CreateRecipeProvider { .unlockedBy(() -> Items.BONE_MEAL) .whenModLoaded(Mods.UA.getId()) .viaShapeless(b -> b.requires(Ingredient.of(ItemTags.SMALL_FLOWERS), 2) - .requires(AllItemTags.UA_CORAL.tag).requires(Items.BONE_MEAL)) + .requires(AllItemTags.UA_CORAL.tag) + .requires(Items.BONE_MEAL)) ; @@ -1285,7 +1455,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { for (int i = 0; i < cycle.size(); i++) { ItemProviderEntry currentEntry = cycle.get(i); ItemProviderEntry nextEntry = cycle.get((i + 1) % cycle.size()); - result = create(nextEntry).withSuffix("from_conversion") + result = create(nextEntry).withSuffix("_from_conversion") .unlockedBy(currentEntry::get) .viaShapeless(b -> b.requires(currentEntry.get())); } @@ -1366,7 +1536,8 @@ public class StandardRecipeGen extends CreateRecipeProvider { // FIXME 5.1 refactor - recipe categories as markers instead of sections? GeneratedRecipe viaShaped(UnaryOperator builder) { return register(consumer -> { - ShapedRecipeBuilder b = builder.apply(ShapedRecipeBuilder.shaped(RecipeCategory.MISC, result.get(), amount)); + ShapedRecipeBuilder b = + builder.apply(ShapedRecipeBuilder.shaped(RecipeCategory.MISC, result.get(), amount)); if (unlockedBy != null) b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); b.save(consumer, createLocation("crafting")); @@ -1375,14 +1546,15 @@ public class StandardRecipeGen extends CreateRecipeProvider { GeneratedRecipe viaShapeless(UnaryOperator builder) { return register(consumer -> { - ShapelessRecipeBuilder b = builder.apply(ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, result.get(), amount)); + ShapelessRecipeBuilder b = + builder.apply(ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, result.get(), amount)); if (unlockedBy != null) b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); b.save(result -> { - consumer.accept( - !recipeConditions.isEmpty() ? new ConditionSupportingShapelessRecipeResult(result, recipeConditions) - : result); + consumer.accept(!recipeConditions.isEmpty() + ? new ConditionSupportingShapelessRecipeResult(result, recipeConditions) + : result); }, createLocation("crafting")); }); } @@ -1409,7 +1581,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { } private ResourceLocation getRegistryName() { - return compatDatagenOutput == null ? RegisteredObjects.getKeyOrThrow(result.get() + return compatDatagenOutput == null ? CatnipServices.REGISTRIES.getKeyOrThrow(result.get() .asItem()) : compatDatagenOutput; } @@ -1494,7 +1666,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { consumer.accept( isOtherMod ? new ModdedCookingRecipeResult(result, compatDatagenOutput, recipeConditions) : result); - }, createSimpleLocation(RegisteredObjects.getKeyOrThrow(serializer) + }, createSimpleLocation(CatnipServices.REGISTRIES.getKeyOrThrow(serializer) .getPath())); }); } @@ -1510,39 +1682,41 @@ public class StandardRecipeGen extends CreateRecipeProvider { super(p_i48262_1_); } - private record ModdedCookingRecipeResult(FinishedRecipe wrapped, ResourceLocation outputOverride, List conditions) implements FinishedRecipe { - @Override - public ResourceLocation getId() { - return wrapped.getId(); - } - - @Override - public RecipeSerializer getType() { - return wrapped.getType(); - } - - @Override - public JsonObject serializeAdvancement() { - return wrapped.serializeAdvancement(); - } - - @Override - public ResourceLocation getAdvancementId() { - return wrapped.getAdvancementId(); - } - - @Override - public void serializeRecipeData(JsonObject object) { - wrapped.serializeRecipeData(object); - object.addProperty("result", outputOverride.toString()); - - JsonArray conds = new JsonArray(); - conditions.forEach(c -> conds.add(CraftingHelper.serialize(c))); - object.add("conditions", conds); - } + private record ModdedCookingRecipeResult(FinishedRecipe wrapped, ResourceLocation outputOverride, + List conditions) implements FinishedRecipe { + @Override + public ResourceLocation getId() { + return wrapped.getId(); } - private record ConditionSupportingShapelessRecipeResult(FinishedRecipe wrapped, List conditions) implements FinishedRecipe { + @Override + public RecipeSerializer getType() { + return wrapped.getType(); + } + + @Override + public JsonObject serializeAdvancement() { + return wrapped.serializeAdvancement(); + } + + @Override + public ResourceLocation getAdvancementId() { + return wrapped.getAdvancementId(); + } + + @Override + public void serializeRecipeData(JsonObject object) { + wrapped.serializeRecipeData(object); + object.addProperty("result", outputOverride.toString()); + + JsonArray conds = new JsonArray(); + conditions.forEach(c -> conds.add(CraftingHelper.serialize(c))); + object.add("conditions", conds); + } + } + + private record ConditionSupportingShapelessRecipeResult(FinishedRecipe wrapped, List conditions) + implements FinishedRecipe { @Override public ResourceLocation getId() { return wrapped.getId(); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java index 28b4e20630..54644334ee 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java @@ -12,8 +12,10 @@ import static com.simibubi.create.foundation.data.recipe.CompatMetals.URANIUM; import java.util.function.Supplier; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; import com.tterrag.registrate.util.entry.ItemEntry; import net.minecraft.data.PackOutput; @@ -47,6 +49,13 @@ public class WashingRecipeGen extends ProcessingRecipeGen { .output(.05f, Items.DEAD_BUSH)), SAND = create(() -> Blocks.SAND, b -> b.output(.25f, Items.CLAY_BALL)), + WEATHERED_IRON_BLOCK = + create(AllBlocks.INDUSTRIAL_IRON_BLOCK::get, b -> b.output(AllBlocks.WEATHERED_IRON_BLOCK)), + WEATHERED_IRON_WINDOW = + create(AllPaletteBlocks.INDUSTRIAL_IRON_WINDOW::get, b -> b.output(AllPaletteBlocks.WEATHERED_IRON_WINDOW)), + WEATHERED_IRON_WINDOW_PANE = create(AllPaletteBlocks.INDUSTRIAL_IRON_WINDOW_PANE::get, + b -> b.output(AllPaletteBlocks.WEATHERED_IRON_WINDOW_PANE)), + CRUSHED_COPPER = crushedOre(AllItems.CRUSHED_COPPER, AllItems.COPPER_NUGGET::get, () -> Items.CLAY_BALL, .5f), CRUSHED_ZINC = crushedOre(AllItems.CRUSHED_ZINC, AllItems.ZINC_NUGGET::get, () -> Items.GUNPOWDER, .25f), CRUSHED_GOLD = crushedOre(AllItems.CRUSHED_GOLD, () -> Items.GOLD_NUGGET, () -> Items.QUARTZ, .5f), @@ -80,7 +89,7 @@ public class WashingRecipeGen extends ProcessingRecipeGen { BLUE_CONCRETE = convert(Blocks.BLUE_CONCRETE_POWDER, Blocks.BLUE_CONCRETE), CYAN_CONCRETE = convert(Blocks.CYAN_CONCRETE_POWDER, Blocks.CYAN_CONCRETE), BLACK_CONCRETE = convert(Blocks.BLACK_CONCRETE_POWDER, Blocks.BLACK_CONCRETE), - + FLOUR = create("wheat_flour", b -> b.require(I.wheatFlour()) .output(AllItems.DOUGH.get())), diff --git a/src/main/java/com/simibubi/create/foundation/events/ClientEvents.java b/src/main/java/com/simibubi/create/foundation/events/ClientEvents.java index f41ba8c3bb..080ead8177 100644 --- a/src/main/java/com/simibubi/create/foundation/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/foundation/events/ClientEvents.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.events; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllItems; import com.simibubi.create.AllPackets; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; @@ -14,8 +15,10 @@ import com.simibubi.create.content.contraptions.minecart.CouplingPhysics; import com.simibubi.create.content.contraptions.minecart.CouplingRenderer; import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.render.ContraptionRenderInfoManager; +import com.simibubi.create.content.contraptions.wrench.RadialWrenchHandler; import com.simibubi.create.content.decoration.girder.GirderWrenchBehavior; import com.simibubi.create.content.equipment.armor.BacktankArmorLayer; +import com.simibubi.create.content.equipment.armor.CardboardArmorStealthOverlay; import com.simibubi.create.content.equipment.armor.DivingHelmetItem; import com.simibubi.create.content.equipment.armor.NetheriteBacktankFirstPersonRenderer; import com.simibubi.create.content.equipment.armor.NetheriteDivingHandler; @@ -24,17 +27,26 @@ import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer; import com.simibubi.create.content.equipment.clipboard.ClipboardValueSettingsHandler; import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripRenderHandler; import com.simibubi.create.content.equipment.goggles.GoggleOverlayRenderer; +import com.simibubi.create.content.equipment.hats.CreateHatArmorLayer; +import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItemRenderer; import com.simibubi.create.content.equipment.toolbox.ToolboxHandlerClient; import com.simibubi.create.content.equipment.zapper.ZapperItem; import com.simibubi.create.content.equipment.zapper.terrainzapper.WorldshaperRenderHandler; import com.simibubi.create.content.kinetics.KineticDebugger; import com.simibubi.create.content.kinetics.belt.item.BeltConnectorHandler; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorConnectionHandler; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorInteractionHandler; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorRidingHandler; import com.simibubi.create.content.kinetics.fan.AirCurrent; import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointHandler; import com.simibubi.create.content.kinetics.turntable.TurntableHandler; import com.simibubi.create.content.logistics.depot.EjectorTargetHandler; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelConnectionHandler; +import com.simibubi.create.content.logistics.packagePort.PackagePortTargetSelectionHandler; +import com.simibubi.create.content.logistics.packagerLink.LogisticallyLinkedClientHandler; +import com.simibubi.create.content.logistics.tableCloth.TableClothOverlayRenderer; import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; -import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockItem; +import com.simibubi.create.content.redstone.displayLink.ClickToLinkBlockItem; import com.simibubi.create.content.redstone.link.LinkRenderer; import com.simibubi.create.content.redstone.link.controller.LinkedControllerClientHandler; import com.simibubi.create.content.trains.CameraDistanceModifier; @@ -42,7 +54,6 @@ import com.simibubi.create.content.trains.TrainHUD; import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.content.trains.entity.CarriageCouplingRenderer; import com.simibubi.create.content.trains.entity.TrainRelocator; -import com.simibubi.create.content.trains.schedule.hat.TrainHatArmorLayer; import com.simibubi.create.content.trains.schedule.hat.TrainHatInfoReloadListener; import com.simibubi.create.content.trains.track.CurvedTrackInteraction; import com.simibubi.create.content.trains.track.TrackBlockOutline; @@ -53,20 +64,21 @@ import com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction.Edge import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueHandler; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueRenderer; -import com.simibubi.create.foundation.config.ui.BaseConfigScreen; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.item.TooltipModifier; import com.simibubi.create.foundation.networking.LeftClickPacket; -import com.simibubi.create.foundation.placement.PlacementHelpers; -import com.simibubi.create.foundation.ponder.PonderTooltipHandler; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.sound.SoundScapes; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.CameraAngleAnimationService; import com.simibubi.create.foundation.utility.ServerSpeedProvider; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedClientWorld; +import com.simibubi.create.foundation.utility.TickBasedCache; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.createmod.catnip.animation.AnimationTickHolder; +import net.createmod.catnip.config.ui.BaseConfigScreen; +import net.createmod.catnip.levelWrappers.WrappedClientLevel; +import net.createmod.catnip.render.DefaultSuperRenderTypeBuffer; +import net.createmod.catnip.render.SuperRenderTypeBuffer; +import net.createmod.ponder.foundation.PonderTooltipHandler; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -80,15 +92,16 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.ConfigScreenHandler; import net.minecraftforge.client.event.ClientPlayerNetworkEvent; import net.minecraftforge.client.event.EntityRenderersEvent; import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; import net.minecraftforge.client.event.RegisterGuiOverlaysEvent; +import net.minecraftforge.client.event.RegisterItemDecorationsEvent; import net.minecraftforge.client.event.RenderLevelStageEvent; import net.minecraftforge.client.event.RenderLevelStageEvent.Stage; -import net.minecraftforge.client.event.RenderTooltipEvent; import net.minecraftforge.client.event.ViewportEvent; import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay; import net.minecraftforge.event.TickEvent.ClientTickEvent; @@ -121,7 +134,6 @@ public class ClientEvents { } SoundScapes.tick(); - AnimationTickHolder.tick(); CreateClient.SCHEMATIC_SENDER.tick(); CreateClient.SCHEMATIC_AND_QUILL_HANDLER.tick(); @@ -155,16 +167,14 @@ public class ClientEvents { // CollisionDebugger.tick(); ArmInteractionPointHandler.tick(); EjectorTargetHandler.tick(); - PlacementHelpers.tick(); - CreateClient.OUTLINER.tickOutlines(); - CreateClient.GHOST_BLOCKS.tickGhosts(); ContraptionRenderInfoManager.tickFor(world); BlueprintOverlayRenderer.tick(); ToolboxHandlerClient.clientTick(); + RadialWrenchHandler.clientTick(); TrackTargetingClient.clientTick(); TrackPlacement.clientTick(); TrainRelocator.clientTick(); - DisplayLinkBlockItem.clientTick(); + ClickToLinkBlockItem.clientTick(); CurvedTrackInteraction.clientTick(); CameraDistanceModifier.tick(); CameraAngleAnimationService.tick(); @@ -174,6 +184,15 @@ public class ClientEvents { ScrollValueHandler.tick(); NetheriteBacktankFirstPersonRenderer.clientTick(); ContraptionPlayerPassengerRotation.tick(); + ChainConveyorInteractionHandler.clientTick(); + ChainConveyorRidingHandler.clientTick(); + ChainConveyorConnectionHandler.clientTick(); + PackagePortTargetSelectionHandler.tick(); + LogisticallyLinkedClientHandler.tick(); + TableClothOverlayRenderer.tick(); + CardboardArmorStealthOverlay.clientTick(); + FactoryPanelConnectionHandler.clientTick(); + TickBasedCache.clientTick(); } @SubscribeEvent @@ -189,7 +208,7 @@ public class ClientEvents { @SubscribeEvent public static void onLoadWorld(LevelEvent.Load event) { LevelAccessor world = event.getLevel(); - if (world.isClientSide() && world instanceof ClientLevel && !(world instanceof WrappedClientWorld)) { + if (world.isClientSide() && world instanceof ClientLevel && !(world instanceof WrappedClientLevel)) { CreateClient.invalidateRenderers(); AnimationTickHolder.reset(); } @@ -213,8 +232,7 @@ public class ClientEvents { PoseStack ms = event.getPoseStack(); ms.pushPose(); - SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); - float partialTicks = AnimationTickHolder.getPartialTicks(); + SuperRenderTypeBuffer buffer = DefaultSuperRenderTypeBuffer.getInstance(); Vec3 camera = Minecraft.getInstance().gameRenderer.getMainCamera() .getPosition(); @@ -223,13 +241,12 @@ public class ClientEvents { CouplingRenderer.renderAll(ms, buffer, camera); CarriageCouplingRenderer.renderAll(ms, buffer, camera); CreateClient.SCHEMATIC_HANDLER.render(ms, buffer, camera); - CreateClient.GHOST_BLOCKS.renderAll(ms, buffer, camera); - CreateClient.OUTLINER.renderOutlines(ms, buffer, camera, partialTicks); + ChainConveyorInteractionHandler.drawCustomBlockSelection(ms, buffer, camera); buffer.draw(); RenderSystem.enableCull(); ms.popPose(); - + ContraptionPlayerPassengerRotation.frame(); } @@ -244,11 +261,6 @@ public class ClientEvents { event.setPitch(CameraAngleAnimationService.getPitch(partialTicks)); } - @SubscribeEvent - public static void getItemTooltipColor(RenderTooltipEvent.Color event) { - PonderTooltipHandler.handleTooltipColor(event); - } - @SubscribeEvent public static void addToItemTooltip(ItemTooltipEvent event) { if (!AllConfigs.client().tooltips.get()) @@ -262,7 +274,6 @@ public class ClientEvents { modifier.modify(event); } - PonderTooltipHandler.addToTooltip(event); SequencedAssemblyRecipe.addToTooltip(event); } @@ -346,7 +357,7 @@ public class ClientEvents { EntityRenderDispatcher dispatcher = Minecraft.getInstance() .getEntityRenderDispatcher(); BacktankArmorLayer.registerOnAll(dispatcher); - TrainHatArmorLayer.registerOnAll(dispatcher); + CreateHatArmorLayer.registerOnAll(dispatcher); } @SubscribeEvent @@ -363,6 +374,11 @@ public class ClientEvents { event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "toolbox", ToolboxHandlerClient.OVERLAY); } + @SubscribeEvent + public static void registerItemDecorations(RegisterItemDecorationsEvent event) { + event.register(AllItems.POTATO_CANNON, PotatoCannonItemRenderer.DECORATOR); + } + @SubscribeEvent public static void onLoadComplete(FMLLoadCompleteEvent event) { ModContainer createContainer = ModList.get() @@ -370,7 +386,7 @@ public class ClientEvents { .orElseThrow(() -> new IllegalStateException("Create mod container missing on LoadComplete")); createContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> new ConfigScreenHandler.ConfigScreenFactory( - (mc, previousScreen) -> BaseConfigScreen.forCreate(previousScreen))); + (mc, previousScreen) -> new BaseConfigScreen(previousScreen, Create.ID))); } } diff --git a/src/main/java/com/simibubi/create/foundation/events/CommonEvents.java b/src/main/java/com/simibubi/create/foundation/events/CommonEvents.java index 5ae94185ef..7f94e72ec1 100644 --- a/src/main/java/com/simibubi/create/foundation/events/CommonEvents.java +++ b/src/main/java/com/simibubi/create/foundation/events/CommonEvents.java @@ -6,36 +6,38 @@ import com.simibubi.create.content.contraptions.ContraptionHandler; import com.simibubi.create.content.contraptions.actors.trainControls.ControlsServerHandler; import com.simibubi.create.content.contraptions.minecart.CouplingPhysics; import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; -import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileTypeManager; import com.simibubi.create.content.equipment.toolbox.ToolboxHandler; import com.simibubi.create.content.equipment.wrench.WrenchItem; import com.simibubi.create.content.equipment.zapper.ZapperInteractionHandler; import com.simibubi.create.content.equipment.zapper.ZapperItem; import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.chainConveyor.ServerChainConveyorHandler; +import com.simibubi.create.content.kinetics.drill.CobbleGenOptimisation; import com.simibubi.create.content.redstone.link.controller.LinkedControllerServerHandler; import com.simibubi.create.content.trains.entity.CarriageEntityHandler; -import com.simibubi.create.foundation.ModFilePackResources; +import com.simibubi.create.foundation.data.RuntimeDataGenerator; +import com.simibubi.create.foundation.pack.DynamicPack; +import com.simibubi.create.foundation.pack.DynamicPackSource; import com.simibubi.create.foundation.recipe.RecipeFinder; -import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.ServerSpeedProvider; -import com.simibubi.create.foundation.utility.WorldAttached; +import com.simibubi.create.foundation.utility.TickBasedCache; import com.simibubi.create.infrastructure.command.AllCommands; +import net.createmod.catnip.data.WorldAttached; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.repository.Pack; -import net.minecraft.server.packs.repository.PackSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; + import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.event.AddPackFindersEvent; import net.minecraftforge.event.AddReloadListenerEvent; import net.minecraftforge.event.AttachCapabilitiesEvent; -import net.minecraftforge.event.OnDatapackSyncEvent; import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.TickEvent.LevelTickEvent; import net.minecraftforge.event.TickEvent.Phase; @@ -52,10 +54,7 @@ import net.minecraftforge.event.level.LevelEvent; import net.minecraftforge.event.server.ServerStoppingEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.LogicalSide; -import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import net.minecraftforge.forgespi.language.IModFileInfo; -import net.minecraftforge.forgespi.locating.IModFile; @EventBusSubscriber public class CommonEvents { @@ -69,6 +68,8 @@ public class CommonEvents { ServerSpeedProvider.serverTick(); Create.RAILWAYS.sync.serverTick(); TrainMapSync.serverTick(event); + ServerChainConveyorHandler.tick(); + TickBasedCache.tick(); } @SubscribeEvent @@ -102,6 +103,7 @@ public class CommonEvents { LinkedControllerServerHandler.tick(world); ControlsServerHandler.tick(world); Create.RAILWAYS.tick(world); + Create.LOGISTICS.tick(world); } @SubscribeEvent @@ -139,20 +141,9 @@ public class CommonEvents { @SubscribeEvent public static void addReloadListeners(AddReloadListenerEvent event) { event.addListener(RecipeFinder.LISTENER); - event.addListener(PotatoProjectileTypeManager.ReloadListener.INSTANCE); event.addListener(BeltHelper.LISTENER); } - @SubscribeEvent - public static void onDatapackSync(OnDatapackSyncEvent event) { - ServerPlayer player = event.getPlayer(); - if (player != null) { - PotatoProjectileTypeManager.syncTo(player); - } else { - PotatoProjectileTypeManager.syncToAll(); - } - } - @SubscribeEvent public static void serverStopping(ServerStoppingEvent event) { Create.SCHEMATIC_RECEIVER.shutdown(); @@ -164,6 +155,7 @@ public class CommonEvents { Create.REDSTONE_LINK_NETWORK_HANDLER.onLoadWorld(world); Create.TORQUE_PROPAGATOR.onLoadWorld(world); Create.RAILWAYS.levelLoaded(world); + Create.LOGISTICS.levelLoaded(world); } @SubscribeEvent @@ -172,6 +164,7 @@ public class CommonEvents { Create.REDSTONE_LINK_NETWORK_HANDLER.onUnloadWorld(world); Create.TORQUE_PROPAGATOR.onUnloadWorld(world); WorldAttached.invalidateWorld(world); + CobbleGenOptimisation.invalidateWorld(world); } @SubscribeEvent @@ -201,19 +194,26 @@ public class CommonEvents { @SubscribeEvent public static void addPackFinders(AddPackFindersEvent event) { - if (event.getPackType() == PackType.CLIENT_RESOURCES) { - IModFileInfo modFileInfo = ModList.get().getModFileById(Create.ID); - if (modFileInfo == null) { - Create.LOGGER.error("Could not find Create mod file info; built-in resource packs will be missing!"); - return; - } - IModFile modFile = modFileInfo.getFile(); - event.addRepositorySource(consumer -> { - Pack pack = Pack.readMetaAndCreate(Create.asResource("legacy_copper").toString(), Components.literal("Create Legacy Copper"), false, id -> new ModFilePackResources(id, modFile, "resourcepacks/legacy_copper"), PackType.CLIENT_RESOURCES, Pack.Position.TOP, PackSource.BUILT_IN); - if (pack != null) { - consumer.accept(pack); - } - }); + // Uncomment and rename pack to add built in resource packs +// if (event.getPackType() == PackType.CLIENT_RESOURCES) { +// IModFileInfo modFileInfo = ModList.get().getModFileById(Create.ID); +// if (modFileInfo == null) { +// Create.LOGGER.error("Could not find Create mod file info; built-in resource packs will be missing!"); +// return; +// } +// IModFile modFile = modFileInfo.getFile(); +// event.addRepositorySource(consumer -> { +// Pack pack = Pack.readMetaAndCreate(Create.asResource("legacy_copper").toString(), Component.literal("Create Legacy Copper"), false, id -> new ModFilePackResources(id, modFile, "resourcepacks/legacy_copper"), PackType.CLIENT_RESOURCES, Pack.Position.TOP, PackSource.BUILT_IN); +// if (pack != null) { +// consumer.accept(pack); +// } +// }); +// } + + if (event.getPackType() == PackType.SERVER_DATA) { + DynamicPack dynamicPack = new DynamicPack("create:dynamic_data", PackType.SERVER_DATA); + RuntimeDataGenerator.insertIntoPack(dynamicPack); + event.addRepositorySource(new DynamicPackSource("create:dynamic_data", PackType.SERVER_DATA, Pack.Position.BOTTOM, dynamicPack)); } } } diff --git a/src/main/java/com/simibubi/create/foundation/events/InputEvents.java b/src/main/java/com/simibubi/create/foundation/events/InputEvents.java index f5a524fcb9..2d75de0d3c 100644 --- a/src/main/java/com/simibubi/create/foundation/events/InputEvents.java +++ b/src/main/java/com/simibubi/create/foundation/events/InputEvents.java @@ -2,7 +2,13 @@ package com.simibubi.create.foundation.events; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.elevator.ElevatorControlsHandler; +import com.simibubi.create.content.contraptions.wrench.RadialWrenchHandler; import com.simibubi.create.content.equipment.toolbox.ToolboxHandlerClient; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorConnectionHandler; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorInteractionHandler; +import com.simibubi.create.content.kinetics.chainConveyor.ChainPackageInteractionHandler; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelConnectionHandler; +import com.simibubi.create.content.logistics.packagePort.PackagePortTargetSelectionHandler; import com.simibubi.create.content.redstone.link.controller.LinkedControllerClientHandler; import com.simibubi.create.content.trains.TrainHUD; import com.simibubi.create.content.trains.entity.TrainRelocator; @@ -13,6 +19,7 @@ import net.minecraft.client.Minecraft; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber(Dist.CLIENT) @@ -28,6 +35,7 @@ public class InputEvents { CreateClient.SCHEMATIC_HANDLER.onKeyInput(key, pressed); ToolboxHandlerClient.onKeyInput(key, pressed); + RadialWrenchHandler.onKeyInput(key, pressed); } @SubscribeEvent @@ -75,6 +83,12 @@ public class InputEvents { event.setCanceled(true); } + if (key == mc.options.keyUse + && (FactoryPanelConnectionHandler.onRightClick() || ChainConveyorConnectionHandler.onRightClick())) { + event.setCanceled(true); + return; + } + if (key == mc.options.keyPickItem) { if (ToolboxHandlerClient.onPickItem()) event.setCanceled(true); @@ -86,6 +100,19 @@ public class InputEvents { LinkedControllerClientHandler.deactivateInLectern(); TrainRelocator.onClicked(event); + + if (ChainConveyorInteractionHandler.onUse()) { + event.setCanceled(true); + return; + } else if (PackagePortTargetSelectionHandler.onUse()) { + event.setCanceled(true); + return; + } + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + if (ChainPackageInteractionHandler.onUse()) + event.setCanceled(true); + }); } } diff --git a/src/main/java/com/simibubi/create/foundation/fluid/CombinedTankWrapper.java b/src/main/java/com/simibubi/create/foundation/fluid/CombinedTankWrapper.java index a04d735312..cdd0af69dd 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/CombinedTankWrapper.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/CombinedTankWrapper.java @@ -1,7 +1,6 @@ package com.simibubi.create.foundation.fluid; -import com.simibubi.create.foundation.utility.Iterate; - +import net.createmod.catnip.data.Iterate; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.wrapper.EmptyHandler; diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java index 7e47daee68..6eb95f42f4 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java @@ -11,9 +11,9 @@ import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; import com.simibubi.create.content.fluids.transfer.GenericItemFilling; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.data.Pair; import net.minecraft.nbt.TagParser; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; @@ -133,7 +133,7 @@ public class FluidHelper { public static JsonElement serializeFluidStack(FluidStack stack) { JsonObject json = new JsonObject(); - json.addProperty("fluid", RegisteredObjects.getKeyOrThrow(stack.getFluid()) + json.addProperty("fluid", CatnipServices.REGISTRIES.getKeyOrThrow(stack.getFluid()) .toString()); json.addProperty("amount", stack.getAmount()); if (stack.hasTag()) diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java index 5672f1b83e..e2d86eac92 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidIngredient.java @@ -2,7 +2,6 @@ package com.simibubi.create.foundation.fluid; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -13,8 +12,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; -import com.simibubi.create.foundation.utility.RegisteredObjects; +import net.createmod.catnip.platform.CatnipServices; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -23,6 +22,7 @@ import net.minecraft.tags.TagKey; import net.minecraft.util.GsonHelper; import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.material.Fluid; + import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.registries.ForgeRegistries; @@ -183,7 +183,7 @@ public abstract class FluidIngredient implements Predicate { @Override protected void writeInternal(JsonObject json) { - json.addProperty("fluid", RegisteredObjects.getKeyOrThrow(fluid) + json.addProperty("fluid", CatnipServices.REGISTRIES.getKeyOrThrow(fluid) .toString()); json.add("nbt", JsonParser.parseString(tagToMatch.toString())); } diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java index 423008240f..4ec0142619 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java @@ -3,26 +3,19 @@ package com.simibubi.create.foundation.fluid; import java.util.function.Function; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.PoseStack.Pose; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.foundation.render.RenderTypes; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; import dev.engine_room.flywheel.lib.transform.TransformStack; +import net.createmod.catnip.render.BasicFluidRenderer; +import net.createmod.catnip.math.AngleHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.core.Vec3i; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; @@ -30,11 +23,7 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidType; @OnlyIn(Dist.CLIENT) -public class FluidRenderer { - - public static VertexConsumer getFluidBuilder(MultiBufferSource buffer) { - return buffer.getBuffer(RenderTypes.fluid()); - } +public class FluidRenderer extends BasicFluidRenderer { public static void renderFluidStream(FluidStack fluidStack, Direction direction, float radius, float progress, boolean inbound, MultiBufferSource buffer, PoseStack ms, int light) { @@ -87,149 +76,9 @@ public class FluidRenderer { ms.popPose(); } - public static void renderFluidBox(FluidStack fluidStack, float xMin, float yMin, float zMin, float xMax, float yMax, - float zMax, MultiBufferSource buffer, PoseStack ms, int light, boolean renderBottom) { - renderFluidBox(fluidStack, xMin, yMin, zMin, xMax, yMax, zMax, getFluidBuilder(buffer), ms, light, - renderBottom); - } - - public static void renderFluidBox(FluidStack fluidStack, float xMin, float yMin, float zMin, float xMax, float yMax, - float zMax, VertexConsumer builder, PoseStack ms, int light, boolean renderBottom) { - Fluid fluid = fluidStack.getFluid(); - IClientFluidTypeExtensions clientFluid = IClientFluidTypeExtensions.of(fluid); - FluidType fluidAttributes = fluid.getFluidType(); - TextureAtlasSprite fluidTexture = Minecraft.getInstance() - .getTextureAtlas(InventoryMenu.BLOCK_ATLAS) - .apply(clientFluid.getStillTexture(fluidStack)); - - int color = clientFluid.getTintColor(fluidStack); - int blockLightIn = (light >> 4) & 0xF; - int luminosity = Math.max(blockLightIn, fluidAttributes.getLightLevel(fluidStack)); - light = (light & 0xF00000) | luminosity << 4; - - Vec3 center = new Vec3(xMin + (xMax - xMin) / 2, yMin + (yMax - yMin) / 2, zMin + (zMax - zMin) / 2); - ms.pushPose(); - if (fluidAttributes.isLighterThanAir()) - TransformStack.of(ms) - .translate(center) - .rotateXDegrees(180) - .translateBack(center); - - for (Direction side : Iterate.directions) { - if (side == Direction.DOWN && !renderBottom) - continue; - - boolean positive = side.getAxisDirection() == AxisDirection.POSITIVE; - if (side.getAxis() - .isHorizontal()) { - if (side.getAxis() == Axis.X) { - renderStillTiledFace(side, zMin, yMin, zMax, yMax, positive ? xMax : xMin, builder, ms, light, - color, fluidTexture); - } else { - renderStillTiledFace(side, xMin, yMin, xMax, yMax, positive ? zMax : zMin, builder, ms, light, - color, fluidTexture); - } - } else { - renderStillTiledFace(side, xMin, zMin, xMax, zMax, positive ? yMax : yMin, builder, ms, light, color, - fluidTexture); - } - } - - ms.popPose(); - } - - public static void renderStillTiledFace(Direction dir, float left, float down, float right, float up, float depth, - VertexConsumer builder, PoseStack ms, int light, int color, TextureAtlasSprite texture) { - FluidRenderer.renderTiledFace(dir, left, down, right, up, depth, builder, ms, light, color, texture, 1); - } - - public static void renderFlowingTiledFace(Direction dir, float left, float down, float right, float up, float depth, - VertexConsumer builder, PoseStack ms, int light, int color, TextureAtlasSprite texture) { - FluidRenderer.renderTiledFace(dir, left, down, right, up, depth, builder, ms, light, color, texture, 0.5f); - } - - public static void renderTiledFace(Direction dir, float left, float down, float right, float up, float depth, - VertexConsumer builder, PoseStack ms, int light, int color, TextureAtlasSprite texture, float textureScale) { - boolean positive = dir.getAxisDirection() == Direction.AxisDirection.POSITIVE; - boolean horizontal = dir.getAxis() - .isHorizontal(); - boolean x = dir.getAxis() == Axis.X; - - float shrink = texture.uvShrinkRatio() * 0.25f * textureScale; - float centerU = texture.getU0() + (texture.getU1() - texture.getU0()) * 0.5f * textureScale; - float centerV = texture.getV0() + (texture.getV1() - texture.getV0()) * 0.5f * textureScale; - - float f; - float x2 = 0; - float y2 = 0; - float u1, u2; - float v1, v2; - for (float x1 = left; x1 < right; x1 = x2) { - f = Mth.floor(x1); - x2 = Math.min(f + 1, right); - if (dir == Direction.NORTH || dir == Direction.EAST) { - f = Mth.ceil(x2); - u1 = texture.getU((f - x2) * 16 * textureScale); - u2 = texture.getU((f - x1) * 16 * textureScale); - } else { - u1 = texture.getU((x1 - f) * 16 * textureScale); - u2 = texture.getU((x2 - f) * 16 * textureScale); - } - u1 = Mth.lerp(shrink, u1, centerU); - u2 = Mth.lerp(shrink, u2, centerU); - for (float y1 = down; y1 < up; y1 = y2) { - f = Mth.floor(y1); - y2 = Math.min(f + 1, up); - if (dir == Direction.UP) { - v1 = texture.getV((y1 - f) * 16 * textureScale); - v2 = texture.getV((y2 - f) * 16 * textureScale); - } else { - f = Mth.ceil(y2); - v1 = texture.getV((f - y2) * 16 * textureScale); - v2 = texture.getV((f - y1) * 16 * textureScale); - } - v1 = Mth.lerp(shrink, v1, centerV); - v2 = Mth.lerp(shrink, v2, centerV); - - if (horizontal) { - if (x) { - putVertex(builder, ms, depth, y2, positive ? x2 : x1, color, u1, v1, dir, light); - putVertex(builder, ms, depth, y1, positive ? x2 : x1, color, u1, v2, dir, light); - putVertex(builder, ms, depth, y1, positive ? x1 : x2, color, u2, v2, dir, light); - putVertex(builder, ms, depth, y2, positive ? x1 : x2, color, u2, v1, dir, light); - } else { - putVertex(builder, ms, positive ? x1 : x2, y2, depth, color, u1, v1, dir, light); - putVertex(builder, ms, positive ? x1 : x2, y1, depth, color, u1, v2, dir, light); - putVertex(builder, ms, positive ? x2 : x1, y1, depth, color, u2, v2, dir, light); - putVertex(builder, ms, positive ? x2 : x1, y2, depth, color, u2, v1, dir, light); - } - } else { - putVertex(builder, ms, x1, depth, positive ? y1 : y2, color, u1, v1, dir, light); - putVertex(builder, ms, x1, depth, positive ? y2 : y1, color, u1, v2, dir, light); - putVertex(builder, ms, x2, depth, positive ? y2 : y1, color, u2, v2, dir, light); - putVertex(builder, ms, x2, depth, positive ? y1 : y2, color, u2, v1, dir, light); - } - } - } - } - - private static void putVertex(VertexConsumer builder, PoseStack ms, float x, float y, float z, int color, float u, - float v, Direction face, int light) { - - Vec3i normal = face.getNormal(); - Pose peek = ms.last(); - int a = color >> 24 & 0xff; - int r = color >> 16 & 0xff; - int g = color >> 8 & 0xff; - int b = color & 0xff; - - builder.vertex(peek.pose(), x, y, z) - .color(r, g, b, a) - .uv(u, v) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(light) - .normal(peek.normal(), normal.getX(), normal.getY(), normal.getZ()) - .endVertex(); + public static void renderFlowingTiledFace(Direction dir, float left, float down, float right, float up, + float depth, VertexConsumer builder, PoseStack ms, int light, int color, TextureAtlasSprite texture) { + renderTiledFace(dir, left, down, right, up, depth, builder, ms, light, color, texture, 0.5f); } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java deleted file mode 100644 index 5c8a3a302b..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.simibubi.create.foundation.gui; - -import java.util.Collection; -import java.util.List; - -import com.mojang.blaze3d.platform.InputConstants; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.AbstractWidget; -import net.minecraft.client.gui.components.EditBox; -import net.minecraft.client.gui.components.Renderable; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.narration.NarratableEntry; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@OnlyIn(Dist.CLIENT) -public abstract class AbstractSimiScreen extends Screen { - - protected int windowWidth, windowHeight; - protected int windowXOffset, windowYOffset; - protected int guiLeft, guiTop; - - protected AbstractSimiScreen(Component title) { - super(title); - } - - protected AbstractSimiScreen() { - this(Components.immutableEmpty()); - } - - /** - * This method must be called before {@code super.init()}! - */ - protected void setWindowSize(int width, int height) { - windowWidth = width; - windowHeight = height; - } - - /** - * This method must be called before {@code super.init()}! - */ - protected void setWindowOffset(int xOffset, int yOffset) { - windowXOffset = xOffset; - windowYOffset = yOffset; - } - - @Override - protected void init() { - guiLeft = (width - windowWidth) / 2; - guiTop = (height - windowHeight) / 2; - guiLeft += windowXOffset; - guiTop += windowYOffset; - } - - @Override - public void tick() { - for (GuiEventListener listener : children()) { - if (listener instanceof TickableGuiEventListener tickable) { - tickable.tick(); - } - } - } - - @Override - public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { - if (getFocused() != null && !getFocused().isMouseOver(pMouseX, pMouseY)) - setFocused(null); - return super.mouseClicked(pMouseX, pMouseY, pButton); - } - - @Override - public boolean isPauseScreen() { - return false; - } - - @SuppressWarnings("unchecked") - protected void addRenderableWidgets(W... widgets) { - for (W widget : widgets) { - addRenderableWidget(widget); - } - } - - protected void addRenderableWidgets(Collection widgets) { - for (W widget : widgets) { - addRenderableWidget(widget); - } - } - - protected void removeWidgets(GuiEventListener... widgets) { - for (GuiEventListener widget : widgets) { - removeWidget(widget); - } - } - - protected void removeWidgets(Collection widgets) { - for (GuiEventListener widget : widgets) { - removeWidget(widget); - } - } - - @Override - public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - partialTicks = minecraft.getFrameTime(); - PoseStack ms = graphics.pose(); - - ms.pushPose(); - - prepareFrame(); - - renderWindowBackground(graphics, mouseX, mouseY, partialTicks); - renderWindow(graphics, mouseX, mouseY, partialTicks); - super.render(graphics, mouseX, mouseY, partialTicks); - renderWindowForeground(graphics, mouseX, mouseY, partialTicks); - - endFrame(); - - ms.popPose(); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - boolean keyPressed = super.keyPressed(keyCode, scanCode, modifiers); - if (keyPressed || getFocused() instanceof EditBox) - return keyPressed; - - InputConstants.Key mouseKey = InputConstants.getKey(keyCode, scanCode); - if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) { - this.onClose(); - return true; - } - - return false; - } - - protected void prepareFrame() {} - - protected void renderWindowBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - renderBackground(graphics); - } - - protected abstract void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks); - - protected void renderWindowForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - for (Renderable widget : renderables) { - if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isMouseOver(mouseX, mouseY) - && simiWidget.visible) { - List tooltip = simiWidget.getToolTip(); - if (tooltip.isEmpty()) - continue; - int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.getX(); - int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.getY(); - graphics.renderComponentTooltip(font, tooltip, ttx, tty); - } - } - } - - protected void endFrame() {} - - @Deprecated - protected void debugWindowArea(GuiGraphics graphics) { - graphics.fill(guiLeft + windowWidth, guiTop + windowHeight, guiLeft, guiTop, 0xD3D3D3D3); - } - - @Override - public GuiEventListener getFocused() { - GuiEventListener focused = super.getFocused(); - if (focused instanceof AbstractWidget && !((AbstractWidget) focused).isFocused()) - focused = null; - setFocused(focused); - return focused; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java index 06bf6274fa..f899d35872 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -1,16 +1,17 @@ package com.simibubi.create.foundation.gui; -import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.Create; -import com.simibubi.create.foundation.gui.element.ScreenElement; -import com.simibubi.create.foundation.utility.Color; +import net.createmod.catnip.gui.TextureSheetSegment; +import net.createmod.catnip.gui.UIRenderHelper; +import net.createmod.catnip.gui.element.ScreenElement; +import net.createmod.catnip.theme.Color; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -public enum AllGuiTextures implements ScreenElement { +public enum AllGuiTextures implements ScreenElement, TextureSheetSegment { // Inventories PLAYER_INVENTORY("player_inventory", 176, 108), @@ -23,13 +24,14 @@ public enum AllGuiTextures implements ScreenElement { CURSEFORGE_LOGO("platform_icons/curseforge", 256, 256), MODRINTH_LOGO("platform_icons/modrinth", 256, 256), - SCHEMATIC("schematics", 192, 121), + SCHEMATIC("schematics", 10, 8, 192, 123), + SCHEMATIC_TITLE("schematics_2", 205, 15), SCHEMATIC_SLOT("widgets", 54, 0, 16, 16), - SCHEMATIC_PROMPT("schematics_2", 213, 77), + SCHEMATIC_PROMPT("schematics_2", 213, 79), HUD_BACKGROUND("overlay", 0, 0, 16, 16), - SCHEMATIC_TABLE("schematics", 0, 121, 214, 83), - SCHEMATIC_TABLE_PROGRESS("schematics", 0, 204, 84, 16), + SCHEMATIC_TABLE("schematics", 10, 139, 214, 85), + SCHEMATIC_TABLE_PROGRESS("schematics", 10, 224, 84, 16), SCHEMATICANNON_TOP("schematics_2", 0, 77, 213, 42), SCHEMATICANNON_BOTTOM("schematics_2", 0, 119, 213, 99), @@ -39,16 +41,20 @@ public enum AllGuiTextures implements ScreenElement { SCHEMATICANNON_FUEL("schematics_2", 28, 222, 47, 16), SCHEMATICANNON_FUEL_CREATIVE("schematics_2", 28, 239, 47, 16), - STOCKSWITCH("logistics", 182, 95), - STOCKSWITCH_ARROW_UP("logistics", 191, 0, 7, 24), - STOCKSWITCH_ARROW_DOWN("logistics", 198, 0, 7, 24), - STOCKSWITCH_CURSOR("logistics", 206, 0, 7, 16), - STOCKSWITCH_INTERVAL("logistics", 0, 95, 100, 18), - STOCKSWITCH_UNPOWERED_LANE("logistics", 37, 20, 100, 18), - STOCKSWITCH_POWERED_LANE("logistics", 37, 42, 100, 18), + THRESHOLD_SWITCH("threshold_switch", 182, 103), + THRESHOLD_SWITCH_ITEMCOUNT_INPUTS("threshold_switch", 0, 105, 115, 22), + THRESHOLD_SWITCH_MISC_INPUTS("threshold_switch", 0, 129, 115, 22), + THRESHOLD_SWITCH_CURRENT_STATE("threshold_switch", 0, 153, 24, 24), FILTER("filters", 214, 99), ATTRIBUTE_FILTER("filters", 0, 99, 241, 85), + PACKAGE_FILTER("filters_2", 0, 0, 218, 79), + + POSTBOX_HEADER("frogport_and_mailbox", 0, 23, 214, 24), + FROGPORT_HEADER("frogport_and_mailbox", 0, 0, 214, 17), + FROGPORT_SLOT("frogport_and_mailbox", 26, 55, 18, 18), + FROGPORT_EDIT_NAME("frogport_and_mailbox", 230, 3, 13, 13), + FROGPORT_BG("frogport_and_mailbox", 0, 47, 220, 82), TOOLBOX("toolbox", 188, 171), TOOLBELT_SLOT("minecraft", "widgets", 24, 23, 22, 22), @@ -71,8 +77,10 @@ public enum AllGuiTextures implements ScreenElement { LINKED_CONTROLLER("curiosities_2", 179, 109), BLUEPRINT("curiosities_2", 0, 109, 179, 109), - + CLIPBOARD("clipboard", 0, 0, 256, 256), + CLIPBOARD_ADDRESS("widgets", 116, 7, 8, 8), + CLIPBOARD_ADDRESS_INACTIVE("widgets", 125, 7, 8, 8), DATA_GATHERER("display_link", 235, 162), DATA_AREA_START("display_link", 0, 163, 2, 18), @@ -122,7 +130,7 @@ public enum AllGuiTextures implements ScreenElement { I_NEW_TRAIN("schedule_2", 14, 239, 24, 16), I_DISASSEMBLE_TRAIN("schedule_2", 39, 239, 24, 16), I_ASSEMBLE_TRAIN("schedule_2", 64, 239, 24, 16), - + ELEVATOR_CONTACT("display_link", 20, 172, 233, 82), BRASS_FRAME_TL("value_settings", 65, 9, 4, 4), @@ -133,7 +141,7 @@ public enum AllGuiTextures implements ScreenElement { BRASS_FRAME_RIGHT("value_settings", 71, 14, 3, 4), BRASS_FRAME_TOP("value_settings", 0, 24, 256, 3), BRASS_FRAME_BOTTOM("value_settings", 0, 27, 256, 3), - + VALUE_SETTINGS_MILESTONE("value_settings", 0, 0, 7, 8), VALUE_SETTINGS_WIDE_MILESTONE("value_settings", 75, 14, 13, 8), VALUE_SETTINGS_BAR("value_settings", 7, 0, 249, 8), @@ -144,7 +152,49 @@ public enum AllGuiTextures implements ScreenElement { VALUE_SETTINGS_CURSOR_RIGHT("value_settings", 61, 9, 3, 14), VALUE_SETTINGS_CURSOR_ICON("value_settings", 0, 44, 22, 20), VALUE_SETTINGS_LABEL_BG("value_settings", 0, 31, 81, 11), - + + // HILO + FACTORY_GAUGE_RECIPE("factory_gauge", 32, 0, 192, 96), + FACTORY_GAUGE_RESTOCK("factory_gauge", 32, 112, 192, 40), + FACTORY_GAUGE_BOTTOM("factory_gauge", 32, 176, 200, 64), + FACTORY_GAUGE_SET_ITEM("requester", 16, 160, 184, 88), + + STOCK_KEEPER_REQUEST_HEADER("stock_keeper", 0, 0, 256, 36), + STOCK_KEEPER_REQUEST_BODY("stock_keeper", 0, 48, 256, 20), + STOCK_KEEPER_REQUEST_FOOTER("stock_keeper", 0, 80, 256, 80), + STOCK_KEEPER_REQUEST_SEARCH("stock_keeper", 57, 17, 142, 18), + STOCK_KEEPER_REQUEST_SAYS("stock_keeper", 4, 163, 8, 16), + STOCK_KEEPER_REQUEST_LOCKED("stock_keeper", 16, 176, 15, 16), + STOCK_KEEPER_REQUEST_UNLOCKED("stock_keeper", 32, 176, 15, 16), + STOCK_KEEPER_REQUEST_SLOT("stock_keeper", 32, 200, 18, 18), + STOCK_KEEPER_REQUEST_BLUEPRINT_LEFT("stock_keeper", 28, 220, 10, 25), + STOCK_KEEPER_REQUEST_BLUEPRINT_MIDDLE("stock_keeper", 38, 220, 4, 25), + STOCK_KEEPER_REQUEST_BLUEPRINT_RIGHT("stock_keeper", 42, 220, 10, 25), + STOCK_KEEPER_REQUEST_SEND_HOVER("stock_keeper", 55, 200, 80, 20), + STOCK_KEEPER_REQUEST_SCROLL_TOP("stock_keeper", 219, 192, 5, 4), + STOCK_KEEPER_REQUEST_SCROLL_PAD("stock_keeper", 219, 196, 5, 1), + STOCK_KEEPER_REQUEST_SCROLL_MID("stock_keeper", 219, 197, 5, 9), + STOCK_KEEPER_REQUEST_SCROLL_BOT("stock_keeper", 219, 207, 5, 5), + STOCK_KEEPER_REQUEST_BANNER_L("stock_keeper", 64, 228, 8, 16), + STOCK_KEEPER_REQUEST_BANNER_M("stock_keeper", 73, 228, 1, 16), + STOCK_KEEPER_REQUEST_BANNER_R("stock_keeper", 75, 228, 8, 16), + STOCK_KEEPER_REQUEST_BG("stock_keeper", 37, 48, 182, 20), + STOCK_KEEPER_CATEGORY_HIDDEN("stock_keeper", 143, 176, 8, 8), + STOCK_KEEPER_CATEGORY_SHOWN("stock_keeper", 151, 176, 8, 8), + NUMBERS("stock_keeper", 48, 176, 5, 8), + + STOCK_KEEPER_CATEGORY("stock_keeper_categories", 32, 32, 192, 20), + STOCK_KEEPER_CATEGORY_SAYS("stock_keeper_categories", 238, 86, 14, 20), + STOCK_KEEPER_CATEGORY_HEADER("stock_keeper_categories", 32, 0, 192, 18), + STOCK_KEEPER_CATEGORY_EDIT("stock_keeper_categories", 32, 208, 192, 38), + STOCK_KEEPER_CATEGORY_FOOTER("stock_keeper_categories", 32, 79, 200, 33), + STOCK_KEEPER_CATEGORY_NEW("stock_keeper_categories", 38, 127, 27, 18), + STOCK_KEEPER_CATEGORY_ENTRY("stock_keeper_categories", 38, 159, 171, 18), + STOCK_KEEPER_CATEGORY_UP("stock_keeper_categories", 211, 160, 8, 8), + STOCK_KEEPER_CATEGORY_DOWN("stock_keeper_categories", 211, 169, 8, 8), + + REDSTONE_REQUESTER("requester", 16, 16, 232, 120), + // JEI JEI_SLOT("jei/widgets", 18, 18), JEI_CHANCE_SLOT("jei/widgets", 20, 156, 18, 18), @@ -163,6 +213,8 @@ public enum AllGuiTextures implements ScreenElement { BUTTON("widgets", 18, 18), BUTTON_HOVER("widgets", 18, 0, 18, 18), BUTTON_DOWN("widgets", 36, 0, 18, 18), + BUTTON_GREEN("widgets", 72, 0, 18, 18), + BUTTON_DISABLED("widgets", 90, 0, 18, 18), INDICATOR("widgets", 0, 18, 18, 6), INDICATOR_WHITE("widgets", 18, 18, 18, 6), INDICATOR_GREEN("widgets", 36, 18, 18, 6), @@ -170,6 +222,7 @@ public enum AllGuiTextures implements ScreenElement { INDICATOR_RED("widgets", 72, 18, 18, 6), HOTSLOT_ARROW("widgets", 24, 51, 20, 12), + HOTSLOT_ARROW_BAD("widgets", 52, 51, 20, 15), HOTSLOT("widgets", 0, 68, 22, 22), HOTSLOT_ACTIVE("widgets", 0, 46, 22, 22), HOTSLOT_SUPER_ACTIVE("widgets", 27, 67, 24, 24), @@ -187,9 +240,11 @@ public enum AllGuiTextures implements ScreenElement { TRAIN_PROMPT_R("widgets", 11, 209, 3, 16), TRAIN_PROMPT("widgets", 0, 230, 256, 16), + TRADE_OVERLAY("widgets", 128, 98, 96, 46), + // PlacementIndicator PLACEMENT_INDICATOR_SHEET("placement_indicator", 0, 0, 16, 256), - + // Train Map TRAINMAP_SPRITES("trainmap_sprite_sheet", 0, 0, 512, 256), TRAINMAP_SIGNAL("widgets", 81, 156, 5, 10), @@ -197,10 +252,10 @@ public enum AllGuiTextures implements ScreenElement { TRAINMAP_STATION_DIAGO("widgets", 56, 156, 5, 5), TRAINMAP_STATION_ORTHO_HIGHLIGHT("widgets", 63, 156, 7, 7), TRAINMAP_STATION_DIAGO_HIGHLIGHT("widgets", 72, 156, 7, 7), - - TRAINMAP_TOGGLE_PANEL("widgets", 166, 74, 33, 14), - TRAINMAP_TOGGLE_ON("widgets", 166, 89, 12, 7), - TRAINMAP_TOGGLE_OFF("widgets", 166, 97, 12, 7), + + TRAINMAP_TOGGLE_PANEL("widgets", 219, 4, 33, 14), + TRAINMAP_TOGGLE_ON("widgets", 219, 19, 12, 7), + TRAINMAP_TOGGLE_OFF("widgets", 219, 27, 12, 7), // ComputerCraft COMPUTER("computer", 200, 102); @@ -210,22 +265,20 @@ public enum AllGuiTextures implements ScreenElement { public static final int FONT_COLOR = 0x575F7A; public final ResourceLocation location; - public int width, height; - public int startX, startY; + private final int width; + private final int height; + private final int startX; + private final int startY; - private AllGuiTextures(String location, int width, int height) { + AllGuiTextures(String location, int width, int height) { this(location, 0, 0, width, height); } - private AllGuiTextures(int startX, int startY) { - this("icons", startX * 16, startY * 16, 16, 16); - } - - private AllGuiTextures(String location, int startX, int startY, int width, int height) { + AllGuiTextures(String location, int startX, int startY, int width, int height) { this(Create.ID, location, startX, startY, width, height); } - private AllGuiTextures(String namespace, String location, int startX, int startY, int width, int height) { + AllGuiTextures(String namespace, String location, int startX, int startY, int width, int height) { this.location = new ResourceLocation(namespace, "textures/gui/" + location + ".png"); this.width = width; this.height = height; @@ -233,9 +286,9 @@ public enum AllGuiTextures implements ScreenElement { this.startY = startY; } - @OnlyIn(Dist.CLIENT) - public void bind() { - RenderSystem.setShaderTexture(0, location); + @Override + public ResourceLocation getLocation() { + return location; } @OnlyIn(Dist.CLIENT) @@ -249,4 +302,23 @@ public enum AllGuiTextures implements ScreenElement { UIRenderHelper.drawColoredTexture(graphics, c, x, y, startX, startY, width, height); } + @Override + public int getStartX() { + return startX; + } + + @Override + public int getStartY() { + return startY; + } + + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java index 16e40d34b9..4f3e21c031 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java @@ -6,10 +6,10 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.Create; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.gui.element.ScreenElement; -import com.simibubi.create.foundation.utility.Color; +import net.createmod.catnip.gui.element.DelegatedStencilElement; +import net.createmod.catnip.gui.element.ScreenElement; +import net.createmod.catnip.theme.Color; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; @@ -105,7 +105,7 @@ public class AllIcons implements ScreenElement { I_ADD_INVERTED_ATTRIBUTE = next(), I_FLIP = next(), - + I_ROLLER_PAVE = next(), I_ROLLER_FILL = next(), I_ROLLER_WIDE_FILL = next(), @@ -128,7 +128,7 @@ public class AllIcons implements ScreenElement { I_PATTERN_CHANCE_75 = next(), I_FOLLOW_DIAGONAL = next(), I_FOLLOW_MATERIAL = next(), - + I_CLEAR_CHECKED = next(), I_SCHEMATIC = newRow(), @@ -161,7 +161,13 @@ public class AllIcons implements ScreenElement { I_FX_FIELD_OFF = next(), I_FX_FIELD_ON = next(), I_FX_BLEND = next(), - I_FX_BLEND_OFF = next(); + I_FX_BLEND_OFF = next(), + + I_SEND_ONLY = newRow(), + I_SEND_AND_RECEIVE = next(), + I_PARTIAL_REQUESTS = next(), + I_FULL_REQUESTS = next(), + I_MOVE_GAUGE = next(); ; public AllIcons(int x, int y) { diff --git a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java deleted file mode 100644 index 60a35ad34a..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.simibubi.create.foundation.gui; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import javax.annotation.Nonnull; - -import org.lwjgl.opengl.GL30; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.gui.element.BoxElement; -import com.simibubi.create.foundation.gui.element.TextStencilElement; -import com.simibubi.create.foundation.gui.widget.BoxWidget; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.FormattedText; -import net.minecraft.network.chat.Style; - -public class ConfirmationScreen extends AbstractSimiScreen { - - private Screen source; - private Consumer action = _success -> { - }; - private List text = new ArrayList<>(); - private boolean centered = false; - private int x; - private int y; - private int textWidth; - private int textHeight; - private boolean tristate; - - private BoxWidget confirm; - private BoxWidget confirmDontSave; - private BoxWidget cancel; - private BoxElement textBackground; - - public enum Response { - Confirm, ConfirmDontSave, Cancel - } - - /* - * Removes text lines from the back of the list - * */ - public ConfirmationScreen removeTextLines(int amount) { - if (amount > text.size()) - return clearText(); - - text.subList(text.size() - amount, text.size()).clear(); - return this; - } - - public ConfirmationScreen clearText() { - this.text.clear(); - return this; - } - - public ConfirmationScreen addText(FormattedText text) { - this.text.add(text); - return this; - } - - public ConfirmationScreen withText(FormattedText text) { - return clearText().addText(text); - } - - public ConfirmationScreen at(int x, int y) { - this.x = Math.max(x, 0); - this.y = Math.max(y, 0); - this.centered = false; - return this; - } - - public ConfirmationScreen centered() { - this.centered = true; - return this; - } - - public ConfirmationScreen withAction(Consumer action) { - this.action = r -> action.accept(r == Response.Confirm); - return this; - } - - public ConfirmationScreen withThreeActions(Consumer action) { - this.action = action; - this.tristate = true; - return this; - } - - public void open(@Nonnull Screen source) { - this.source = source; - Minecraft client = source.getMinecraft(); - this.init(client, client.getWindow().getGuiScaledWidth(), client.getWindow().getGuiScaledHeight()); - this.minecraft.screen = this; - } - - @Override - public void tick() { - super.tick(); - source.tick(); - } - - @Override - protected void init() { - super.init(); - - ArrayList copy = new ArrayList<>(text); - text.clear(); - copy.forEach(t -> text.addAll(font.getSplitter().splitLines(t, 300, Style.EMPTY))); - - textHeight = text.size() * (font.lineHeight + 1) + 4; - textWidth = 300; - - if (centered) { - x = width/2 - textWidth/2 - 2; - y = height/2 - textHeight/2 - 16; - } else { - x = Math.max(0, x - textWidth / 2); - y = Math.max(0, y -= textHeight); - } - - if (x + textWidth > width) { - x = width - textWidth; - } - - if (y + textHeight + 30 > height) { - y = height - textHeight - 30; - } - - int buttonX = x + textWidth / 2 - 6 - (int) (70 * (tristate ? 1.5f : 1)); - - TextStencilElement confirmText = - new TextStencilElement(font, tristate ? "Save" : "Confirm").centered(true, true); - confirm = new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.Confirm)); - confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm))); - addRenderableWidget(confirm); - - buttonX += 12 + 70; - - if (tristate) { - TextStencilElement confirmDontSaveText = - new TextStencilElement(font, "Don't Save").centered(true, true); - confirmDontSave = - new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.ConfirmDontSave)); - confirmDontSave.showingElement( - confirmDontSaveText.withElementRenderer(BoxWidget.gradientFactory.apply(confirmDontSave))); - addRenderableWidget(confirmDontSave); - buttonX += 12 + 70; - } - - TextStencilElement cancelText = new TextStencilElement(font, "Cancel").centered(true, true); - cancel = new BoxWidget(buttonX, y + textHeight + 6, 70, 16) - .withCallback(() -> accept(Response.Cancel)); - cancel.showingElement(cancelText.withElementRenderer(BoxWidget.gradientFactory.apply(cancel))); - addRenderableWidget(cancel); - - textBackground = new BoxElement() - .gradientBorder(Theme.p(Theme.Key.BUTTON_DISABLE)) - .withBounds(width + 10, textHeight + 35) - .at(-5, y - 5); - - if (text.size() == 1) - x = (width - font.width(text.get(0))) / 2; - } - - @Override - public void onClose() { - accept(Response.Cancel); - } - - private void accept(Response success) { - minecraft.screen = source; - action.accept(success); - } - - @Override - protected void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - textBackground.render(graphics); - int offset = font.lineHeight + 1; - int lineY = y - offset; - - PoseStack ms = graphics.pose(); - ms.pushPose(); - ms.translate(0, 0, 200); - - for (FormattedText line : text) { - lineY += offset; - if (line == null) - continue; - graphics.drawString(font, line.getString(), x, lineY, 0xeaeaea, false); - } - - ms.popPose(); - } - - @Override - protected void renderWindowBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - endFrame(); - - source.render(graphics, 0, 0, 10); // zero mouse coords to prevent further tooltips - - prepareFrame(); - - graphics.fillGradient(0, 0, this.width, this.height, 0x70101010, 0x80101010); - } - - - @Override - protected void prepareFrame() { - UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer); - RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); - } - - @Override - protected void endFrame() { - UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget()); - } - - @Override - public void resize(@Nonnull Minecraft client, int width, int height) { - super.resize(client, width, height); - source.resize(client, width, height); - } - - @Override - public boolean isPauseScreen() { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/CustomLightingSettings.java b/src/main/java/com/simibubi/create/foundation/gui/CustomLightingSettings.java index 86f8bbb28a..0568a4f6d8 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/CustomLightingSettings.java +++ b/src/main/java/com/simibubi/create/foundation/gui/CustomLightingSettings.java @@ -5,6 +5,8 @@ import org.joml.Vector3f; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.math.Axis; +import net.createmod.catnip.gui.ILightingSettings; + public class CustomLightingSettings implements ILightingSettings { private Vector3f light1; diff --git a/src/main/java/com/simibubi/create/foundation/gui/ILightingSettings.java b/src/main/java/com/simibubi/create/foundation/gui/ILightingSettings.java deleted file mode 100644 index 045d6c97ea..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/ILightingSettings.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.simibubi.create.foundation.gui; - -import com.mojang.blaze3d.platform.Lighting; - -public interface ILightingSettings { - - void applyLighting(); - - static final ILightingSettings DEFAULT_3D = () -> Lighting.setupFor3DItems(); - static final ILightingSettings DEFAULT_FLAT = () -> Lighting.setupForFlatItems(); - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLine.java b/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLine.java index 2c732418fb..825e4e337b 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLine.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLine.java @@ -6,9 +6,10 @@ import java.util.function.Consumer; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.TooltipArea; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.gui.UIRenderHelper; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.EditBox; diff --git a/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLineBuilder.java b/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLineBuilder.java index dd3a525bd7..f36f1ecf7d 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLineBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ModularGuiLineBuilder.java @@ -6,12 +6,12 @@ import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; import com.simibubi.create.foundation.gui.widget.TooltipArea; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.data.Pair; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.components.EditBox; +import net.minecraft.network.chat.CommonComponents; public class ModularGuiLineBuilder { @@ -28,14 +28,14 @@ public class ModularGuiLineBuilder { } public ModularGuiLineBuilder addScrollInput(int x, int width, BiConsumer inputTransform, - String dataKey) { + String dataKey) { ScrollInput input = new ScrollInput(x + this.x, y - 4, width, 18); addScrollInput(input, inputTransform, dataKey); return this; } public ModularGuiLineBuilder addSelectionScrollInput(int x, int width, - BiConsumer inputTransform, String dataKey) { + BiConsumer inputTransform, String dataKey) { SelectionScrollInput input = new SelectionScrollInput(x + this.x, y - 4, width, 18); addScrollInput(input, inputTransform, dataKey); return this; @@ -52,7 +52,7 @@ public class ModularGuiLineBuilder { } private void addScrollInput(T input, BiConsumer inputTransform, String dataKey) { - Label label = new Label(input.getX() + 5, y, Components.immutableEmpty()); + Label label = new Label(input.getX() + 5, y, CommonComponents.EMPTY); label.withShadow(); inputTransform.accept(input, label); input.writingTo(label); @@ -61,7 +61,7 @@ public class ModularGuiLineBuilder { } public ModularGuiLineBuilder addIntegerTextInput(int x, int width, BiConsumer inputTransform, - String dataKey) { + String dataKey) { return addTextInput(x, width, inputTransform.andThen((editBox, $) -> editBox.setFilter(s -> { if (s.isEmpty()) return true; @@ -75,8 +75,8 @@ public class ModularGuiLineBuilder { } public ModularGuiLineBuilder addTextInput(int x, int width, BiConsumer inputTransform, - String dataKey) { - EditBox input = new EditBox(font, x + this.x + 5, y, width - 9, 8, Components.immutableEmpty()); + String dataKey) { + EditBox input = new EditBox(font, x + this.x + 5, y, width - 9, 8, CommonComponents.EMPTY); input.setBordered(false); input.setTextColor(0xffffff); input.setFocused(false); diff --git a/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java b/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java deleted file mode 100644 index 3d1b6f05f7..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.simibubi.create.foundation.gui; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.List; -import java.util.Optional; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.ponder.ui.NavigatableSimiScreen; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; - -public class ScreenOpener { - - private static final Deque backStack = new ArrayDeque<>(); - private static Screen backSteppedFrom = null; - - public static void open(Screen screen) { - open(Minecraft.getInstance().screen, screen); - } - - public static void open(@Nullable Screen current, Screen toOpen) { - backSteppedFrom = null; - if (current != null) { - if (backStack.size() >= 15) // don't go deeper than 15 steps - backStack.pollLast(); - - backStack.push(current); - } else - backStack.clear(); - - openScreen(toOpen); - } - - public static void openPreviousScreen(Screen current, Optional screenWithContext) { - if (backStack.isEmpty()) - return; - backSteppedFrom = current; - Screen previousScreen = backStack.pop(); - if (previousScreen instanceof NavigatableSimiScreen) { - NavigatableSimiScreen previousAbstractSimiScreen = (NavigatableSimiScreen) previousScreen; - screenWithContext.ifPresent(s -> s.shareContextWith(previousAbstractSimiScreen)); - previousAbstractSimiScreen.transition.startWithValue(-0.1) - .chase(-1, .4f, LerpedFloat.Chaser.EXP); - } - openScreen(previousScreen); - } - - // transitions are only supported in simiScreens atm. they take care of all the - // rendering for it - public static void transitionTo(NavigatableSimiScreen screen) { - if (tryBackTracking(screen)) - return; - screen.transition.startWithValue(0.1) - .chase(1, .4f, LerpedFloat.Chaser.EXP); - open(screen); - } - - private static boolean tryBackTracking(NavigatableSimiScreen screen) { - List screenHistory = getScreenHistory(); - if (screenHistory.isEmpty()) - return false; - Screen previouslyRenderedScreen = screenHistory.get(0); - if (!(previouslyRenderedScreen instanceof NavigatableSimiScreen)) - return false; - if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen)) - return false; - - openPreviousScreen(Minecraft.getInstance().screen, Optional.of(screen)); - return true; - } - - public static void clearStack() { - backStack.clear(); - } - - public static List getScreenHistory() { - return new ArrayList<>(backStack); - } - - @Nullable - public static Screen getPreviouslyRenderedScreen() { - return backSteppedFrom != null ? backSteppedFrom : backStack.peek(); - } - - private static void openScreen(Screen screen) { - Minecraft.getInstance() - .tell(() -> { - Minecraft.getInstance() - .setScreen(screen); - Screen previouslyRenderedScreen = getPreviouslyRenderedScreen(); - if (previouslyRenderedScreen != null && screen instanceof NavigatableSimiScreen) - previouslyRenderedScreen.init(Minecraft.getInstance(), screen.width, screen.height); - }); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/ScreenWithStencils.java b/src/main/java/com/simibubi/create/foundation/gui/ScreenWithStencils.java new file mode 100644 index 0000000000..e104992dbd --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/ScreenWithStencils.java @@ -0,0 +1,41 @@ +package com.simibubi.create.foundation.gui; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL30; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; + +public interface ScreenWithStencils { + + default void startStencil(GuiGraphics graphics, float x, float y, float w, float h) { + RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); + + GL11.glDisable(GL11.GL_STENCIL_TEST); + RenderSystem.stencilMask(~0); + RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX); + GL11.glEnable(GL11.GL_STENCIL_TEST); + RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP); + RenderSystem.stencilMask(0xFF); + RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF); + + PoseStack matrixStack = graphics.pose(); + matrixStack.pushPose(); + matrixStack.translate(x, y, 0); + matrixStack.scale(w, h, 1); + graphics.fillGradient(0, 0, 1, 1, -100, 0xff000000, 0xff000000); + matrixStack.popPose(); + + GL11.glEnable(GL11.GL_STENCIL_TEST); + RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF); + } + + default void endStencil() { + GL11.glDisable(GL11.GL_STENCIL_TEST); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/Theme.java b/src/main/java/com/simibubi/create/foundation/gui/Theme.java deleted file mode 100644 index ad21e7223b..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/Theme.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.simibubi.create.foundation.gui; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; - -public class Theme { - - private static final List THEMES = new ArrayList<>(); - public static final Theme BASE = addTheme(new Theme()); - - public static Theme addTheme(@Nonnull Theme theme) { - THEMES.add(theme); - THEMES.sort(Comparator.comparingInt(Theme::getPriority).reversed()); - return theme; - } - - public static void removeTheme(Theme theme) { - THEMES.remove(theme); - } - - public static void reload() { - THEMES.forEach(Theme::init); - } - - private static ColorHolder resolve(String key) { - return THEMES - .stream() - .map(theme -> theme.get(key)) - .filter(Objects::nonNull) - .findFirst() - .map(holder -> holder.lookupKey == null ? holder : resolve(holder.lookupKey)) - .orElse(ColorHolder.MISSING); - } - - @Nonnull public static Couple p(@Nonnull Key key) {return p(key.get());} - @Nonnull public static Couple p(String key) {return resolve(key).asPair();} - - @Nonnull public static Color c(@Nonnull Key key, boolean first) {return c(key.get(), first);} - @Nonnull public static Color c(String key, boolean first) {return p(key).get(first);} - - public static int i(@Nonnull Key key, boolean first) {return i(key.get(), first);} - public static int i(String key, boolean first) {return p(key).get(first).getRGB();} - - @Nonnull public static Color c(@Nonnull Key key) {return c(key.get());} - @Nonnull public static Color c(String key) {return resolve(key).get();} - - public static int i(@Nonnull Key key) {return i(key.get());} - public static int i(String key) {return resolve(key).get().getRGB();} - - //-----------// - - protected final Map colors; - private int priority = 0; - - protected Theme() { - colors = new HashMap<>(); - init(); - } - - /* - * Small note to addons: if you also want to make use of Theme, - * and add new Keys, please do not use mixins. Instead make a Theme - * subclass, override init and apply it via the static #addTheme - * - **/ - - protected void init() { - put(Key.BUTTON_IDLE, new Color(0xdd_8ab6d6, true), new Color(0x90_8ab6d6, true)); - put(Key.BUTTON_HOVER, new Color(0xff_9ABBD3, true), new Color(0xd0_9ABBD3, true)); - put(Key.BUTTON_CLICK, new Color(0xff_ffffff), new Color(0xee_ffffff)); - put(Key.BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x60_909090, true)); - put(Key.BUTTON_SUCCESS, new Color(0xcc_88f788, true), new Color(0xcc_20cc20, true)); - put(Key.BUTTON_FAIL, new Color(0xcc_f78888, true), new Color(0xcc_cc2020, true)); - put(Key.TEXT, new Color(0xff_eeeeee), new Color(0xff_a3a3a3)); - put(Key.TEXT_DARKER, new Color(0xff_a3a3a3), new Color(0xff_808080)); - put(Key.TEXT_ACCENT_STRONG, new Color(0xff_8ab6d6), new Color(0xff_8ab6d6)); - put(Key.TEXT_ACCENT_SLIGHT, new Color(0xff_ddeeff), new Color(0xff_a0b0c0)); - put(Key.STREAK, new Color(0x101010, false)); - put(Key.VANILLA_TOOLTIP_BORDER, new Color(0x50_5000ff, true), new Color(0x50_28007f, true)); - put(Key.VANILLA_TOOLTIP_BACKGROUND, new Color(0xf0_100010, true)); - - put(Key.PONDER_BUTTON_IDLE, new Color(0x60_c0c0ff, true), new Color(0x30_c0c0ff, true)); - put(Key.PONDER_BUTTON_HOVER, new Color(0xf0_c0c0ff, true), new Color(0xa0_c0c0ff, true)); - put(Key.PONDER_BUTTON_CLICK, new Color(0xff_ffffff), new Color(0xdd_ffffff)); - put(Key.PONDER_BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x20_909090, true)); - put(Key.PONDER_BACKGROUND_TRANSPARENT, new Color(0xdd_000000, true)); - put(Key.PONDER_BACKGROUND_FLAT, new Color(0xff_000000, false)); - put(Key.PONDER_BACKGROUND_IMPORTANT, new Color(0xdd_0e0e20, true)); - put(Key.PONDER_IDLE, new Color(0x40ffeedd, true), new Color(0x20ffeedd, true)); - put(Key.PONDER_HOVER, new Color(0x70ffffff, true), new Color(0x30ffffff, true)); - put(Key.PONDER_HIGHLIGHT, new Color(0xf0ffeedd, true), new Color(0x60ffeedd, true)); - put(Key.TEXT_WINDOW_BORDER, new Color(0x607a6000, true), new Color(0x207a6000, true)); - put(Key.PONDER_BACK_ARROW, new Color(0xf0aa9999, true), new Color(0x30aa9999, true)); - put(Key.PONDER_PROGRESSBAR, new Color(0x80ffeedd, true), new Color(0x50ffeedd, true)); - put(Key.PONDER_MISSING_CREATE, new Color(0x70_984500, true), new Color(0x70_692400, true)); - //put(Key.PONDER_MISSING_VANILLA, new Color(0x50_5000ff, true), new Color(0x50_300077, true)); - lookup(Key.PONDER_MISSING_VANILLA, Key.VANILLA_TOOLTIP_BORDER); - put(Key.CONFIG_TITLE_A, new Color(0xffc69fbc, true), new Color(0xfff6b8bb, true)); - put(Key.CONFIG_TITLE_B, new Color(0xfff6b8bb, true), new Color(0xfffbf994, true)); - //put(Key., new Color(0x, true), new Color(0x, true)); - } - - protected void put(String key, Color c) { - colors.put(key, ColorHolder.single(c)); - } - - protected void put(Key key, Color c) { - put(key.get(), c); - } - - protected void put(String key, Color c1, Color c2) { - colors.put(key, ColorHolder.pair(c1, c2)); - } - - protected void put(Key key, Color c1, Color c2) { - put(key.get(), c1, c2); - } - - protected void lookup(Key key, Key source) { - colors.put(key.get(), ColorHolder.lookup(source.get())); - } - - @Nullable protected ColorHolder get(String key) { - return colors.get(key); - } - - public int getPriority() { - return priority; - } - - public Theme setPriority(int priority) { - this.priority = priority; - return this; - } - - public static class Key { - - public static final Key BUTTON_IDLE = new Key(); - public static final Key BUTTON_HOVER = new Key(); - public static final Key BUTTON_CLICK = new Key(); - public static final Key BUTTON_DISABLE = new Key(); - public static final Key BUTTON_SUCCESS = new Key(); - public static final Key BUTTON_FAIL = new Key(); - - public static final Key TEXT = new Key(); - public static final Key TEXT_DARKER = new Key(); - public static final Key TEXT_ACCENT_STRONG = new Key(); - public static final Key TEXT_ACCENT_SLIGHT = new Key(); - - public static final Key STREAK = new Key(); - public static final Key VANILLA_TOOLTIP_BORDER = new Key(); - public static final Key VANILLA_TOOLTIP_BACKGROUND = new Key(); - - public static final Key PONDER_BACKGROUND_TRANSPARENT = new Key(); - public static final Key PONDER_BACKGROUND_FLAT = new Key(); - public static final Key PONDER_BACKGROUND_IMPORTANT = new Key(); - public static final Key PONDER_IDLE = new Key(); - public static final Key PONDER_HOVER = new Key(); - public static final Key PONDER_HIGHLIGHT = new Key(); - public static final Key TEXT_WINDOW_BORDER = new Key(); - public static final Key PONDER_BACK_ARROW = new Key(); - public static final Key PONDER_PROGRESSBAR = new Key(); - public static final Key PONDER_MISSING_CREATE = new Key(); - public static final Key PONDER_MISSING_VANILLA = new Key(); - - public static final Key PONDER_BUTTON_IDLE = new Key(); - public static final Key PONDER_BUTTON_HOVER = new Key(); - public static final Key PONDER_BUTTON_CLICK = new Key(); - public static final Key PONDER_BUTTON_DISABLE = new Key(); - - public static final Key CONFIG_TITLE_A = new Key(); - public static final Key CONFIG_TITLE_B = new Key(); - - private static int index = 0; - - private final String s; - - protected Key() { - this.s = "_" + index++; - } - - protected Key(String s) { - this.s = s; - } - - public String get() { - return s; - } - } - - private static class ColorHolder { - - private static final ColorHolder MISSING = ColorHolder.single(Color.BLACK); - - private Couple colors; - private String lookupKey; - - private static ColorHolder single(Color c) { - ColorHolder h = new ColorHolder(); - h.colors = Couple.create(c.setImmutable(), c.setImmutable()); - return h; - } - - private static ColorHolder pair(Color first, Color second) { - ColorHolder h = new ColorHolder(); - h.colors = Couple.create(first.setImmutable(), second.setImmutable()); - return h; - } - - private static ColorHolder lookup(String key) { - ColorHolder h = new ColorHolder(); - h.lookupKey = key; - return h; - } - - private Color get() { - return colors.getFirst(); - } - - private Couple asPair() { - return colors; - } - - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/TickableGuiEventListener.java b/src/main/java/com/simibubi/create/foundation/gui/TickableGuiEventListener.java deleted file mode 100644 index 898760fb28..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/TickableGuiEventListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.foundation.gui; - -import net.minecraft.client.gui.components.events.GuiEventListener; - -public interface TickableGuiEventListener extends GuiEventListener { - void tick(); -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java deleted file mode 100644 index 3b29daf1d5..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java +++ /dev/null @@ -1,329 +0,0 @@ -package com.simibubi.create.foundation.gui; - -import org.joml.Matrix4f; -import org.lwjgl.opengl.GL20; -import org.lwjgl.opengl.GL30; - -import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.platform.GlConst; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexFormat; -import com.mojang.math.Axis; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.GameRenderer; - -public class UIRenderHelper { - - /** - * An FBO that has a stencil buffer for use wherever stencil are necessary. Forcing the main FBO to have a stencil - * buffer will cause GL error spam when using fabulous graphics. - */ - public static CustomRenderTarget framebuffer; - - public static void init() { - RenderSystem.recordRenderCall(() -> { - Window mainWindow = Minecraft.getInstance().getWindow(); - framebuffer = CustomRenderTarget.create(mainWindow); - }); - } - - public static void updateWindowSize(Window mainWindow) { - if (framebuffer != null) - framebuffer.resize(mainWindow.getWidth(), mainWindow.getHeight(), Minecraft.ON_OSX); - } - - public static void drawFramebuffer(float alpha) { - framebuffer.renderWithAlpha(alpha); - } - - /** - * Switch from src to dst, after copying the contents of src to dst. - */ - public static void swapAndBlitColor(RenderTarget src, RenderTarget dst) { - GlStateManager._glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, src.frameBufferId); - GlStateManager._glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, dst.frameBufferId); - GlStateManager._glBlitFrameBuffer(0, 0, src.viewWidth, src.viewHeight, 0, 0, dst.viewWidth, dst.viewHeight, GL30.GL_COLOR_BUFFER_BIT, GL20.GL_LINEAR); - - GlStateManager._glBindFramebuffer(GlConst.GL_FRAMEBUFFER, dst.frameBufferId); - } - - public static void streak(GuiGraphics graphics, float angle, int x, int y, int breadth, int length) { - streak(graphics, angle, x, y, breadth, length, Theme.i(Theme.Key.STREAK)); - } - // angle in degrees; 0° -> fading to the right - // x and y specify the middle point of the starting edge - // breadth is the total width of the streak - - public static void streak(GuiGraphics graphics, float angle, int x, int y, int breadth, int length, int color) { - int a1 = 0xa0 << 24; - int a2 = 0x80 << 24; - int a3 = 0x10 << 24; - int a4 = 0x00 << 24; - - color &= 0x00FFFFFF; - int c1 = a1 | color; - int c2 = a2 | color; - int c3 = a3 | color; - int c4 = a4 | color; - - PoseStack ms = graphics.pose(); - ms.pushPose(); - ms.translate(x, y, 0); - ms.mulPose(Axis.ZP.rotationDegrees(angle - 90)); - - streak(graphics, breadth / 2, length, c1, c2, c3, c4); - - ms.popPose(); - } - - public static void streak(GuiGraphics graphics, float angle, int x, int y, int breadth, int length, Color c) { - Color color = c.copy().setImmutable(); - int c1 = color.scaleAlpha(0.625f).getRGB(); - int c2 = color.scaleAlpha(0.5f).getRGB(); - int c3 = color.scaleAlpha(0.0625f).getRGB(); - int c4 = color.scaleAlpha(0f).getRGB(); - - PoseStack ms = graphics.pose(); - ms.pushPose(); - ms.translate(x, y, 0); - ms.mulPose(Axis.ZP.rotationDegrees(angle - 90)); - - streak(graphics, breadth / 2, length, c1, c2, c3, c4); - - ms.popPose(); - } - - private static void streak(GuiGraphics graphics, int width, int height, int c1, int c2, int c3, int c4) { - double split1 = .5; - double split2 = .75; - graphics.fillGradient(-width, 0, width, (int) (split1 * height), 0, c1, c2); - graphics.fillGradient(-width, (int) (split1 * height), width, (int) (split2 * height), 0, c2, c3); - graphics.fillGradient(-width, (int) (split2 * height), width, height, 0, c3, c4); - } - - /** - * @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color) - */ - public static void angledGradient(GuiGraphics graphics, float angle, int x, int y, int breadth, int length, Couple c) { - angledGradient(graphics, angle, x, y, 0, breadth, length, c); - } - - /** - * @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color) - */ - public static void angledGradient(GuiGraphics graphics, float angle, int x, int y, int z, int breadth, int length, Couple c) { - angledGradient(graphics, angle, x, y, z, breadth, length, c.getFirst(), c.getSecond()); - } - - /** - * @see #angledGradient(MatrixStack, float, int, int, int, int, int, Color, Color) - */ - public static void angledGradient(GuiGraphics graphics, float angle, int x, int y, int breadth, int length, Color color1, Color color2) { - angledGradient(graphics, angle, x, y, 0, breadth, length, color1, color2); - } - - /** - * x and y specify the middle point of the starting edge - * - * @param angle the angle of the gradient in degrees; 0° means from left to right - * @param color1 the color at the starting edge - * @param color2 the color at the ending edge - * @param breadth the total width of the gradient - */ - public static void angledGradient(GuiGraphics graphics, float angle, int x, int y, int z, int breadth, int length, Color color1, Color color2) { - PoseStack ms = graphics.pose(); - ms.pushPose(); - ms.translate(x, y, z); - ms.mulPose(Axis.ZP.rotationDegrees(angle - 90)); - - int w = breadth / 2; - graphics.fillGradient(-w, 0, w, length, 0, color1.getRGB(), color2.getRGB()); - - ms.popPose(); - } - - public static void breadcrumbArrow(GuiGraphics graphics, int x, int y, int z, int width, int height, int indent, Couple colors) {breadcrumbArrow(graphics, x, y, z, width, height, indent, colors.getFirst(), colors.getSecond());} - - // draws a wide chevron-style breadcrumb arrow pointing left - public static void breadcrumbArrow(GuiGraphics graphics, int x, int y, int z, int width, int height, int indent, Color startColor, Color endColor) { - PoseStack matrixStack = graphics.pose(); - matrixStack.pushPose(); - matrixStack.translate(x - indent, y, z); - - breadcrumbArrow(graphics, width, height, indent, startColor, endColor); - - matrixStack.popPose(); - } - - private static void breadcrumbArrow(GuiGraphics graphics, int width, int height, int indent, Color c1, Color c2) { - - /* - * 0,0 x1,y1 ********************* x4,y4 ***** x7,y7 - * **** **** - * **** **** - * x0,y0 x2,y2 x5,y5 - * **** **** - * **** **** - * x3,y3 ********************* x6,y6 ***** x8,y8 - * - */ - - float x0 = 0, y0 = height / 2f; - float x1 = indent, y1 = 0; - float x2 = indent, y2 = height / 2f; - float x3 = indent, y3 = height; - float x4 = width, y4 = 0; - float x5 = width, y5 = height / 2f; - float x6 = width, y6 = height; - float x7 = indent + width, y7 = 0; - float x8 = indent + width, y8 = height; - - indent = Math.abs(indent); - width = Math.abs(width); - Color fc1 = Color.mixColors(c1, c2, 0); - Color fc2 = Color.mixColors(c1, c2, (indent) / (width + 2f * indent)); - Color fc3 = Color.mixColors(c1, c2, (indent + width) / (width + 2f * indent)); - Color fc4 = Color.mixColors(c1, c2, 1); - -// RenderSystem.disableTexture(); - RenderSystem.enableBlend(); - RenderSystem.disableCull(); - RenderSystem.defaultBlendFunc(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); - - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuilder(); - Matrix4f model = graphics.pose().last().pose(); - bufferbuilder.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION_COLOR); - - bufferbuilder.vertex(model, x0, y0, 0).color(fc1.getRed(), fc1.getGreen(), fc1.getBlue(), fc1.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x1, y1, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x2, y2, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - - bufferbuilder.vertex(model, x0, y0, 0).color(fc1.getRed(), fc1.getGreen(), fc1.getBlue(), fc1.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x2, y2, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - - bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x1, y1, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - - bufferbuilder.vertex(model, x3, y3, 0).color(fc2.getRed(), fc2.getGreen(), fc2.getBlue(), fc2.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x6, y6, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - - bufferbuilder.vertex(model, x5, y5, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x4, y4, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x7, y7, 0).color(fc4.getRed(), fc4.getGreen(), fc4.getBlue(), fc4.getAlpha()).endVertex(); - - bufferbuilder.vertex(model, x6, y6, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x5, y5, 0).color(fc3.getRed(), fc3.getGreen(), fc3.getBlue(), fc3.getAlpha()).endVertex(); - bufferbuilder.vertex(model, x8, y8, 0).color(fc4.getRed(), fc4.getGreen(), fc4.getBlue(), fc4.getAlpha()).endVertex(); - - tessellator.end(); - RenderSystem.enableCull(); - RenderSystem.disableBlend(); -// RenderSystem.enableTexture(); - } - - //just like AbstractGui#drawTexture, but with a color at every vertex - public static void drawColoredTexture(GuiGraphics graphics, Color c, int x, int y, int tex_left, int tex_top, int width, int height) { - drawColoredTexture(graphics, c, x, y, 0, (float) tex_left, (float) tex_top, width, height, 256, 256); - } - - public static void drawColoredTexture(GuiGraphics graphics, Color c, int x, int y, int z, float tex_left, float tex_top, int width, int height, int sheet_width, int sheet_height) { - drawColoredTexture(graphics, c, x, x + width, y, y + height, z, width, height, tex_left, tex_top, sheet_width, sheet_height); - } - - public static void drawStretched(GuiGraphics graphics, int left, int top, int w, int h, int z, AllGuiTextures tex) { - tex.bind(); - drawTexturedQuad(graphics.pose().last() - .pose(), Color.WHITE, left, left + w, top, top + h, z, tex.startX / 256f, (tex.startX + tex.width) / 256f, - tex.startY / 256f, (tex.startY + tex.height) / 256f); - } - - public static void drawCropped(GuiGraphics graphics, int left, int top, int w, int h, int z, AllGuiTextures tex) { - tex.bind(); - drawTexturedQuad(graphics.pose().last() - .pose(), Color.WHITE, left, left + w, top, top + h, z, tex.startX / 256f, (tex.startX + w) / 256f, - tex.startY / 256f, (tex.startY + h) / 256f); - } - - private static void drawColoredTexture(GuiGraphics graphics, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) { - drawTexturedQuad(graphics.pose().last().pose(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float) sheet_width, (tex_left + (float) tex_width) / (float) sheet_width, (tex_top + 0.0F) / (float) sheet_height, (tex_top + (float) tex_height) / (float) sheet_height); - } - - private static void drawTexturedQuad(Matrix4f m, Color c, int left, int right, int top, int bot, int z, float u1, float u2, float v1, float v2) { - Tesselator tesselator = Tesselator.getInstance(); - BufferBuilder bufferbuilder = tesselator.getBuilder(); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.setShader(GameRenderer::getPositionColorTexShader); - bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); - bufferbuilder.vertex(m, (float) left , (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v2).endVertex(); - bufferbuilder.vertex(m, (float) right, (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v2).endVertex(); - bufferbuilder.vertex(m, (float) right, (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v1).endVertex(); - bufferbuilder.vertex(m, (float) left , (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v1).endVertex(); - tesselator.end(); - RenderSystem.disableBlend(); - } - - public static void flipForGuiRender(PoseStack poseStack) { - poseStack.mulPoseMatrix(new Matrix4f().scaling(1, -1, 1)); - } - - public static class CustomRenderTarget extends RenderTarget { - - public CustomRenderTarget(boolean useDepth) { - super(useDepth); - } - - public static CustomRenderTarget create(Window mainWindow) { - CustomRenderTarget framebuffer = new CustomRenderTarget(true); - framebuffer.resize(mainWindow.getWidth(), mainWindow.getHeight(), Minecraft.ON_OSX); - framebuffer.setClearColor(0, 0, 0, 0); - framebuffer.enableStencil(); - return framebuffer; - } - - public void renderWithAlpha(float alpha) { - Window window = Minecraft.getInstance().getWindow(); - - float vx = (float) window.getGuiScaledWidth(); - float vy = (float) window.getGuiScaledHeight(); - float tx = (float) viewWidth / (float) width; - float ty = (float) viewHeight / (float) height; - -// RenderSystem.enableTexture(); - RenderSystem.enableDepthTest(); - RenderSystem.setShader(() -> Minecraft.getInstance().gameRenderer.blitShader); - RenderSystem.getShader().setSampler("DiffuseSampler", colorTextureId); - - bindRead(); - - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuilder(); - bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); - - bufferbuilder.vertex(0, vy, 0).color(1, 1, 1, alpha).uv(0, 0).endVertex(); - bufferbuilder.vertex(vx, vy, 0).color(1, 1, 1, alpha).uv(tx, 0).endVertex(); - bufferbuilder.vertex(vx, 0, 0).color(1, 1, 1, alpha).uv(tx, ty).endVertex(); - bufferbuilder.vertex(0, 0, 0).color(1, 1, 1, alpha).uv(0, ty).endVertex(); - - tessellator.end(); - unbindRead(); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/BoxElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/BoxElement.java deleted file mode 100644 index 61722e7a05..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/BoxElement.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import org.joml.Matrix4f; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexFormat; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.GameRenderer; - -public class BoxElement extends RenderElement { - - protected Color background = new Color(0xff000000, true); - protected Color borderTop = new Color(0x40ffeedd, true); - protected Color borderBot = new Color(0x20ffeedd, true); - protected int borderOffset = 2; - - public T withBackground(Color color) { - this.background = color; - //noinspection unchecked - return (T) this; - } - - public T withBackground(int color) { - return withBackground(new Color(color, true)); - } - - public T flatBorder(Color color) { - this.borderTop = color; - this.borderBot = color; - //noinspection unchecked - return (T) this; - } - - public T flatBorder(int color) { - return flatBorder(new Color(color, true)); - } - - public T gradientBorder(Couple colors) { - this.borderTop = colors.getFirst(); - this.borderBot = colors.getSecond(); - //noinspection unchecked - return (T) this; - } - - public T gradientBorder(Color top, Color bot) { - this.borderTop = top; - this.borderBot = bot; - //noinspection unchecked - return (T) this; - } - - public T gradientBorder(int top, int bot) { - return gradientBorder(new Color(top, true), new Color(bot, true)); - } - - public T withBorderOffset(int offset) { - this.borderOffset = offset; - //noinspection unchecked - return (T) this; - } - - @Override - public void render(GuiGraphics graphics) { - renderBox(graphics.pose()); - } - - //total box width = 1 * 2 (outer border) + 1 * 2 (inner color border) + 2 * borderOffset + width - //defaults to 2 + 2 + 4 + 16 = 24px - //batch everything together to save a bunch of gl calls over ScreenUtils - protected void renderBox(PoseStack ms) { - /* - * _____________ - * _|_____________|_ - * | | ___________ | | - * | | | | | | | - * | | | | | | | - * | | |--* | | | | - * | | | h | | | - * | | | --w-+ | | | - * | | | | | | - * | | |_________| | | - * |_|_____________|_| - * |_____________| - * - * */ -// RenderSystem.disableTexture(); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); - - Matrix4f model = ms.last().pose(); - int f = borderOffset; - Color c1 = background.copy().scaleAlpha(alpha); - Color c2 = borderTop.copy().scaleAlpha(alpha); - Color c3 = borderBot.copy().scaleAlpha(alpha); - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder b = tessellator.getBuilder(); - - b.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - //outer top - b.vertex(model, x - f - 1 , y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - //outer left - b.vertex(model, x - f - 2 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x - f - 2 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - //outer bottom - b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - //outer right - b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 2 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 2 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - //inner background - also render behind the inner edges - b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex(); - tessellator.end(); - b.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - //inner top - includes corners - b.vertex(model, x - f - 1 , y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - //inner left - excludes corners - b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - b.vertex(model, x - f , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - b.vertex(model, x - f , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - //inner bottom - includes corners - b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - //inner right - excludes corners - b.vertex(model, x + f + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - b.vertex(model, x + f + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex(); - b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex(); - - tessellator.end(); - - RenderSystem.disableBlend(); -// RenderSystem.enableTexture(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/CombinedStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/CombinedStencilElement.java deleted file mode 100644 index 0651dc2336..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/CombinedStencilElement.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import javax.annotation.Nonnull; - -import com.mojang.blaze3d.vertex.PoseStack; - -import net.minecraft.client.gui.GuiGraphics; - -public class CombinedStencilElement extends StencilElement { - - private StencilElement element1; - private StencilElement element2; - private ElementMode mode; - - private CombinedStencilElement() {} - - public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2) { - return of(element1, element2, ElementMode.FIRST); - } - - public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2, ElementMode mode) { - CombinedStencilElement e = new CombinedStencilElement(); - e.element1 = element1; - e.element2 = element2; - e.mode = mode; - return e; - } - - public T withFirst(StencilElement element) { - this.element1 = element; - //noinspection unchecked - return (T) this; - } - - public T withSecond(StencilElement element) { - this.element2 = element; - //noinspection unchecked - return (T) this; - } - - public T withMode(ElementMode mode) { - this.mode = mode; - //noinspection unchecked - return (T) this; - } - - @Override - protected void renderStencil(GuiGraphics graphics) { - PoseStack ms = graphics.pose(); - ms.pushPose(); - element1.transform(ms); - element1.withBounds(width, height); - element1.renderStencil(graphics); - ms.popPose(); - ms.pushPose(); - element2.transform(ms); - element2.withBounds(width, height); - element2.renderStencil(graphics); - ms.popPose(); - } - - @Override - protected void renderElement(GuiGraphics graphics) { - if (mode.rendersFirst()) - element1.withBounds(width, height).renderElement(graphics); - - if (mode.rendersSecond()) - element2.withBounds(width, height).renderElement(graphics); - } - - public enum ElementMode { - FIRST, SECOND, BOTH; - - boolean rendersFirst() { - return this == FIRST || this == BOTH; - } - - boolean rendersSecond() { - return this == SECOND || this == BOTH; - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/DelegatedStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/DelegatedStencilElement.java deleted file mode 100644 index 66bf3c5218..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/DelegatedStencilElement.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.utility.Color; - -import net.minecraft.client.gui.GuiGraphics; - -public class DelegatedStencilElement extends StencilElement { - - protected static final ElementRenderer EMPTY_RENDERER = (graphics, width, height, alpha) -> {}; - protected static final ElementRenderer DEFAULT_ELEMENT = (graphics, width, height, alpha) -> UIRenderHelper.angledGradient(graphics, 0, -3, 5, height+4, width+6, new Color(0xff_10dd10).scaleAlpha(alpha), new Color(0xff_1010dd).scaleAlpha(alpha)); - - protected ElementRenderer stencil; - protected ElementRenderer element; - - public DelegatedStencilElement() { - stencil = EMPTY_RENDERER; - element = DEFAULT_ELEMENT; - } - - public DelegatedStencilElement(ElementRenderer stencil, ElementRenderer element) { - this.stencil = stencil; - this.element = element; - } - - public T withStencilRenderer(ElementRenderer renderer) { - stencil = renderer; - //noinspection unchecked - return (T) this; - } - - public T withElementRenderer(ElementRenderer renderer) { - element = renderer; - //noinspection unchecked - return (T) this; - } - - @Override - protected void renderStencil(GuiGraphics graphics) { - stencil.render(graphics, width, height, 1); - } - - @Override - protected void renderElement(GuiGraphics graphics) { - element.render(graphics, width, height, alpha); - } - - @FunctionalInterface - public interface ElementRenderer { - void render(GuiGraphics graphics, int width, int height, float alpha); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/GuiGameElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/GuiGameElement.java deleted file mode 100644 index 568e0e08b9..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/GuiGameElement.java +++ /dev/null @@ -1,304 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import javax.annotation.Nullable; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.platform.GlStateManager.DestFactor; -import com.mojang.blaze3d.platform.GlStateManager.SourceFactor; -import com.mojang.blaze3d.platform.Lighting; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.gui.ILightingSettings; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.render.VirtualRenderHelper; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; - -import dev.engine_room.flywheel.lib.model.baked.PartialModel; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.Sheets; -import net.minecraft.client.renderer.block.BlockRenderDispatcher; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.util.RandomSource; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.block.BaseFireBlock; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LiquidBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.client.RenderTypeHelper; -import net.minecraftforge.fluids.FluidStack; - -public class GuiGameElement { - - public static GuiRenderBuilder of(ItemStack stack) { - return new GuiItemRenderBuilder(stack); - } - - public static GuiRenderBuilder of(ItemLike itemProvider) { - return new GuiItemRenderBuilder(itemProvider); - } - - public static GuiRenderBuilder of(BlockState state) { - return new GuiBlockStateRenderBuilder(state); - } - - public static GuiRenderBuilder of(PartialModel partial) { - return new GuiBlockPartialRenderBuilder(partial); - } - - public static GuiRenderBuilder of(Fluid fluid) { - return new GuiBlockStateRenderBuilder(fluid.defaultFluidState() - .createLegacyBlock() - .setValue(LiquidBlock.LEVEL, 0)); - } - - public static abstract class GuiRenderBuilder extends RenderElement { - protected double xLocal, yLocal, zLocal; - protected double xRot, yRot, zRot; - protected double scale = 1; - protected int color = 0xFFFFFF; - protected Vec3 rotationOffset = Vec3.ZERO; - protected ILightingSettings customLighting = null; - - public GuiRenderBuilder atLocal(double x, double y, double z) { - this.xLocal = x; - this.yLocal = y; - this.zLocal = z; - return this; - } - - public GuiRenderBuilder rotate(double xRot, double yRot, double zRot) { - this.xRot = xRot; - this.yRot = yRot; - this.zRot = zRot; - return this; - } - - public GuiRenderBuilder rotateBlock(double xRot, double yRot, double zRot) { - return this.rotate(xRot, yRot, zRot) - .withRotationOffset(VecHelper.getCenterOf(BlockPos.ZERO)); - } - - public GuiRenderBuilder scale(double scale) { - this.scale = scale; - return this; - } - - public GuiRenderBuilder color(int color) { - this.color = color; - return this; - } - - public GuiRenderBuilder withRotationOffset(Vec3 offset) { - this.rotationOffset = offset; - return this; - } - - public GuiRenderBuilder lighting(ILightingSettings lighting) { - customLighting = lighting; - return this; - } - - protected void prepareMatrix(PoseStack matrixStack) { - matrixStack.pushPose(); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.enableDepthTest(); - RenderSystem.enableBlend(); - RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); - prepareLighting(matrixStack); - } - - protected void transformMatrix(PoseStack matrixStack) { - matrixStack.translate(x, y, z); - matrixStack.scale((float) scale, (float) scale, (float) scale); - matrixStack.translate(xLocal, yLocal, zLocal); - UIRenderHelper.flipForGuiRender(matrixStack); - matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z); - matrixStack.mulPose(Axis.ZP.rotationDegrees((float) zRot)); - matrixStack.mulPose(Axis.XP.rotationDegrees((float) xRot)); - matrixStack.mulPose(Axis.YP.rotationDegrees((float) yRot)); - matrixStack.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z); - } - - protected void cleanUpMatrix(PoseStack matrixStack) { - matrixStack.popPose(); - cleanUpLighting(matrixStack); - } - - protected void prepareLighting(PoseStack matrixStack) { - if (customLighting != null) { - customLighting.applyLighting(); - } else { - Lighting.setupFor3DItems(); - } - } - - protected void cleanUpLighting(PoseStack matrixStack) { - if (customLighting != null) { - Lighting.setupFor3DItems(); - } - } - } - - private static class GuiBlockModelRenderBuilder extends GuiRenderBuilder { - - protected BakedModel blockModel; - protected BlockState blockState; - - public GuiBlockModelRenderBuilder(BakedModel blockmodel, @Nullable BlockState blockState) { - this.blockState = blockState == null ? Blocks.AIR.defaultBlockState() : blockState; - this.blockModel = blockmodel; - } - - @Override - public void render(GuiGraphics graphics) { - PoseStack matrixStack = graphics.pose(); - prepareMatrix(matrixStack); - - Minecraft mc = Minecraft.getInstance(); - BlockRenderDispatcher blockRenderer = mc.getBlockRenderer(); - MultiBufferSource.BufferSource buffer = graphics.bufferSource(); - - transformMatrix(matrixStack); - - RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); - renderModel(blockRenderer, buffer, matrixStack); - - cleanUpMatrix(matrixStack); - } - - protected void renderModel(BlockRenderDispatcher blockRenderer, MultiBufferSource.BufferSource buffer, - PoseStack ms) { - if (blockState.getBlock() == Blocks.AIR) { - RenderType renderType = Sheets.translucentCullBlockSheet(); - blockRenderer.getModelRenderer() - .renderModel(ms.last(), buffer.getBuffer(renderType), blockState, blockModel, 1, 1, 1, - LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, VirtualRenderHelper.VIRTUAL_DATA, null); - } else { - int color = Minecraft.getInstance() - .getBlockColors() - .getColor(blockState, null, null, 0); - Color rgb = new Color(color == -1 ? this.color : color); - - for (RenderType chunkType : blockModel.getRenderTypes(blockState, RandomSource.create(42L), VirtualRenderHelper.VIRTUAL_DATA)) { - RenderType renderType = RenderTypeHelper.getEntityRenderType(chunkType, true); - blockRenderer.getModelRenderer() - .renderModel(ms.last(), buffer.getBuffer(renderType), blockState, blockModel, - rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(), - LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, VirtualRenderHelper.VIRTUAL_DATA, chunkType); - } - } - - buffer.endBatch(); - } - - } - - public static class GuiBlockStateRenderBuilder extends GuiBlockModelRenderBuilder { - - public GuiBlockStateRenderBuilder(BlockState blockstate) { - super(Minecraft.getInstance() - .getBlockRenderer() - .getBlockModel(blockstate), blockstate); - } - - @Override - protected void renderModel(BlockRenderDispatcher blockRenderer, MultiBufferSource.BufferSource buffer, - PoseStack ms) { - if (blockState.getBlock() instanceof BaseFireBlock) { - Lighting.setupForFlatItems(); - super.renderModel(blockRenderer, buffer, ms); - Lighting.setupFor3DItems(); - return; - } - - super.renderModel(blockRenderer, buffer, ms); - - if (blockState.getFluidState() - .isEmpty()) - return; - - FluidRenderer.renderFluidBox(new FluidStack(blockState.getFluidState() - .getType(), 1000), 0, 0, 0, 1, 1, 1, buffer, ms, LightTexture.FULL_BRIGHT, false); - buffer.endBatch(); - } - } - - public static class GuiBlockPartialRenderBuilder extends GuiBlockModelRenderBuilder { - - public GuiBlockPartialRenderBuilder(PartialModel partial) { - super(partial.get(), null); - } - - } - - public static class GuiItemRenderBuilder extends GuiRenderBuilder { - - private final ItemStack stack; - - public GuiItemRenderBuilder(ItemStack stack) { - this.stack = stack; - } - - public GuiItemRenderBuilder(ItemLike provider) { - this(new ItemStack(provider)); - } - - @Override - public void render(GuiGraphics graphics) { - PoseStack matrixStack = graphics.pose(); - prepareMatrix(matrixStack); - transformMatrix(matrixStack); - renderItemIntoGUI(graphics, matrixStack, stack, customLighting == null); - cleanUpMatrix(matrixStack); - } - - public static void renderItemIntoGUI(GuiGraphics graphics, PoseStack matrixStack, ItemStack stack, boolean useDefaultLighting) { - ItemRenderer renderer = Minecraft.getInstance().getItemRenderer(); - BakedModel bakedModel = renderer.getModel(stack, null, null, 0); - - renderer.textureManager.getTexture(InventoryMenu.BLOCK_ATLAS).setFilter(false, false); - RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); - RenderSystem.enableBlend(); - RenderSystem.enableCull(); - RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - matrixStack.pushPose(); - matrixStack.translate(0, 0, 100.0F); - matrixStack.translate(8.0F, -8.0F, 0.0F); - matrixStack.scale(16.0F, 16.0F, 16.0F); - MultiBufferSource.BufferSource buffer = graphics.bufferSource(); - boolean flatLighting = !bakedModel.usesBlockLight(); - if (useDefaultLighting && flatLighting) { - Lighting.setupForFlatItems(); - } - - renderer.render(stack, ItemDisplayContext.GUI, false, matrixStack, buffer, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, bakedModel); - RenderSystem.disableDepthTest(); - buffer.endBatch(); - - RenderSystem.enableDepthTest(); - if (useDefaultLighting && flatLighting) { - Lighting.setupFor3DItems(); - } - - matrixStack.popPose(); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/RenderElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/RenderElement.java deleted file mode 100644 index a7829631f3..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/RenderElement.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import net.minecraft.client.gui.GuiGraphics; - -public abstract class RenderElement implements ScreenElement { - - public static final RenderElement EMPTY = new RenderElement() { - @Override - public void render(GuiGraphics graphics) { - } - }; - - public static RenderElement of(ScreenElement renderable) { - return new SimpleRenderElement(renderable); - } - - protected int width = 16, height = 16; - protected float x = 0, y = 0, z = 0; - protected float alpha = 1f; - - public T at(float x, float y) { - this.x = x; - this.y = y; - //noinspection unchecked - return (T) this; - } - - public T at(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - //noinspection unchecked - return (T) this; - } - - public T withBounds(int width, int height) { - this.width = width; - this.height = height; - //noinspection unchecked - return (T) this; - } - - public T withAlpha(float alpha) { - this.alpha = alpha; - //noinspection unchecked - return (T) this; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public float getX() { - return x; - } - - public float getY() { - return y; - } - - public float getZ() { - return z; - } - - public abstract void render(GuiGraphics graphics); - - @Override - public void render(GuiGraphics graphics, int x, int y) { - this.at(x, y).render(graphics); - } - - public static class SimpleRenderElement extends RenderElement { - - private ScreenElement renderable; - - public SimpleRenderElement(ScreenElement renderable) { - this.renderable = renderable; - } - - @Override - public void render(GuiGraphics graphics) { - renderable.render(graphics, (int) x, (int) y); - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/ScreenElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/ScreenElement.java deleted file mode 100644 index 72c334fea6..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/ScreenElement.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public interface ScreenElement { - - @OnlyIn(Dist.CLIENT) - void render(GuiGraphics graphics, int x, int y); - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/StencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/StencilElement.java deleted file mode 100644 index 6807858ef9..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/StencilElement.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import org.lwjgl.opengl.GL11; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; - -public abstract class StencilElement extends RenderElement { - - @Override - public void render(GuiGraphics graphics) { - PoseStack ms = graphics.pose(); - ms.pushPose(); - transform(ms); - prepareStencil(ms); - renderStencil(graphics); - prepareElement(ms); - renderElement(graphics); - cleanUp(ms); - ms.popPose(); - } - - protected abstract void renderStencil(GuiGraphics graphics); - - protected abstract void renderElement(GuiGraphics graphics); - - protected void transform(PoseStack ms) { - ms.translate(x, y, z); - } - - protected void prepareStencil(PoseStack ms) { - GL11.glDisable(GL11.GL_STENCIL_TEST); - RenderSystem.stencilMask(~0); - RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX); - GL11.glEnable(GL11.GL_STENCIL_TEST); - RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP); - RenderSystem.stencilMask(0xFF); - RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF); - } - - protected void prepareElement(PoseStack ms) { - GL11.glEnable(GL11.GL_STENCIL_TEST); - RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); - RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF); - } - - protected void cleanUp(PoseStack ms) { - GL11.glDisable(GL11.GL_STENCIL_TEST); - - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/element/TextStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/element/TextStencilElement.java deleted file mode 100644 index 1bd90d0824..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/element/TextStencilElement.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.simibubi.create.foundation.gui.element; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.chat.MutableComponent; - -public class TextStencilElement extends DelegatedStencilElement { - - protected Font font; - protected MutableComponent component; - protected boolean centerVertically = false; - protected boolean centerHorizontally = false; - - public TextStencilElement(Font font) { - super(); - this.font = font; - height = 10; - } - - public TextStencilElement(Font font, String text) { - this(font); - component = Components.literal(text); - } - - public TextStencilElement(Font font, MutableComponent component) { - this(font); - this.component = component; - } - - public TextStencilElement withText(String text) { - component = Components.literal(text); - return this; - } - - public TextStencilElement withText(MutableComponent component) { - this.component = component; - return this; - } - - public TextStencilElement centered(boolean vertical, boolean horizontal) { - this.centerVertically = vertical; - this.centerHorizontally = horizontal; - return this; - } - - @Override - protected void renderStencil(GuiGraphics graphics) { - float x = 0, y = 0; - if (centerHorizontally) - x = width / 2f - font.width(component) / 2f; - - if (centerVertically) - y = height / 2f - (font.lineHeight - 1) / 2f; - - graphics.drawString(font, component, Math.round(x), Math.round(y), 0xff_000000, false); - } - - @Override - protected void renderElement(GuiGraphics graphics) { - float x = 0, y = 0; - if (centerHorizontally) - x = width / 2f - font.width(component) / 2f; - - if (centerVertically) - y = height / 2f - (font.lineHeight - 1) / 2f; - - PoseStack ms = graphics.pose(); - ms.pushPose(); - ms.translate(x, y, 0); - element.render(graphics, font.width(component), font.lineHeight + 2, alpha); - ms.popPose(); - } - - public MutableComponent getComponent() { - return component; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/menu/AbstractSimiContainerScreen.java b/src/main/java/com/simibubi/create/foundation/gui/menu/AbstractSimiContainerScreen.java index af8a5c4722..63e33eef1d 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/menu/AbstractSimiContainerScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/AbstractSimiContainerScreen.java @@ -6,11 +6,13 @@ import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; -import com.mojang.blaze3d.platform.InputConstants; -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.TickableGuiEventListener; -import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; +import org.lwjgl.glfw.GLFW; +import com.simibubi.create.foundation.gui.AllGuiTextures; + +import net.createmod.catnip.gui.TickableGuiEventListener; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.EditBox; @@ -20,7 +22,9 @@ import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.client.renderer.Rect2i; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvent; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraftforge.api.distmarker.Dist; @@ -137,19 +141,18 @@ public abstract class AbstractSimiContainerScreen extends MenuBase implements IClearable ghostInventory.setStackInSlot(slot, insert); getSlot(slotId).setChanged(); } + + @Override + protected boolean moveItemStackTo(ItemStack pStack, int pStartIndex, int pEndIndex, boolean pReverseDirection) { + return false; + } @Override public ItemStack quickMoveStack(Player playerIn, int index) { diff --git a/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemSubmitPacket.java b/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemSubmitPacket.java index 234b87d4bb..a29e54e37c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemSubmitPacket.java +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemSubmitPacket.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.gui.menu; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.logistics.stockTicker.StockKeeperCategoryMenu; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.network.FriendlyByteBuf; @@ -37,7 +39,14 @@ public class GhostItemSubmitPacket extends SimplePacketBase { if (player.containerMenu instanceof GhostItemMenu menu) { menu.ghostInventory.setStackInSlot(slot, item); - menu.getSlot(36 + slot).setChanged(); + menu.getSlot(36 + slot) + .setChanged(); + } + if (player.containerMenu instanceof StockKeeperCategoryMenu menu + && (item.isEmpty() || item.getItem() instanceof FilterItem)) { + menu.proxyInventory.setStackInSlot(slot, item); + menu.getSlot(36 + slot) + .setChanged(); } }); return true; diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/AbstractSimiWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widget/AbstractSimiWidget.java deleted file mode 100644 index 0b705600d8..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/AbstractSimiWidget.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.simibubi.create.foundation.gui.widget; - -import java.util.LinkedList; -import java.util.List; -import java.util.function.BiConsumer; - -import javax.annotation.Nonnull; - -import com.simibubi.create.foundation.gui.TickableGuiEventListener; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.AbstractWidget; -import net.minecraft.client.gui.narration.NarrationElementOutput; -import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; -import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; -import net.minecraft.network.chat.Component; - -public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener { - - public static final int HEADER_RGB = 0x5391E1; - public static final int HINT_RGB = 0x96B7E0; - - protected float z; - protected boolean wasHovered = false; - protected List toolTip = new LinkedList<>(); - protected BiConsumer onClick = (_$, _$$) -> {}; - - public int lockedTooltipX = -1; - public int lockedTooltipY = -1; - - protected AbstractSimiWidget(int x, int y) { - this(x, y, 16, 16); - } - - protected AbstractSimiWidget(int x, int y, int width, int height) { - this(x, y, width, height, Components.immutableEmpty()); - } - - protected AbstractSimiWidget(int x, int y, int width, int height, Component message) { - super(x, y, width, height, message); - } - - @Override - protected ClientTooltipPositioner createTooltipPositioner() { - return DefaultTooltipPositioner.INSTANCE; - } - - public T withCallback(BiConsumer cb) { - this.onClick = cb; - //noinspection unchecked - return (T) this; - } - - public T withCallback(Runnable cb) { - return withCallback((_$, _$$) -> cb.run()); - } - - public T atZLevel(float z) { - this.z = z; - //noinspection unchecked - return (T) this; - } - - public List getToolTip() { - return toolTip; - } - - @Override - public void tick() {} - - @Override - public void renderWidget(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - beforeRender(graphics, mouseX, mouseY, partialTicks); - doRender(graphics, mouseX, mouseY, partialTicks); - afterRender(graphics, mouseX, mouseY, partialTicks); - wasHovered = isHoveredOrFocused(); - } - - protected void beforeRender(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - graphics.pose().pushPose(); - } - - protected void doRender(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - } - - protected void afterRender(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - graphics.pose().popPose(); - } - - public void runCallback(double mouseX, double mouseY) { - onClick.accept((int) mouseX, (int) mouseY); - } - - @Override - public void onClick(double mouseX, double mouseY) { - runCallback(mouseX, mouseY); - } - - @Override - public void updateWidgetNarration(NarrationElementOutput pNarrationElementOutput) { - defaultButtonNarrationText(pNarrationElementOutput); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/BoxWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widget/BoxWidget.java deleted file mode 100644 index b22933cd76..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/BoxWidget.java +++ /dev/null @@ -1,228 +0,0 @@ -package com.simibubi.create.foundation.gui.widget; - -import java.util.function.Function; - -import com.simibubi.create.foundation.gui.Theme; -import com.simibubi.create.foundation.gui.Theme.Key; -import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.element.BoxElement; -import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.client.gui.GuiGraphics; - -public class BoxWidget extends ElementWidget { - - public static final Function gradientFactory = (box) -> (ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, w/2, -2, w + 4, h + 4, box.gradientColor1, box.gradientColor2); - - protected BoxElement box; - - protected Color customBorderTop; - protected Color customBorderBot; - protected Color customBackground; - protected boolean animateColors = true; - protected LerpedFloat colorAnimation = LerpedFloat.linear(); - - protected Color gradientColor1, gradientColor2; - private Color previousColor1, previousColor2; - private Color colorTarget1 = Theme.c(getIdleTheme(), true).copy(); - private Color colorTarget2 = Theme.c(getIdleTheme(), false).copy(); - - public BoxWidget() { - this(0, 0); - } - - public BoxWidget(int x, int y) { - this(x, y, 16, 16); - } - - public BoxWidget(int x, int y, int width, int height) { - super(x, y, width, height); - box = new BoxElement() - .at(x, y) - .withBounds(width, height); - gradientColor1 = colorTarget1; - gradientColor2 = colorTarget2; - } - - public T withBounds(int width, int height) { - this.width = width; - this.height = height; - //noinspection unchecked - return (T) this; - } - - public T withBorderColors(Couple colors) { - this.customBorderTop = colors.getFirst(); - this.customBorderBot = colors.getSecond(); - updateColorsFromState(); - //noinspection unchecked - return (T) this; - } - - public T withBorderColors(Color top, Color bot) { - this.customBorderTop = top; - this.customBorderBot = bot; - updateColorsFromState(); - //noinspection unchecked - return (T) this; - } - - public T withCustomBackground(Color color) { - this.customBackground = color; - //noinspection unchecked - return (T) this; - } - - public T animateColors(boolean b) { - this.animateColors = b; - //noinspection unchecked - return (T) this; - } - - @Override - public void tick() { - super.tick(); - colorAnimation.tickChaser(); - } - - @Override - public void onClick(double x, double y) { - super.onClick(x, y); - - gradientColor1 = Theme.c(getClickTheme(), true); - gradientColor2 = Theme.c(getClickTheme(), false); - startGradientAnimation(getColorForState(true), getColorForState(false), true, 0.15); - } - - @Override - protected void beforeRender(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.beforeRender(graphics, mouseX, mouseY, partialTicks); - - if (isHovered != wasHovered) { - startGradientAnimation( - getColorForState(true), - getColorForState(false), - isHovered - ); - } - - if (colorAnimation.settled()) { - gradientColor1 = colorTarget1; - gradientColor2 = colorTarget2; - } else { - float animationValue = 1 - Math.abs(colorAnimation.getValue(partialTicks)); - gradientColor1 = Color.mixColors(previousColor1, colorTarget1, animationValue); - gradientColor2 = Color.mixColors(previousColor2, colorTarget2, animationValue); - } - - } - - @Override - public void doRender(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - float fadeValue = fade.getValue(partialTicks); - if (fadeValue < .1f) - return; - - box.withAlpha(fadeValue); - box.withBackground(customBackground != null ? customBackground : Theme.c(Theme.Key.PONDER_BACKGROUND_TRANSPARENT)) - .gradientBorder(gradientColor1, gradientColor2) - .at(getX(), getY(), z) - .withBounds(width, height) - .render(graphics); - - super.doRender(graphics, mouseX, mouseY, partialTicks); - - wasHovered = isHovered; - } - - @Override - public boolean isMouseOver(double mX, double mY) { - if (!active || !visible) - return false; - - float padX = 2 + paddingX; - float padY = 2 + paddingY; - - return getX() - padX <= mX && getY() - padY <= mY && mX < getX() + padX + width && mY < getY() + padY + height; - } - - @Override - protected boolean clicked(double pMouseX, double pMouseY) { - if (!active || !visible) - return false; - return isMouseOver(pMouseX, pMouseY); - } - - public BoxElement getBox() { - return box; - } - - public void updateColorsFromState() { - colorTarget1 = getColorForState(true); - colorTarget2 = getColorForState(false); - } - - public void animateGradientFromState() { - startGradientAnimation( - getColorForState(true), - getColorForState(false), - true - ); - } - - private void startGradientAnimation(Color c1, Color c2, boolean positive, double expSpeed) { - if (!animateColors) - return; - - colorAnimation.startWithValue(positive ? 1 : -1); - colorAnimation.chase(0, expSpeed, LerpedFloat.Chaser.EXP); - colorAnimation.tickChaser(); - - previousColor1 = gradientColor1; - previousColor2 = gradientColor2; - - colorTarget1 = c1; - colorTarget2 = c2; - } - - private void startGradientAnimation(Color c1, Color c2, boolean positive) { - startGradientAnimation(c1, c2, positive, 0.6); - } - - private Color getColorForState(boolean first) { - if (!active) - return Theme.p(getDisabledTheme()).get(first); - - if (isHovered) { - if (first) - return customBorderTop != null ? customBorderTop.darker() : Theme.c(getHoverTheme(), true); - else - return customBorderBot != null ? customBorderBot.darker() : Theme.c(getHoverTheme(), false); - } - - if (first) - return customBorderTop != null ? customBorderTop : Theme.c(getIdleTheme(), true); - else - return customBorderBot != null ? customBorderBot : Theme.c(getIdleTheme(), false); - } - - public Key getDisabledTheme() { - return Theme.Key.BUTTON_DISABLE; - } - - public Key getIdleTheme() { - return Theme.Key.BUTTON_IDLE; - } - - public Key getHoverTheme() { - return Theme.Key.BUTTON_HOVER; - } - - public Key getClickTheme() { - return Theme.Key.BUTTON_CLICK; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/ElementWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widget/ElementWidget.java deleted file mode 100644 index 79db1c0692..0000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/ElementWidget.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.simibubi.create.foundation.gui.widget; - -import java.util.function.Consumer; -import java.util.function.UnaryOperator; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.gui.element.RenderElement; -import com.simibubi.create.foundation.gui.element.ScreenElement; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.client.gui.GuiGraphics; - -public class ElementWidget extends AbstractSimiWidget { - - protected RenderElement element = RenderElement.EMPTY; - - protected boolean usesFade = false; - protected int fadeModX; - protected int fadeModY; - protected LerpedFloat fade = LerpedFloat.linear().startWithValue(1); - - protected boolean rescaleElement = false; - protected float rescaleSizeX; - protected float rescaleSizeY; - - protected float paddingX = 0; - protected float paddingY = 0; - - public ElementWidget(int x, int y) { - super(x, y); - } - - public ElementWidget(int x, int y, int width, int height) { - super(x, y, width, height); - } - - public T showingElement(RenderElement element) { - this.element = element; - //noinspection unchecked - return (T) this; - } - - public T showing(ScreenElement renderable) { - return this.showingElement(RenderElement.of(renderable)); - } - - public T modifyElement(Consumer consumer) { - if (element != null) - consumer.accept(element); - //noinspection unchecked - return (T) this; - } - - public T mapElement(UnaryOperator function) { - if (element != null) - element = function.apply(element); - //noinspection unchecked - return (T) this; - } - - public T withPadding(float paddingX, float paddingY) { - this.paddingX = paddingX; - this.paddingY = paddingY; - //noinspection unchecked - return (T) this; - } - - public T enableFade(int fadeModifierX, int fadeModifierY) { - this.fade.startWithValue(0); - this.usesFade = true; - this.fadeModX = fadeModifierX; - this.fadeModY = fadeModifierY; - //noinspection unchecked - return (T) this; - } - - public T disableFade() { - this.fade.startWithValue(1); - this.usesFade = false; - //noinspection unchecked - return (T) this; - } - - public LerpedFloat fade() { - return fade; - } - - public T fade(float target) { - fade.chase(target, 0.1, LerpedFloat.Chaser.EXP); - //noinspection unchecked - return (T) this; - } - - /** - * Rescaling and its effects aren't properly tested with most elements. - * Thought it should work fine when using a TextStencilElement. - * Check BaseConfigScreen's title for such an example. - */ - @Deprecated - public T rescaleElement(float rescaleSizeX, float rescaleSizeY) { - this.rescaleElement = true; - this.rescaleSizeX = rescaleSizeX; - this.rescaleSizeY = rescaleSizeY; - //noinspection unchecked - return (T) this; - } - - public T disableRescale() { - this.rescaleElement = false; - //noinspection unchecked - return (T) this; - } - - @Override - public void tick() { - super.tick(); - fade.tickChaser(); - } - - @Override - protected void beforeRender(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - super.beforeRender(graphics, mouseX, mouseY, partialTicks); - isHovered = isMouseOver(mouseX, mouseY); - - float fadeValue = fade.getValue(partialTicks); - element.withAlpha(fadeValue); - if (fadeValue < 1) { - graphics.pose().translate((1 - fadeValue) * fadeModX, (1 - fadeValue) * fadeModY, 0); - } - } - - @Override - public void doRender(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { - PoseStack ms = graphics.pose(); - ms.pushPose(); - ms.translate(getX() + paddingX, getY() + paddingY, z); - float innerWidth = width - 2 * paddingX; - float innerHeight = height - 2 * paddingY; - float eX = element.getX(), eY = element.getY(); - if (rescaleElement) { - float xScale = innerWidth / rescaleSizeX; - float yScale = innerHeight / rescaleSizeY; - ms.scale(xScale, yScale, 1); - element.at(eX / xScale, eY / yScale); - innerWidth /= xScale; - innerHeight /= yScale; - } - element.withBounds((int) innerWidth, (int) innerHeight).render(graphics); - ms.popPose(); - if (rescaleElement) { - element.at(eX, eY); - } - } - - public RenderElement getRenderElement() { - return element; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/IconButton.java b/src/main/java/com/simibubi/create/foundation/gui/widget/IconButton.java index d17141c70d..ffee722c24 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/IconButton.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/IconButton.java @@ -1,9 +1,11 @@ package com.simibubi.create.foundation.gui.widget; import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllKeys; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.element.ScreenElement; +import net.createmod.catnip.gui.element.ScreenElement; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; @@ -11,6 +13,8 @@ public class IconButton extends AbstractSimiWidget { protected ScreenElement icon; + public boolean green; + public IconButton(int x, int y, ScreenElement icon) { this(x, y, 18, 18, icon); } @@ -25,8 +29,10 @@ public class IconButton extends AbstractSimiWidget { if (visible) { isHovered = mouseX >= getX() && mouseY >= getY() && mouseX < getX() + width && mouseY < getY() + height; - AllGuiTextures button = !active ? AllGuiTextures.BUTTON_DOWN - : isMouseOver(mouseX, mouseY) ? AllGuiTextures.BUTTON_HOVER : AllGuiTextures.BUTTON; + AllGuiTextures button = !active ? AllGuiTextures.BUTTON_DISABLED + : isHovered && AllKeys.isMouseButtonDown(0) ? AllGuiTextures.BUTTON_DOWN + : isHovered ? AllGuiTextures.BUTTON_HOVER + : green ? AllGuiTextures.BUTTON_GREEN : AllGuiTextures.BUTTON; RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); drawBg(graphics, button); @@ -35,7 +41,8 @@ public class IconButton extends AbstractSimiWidget { } protected void drawBg(GuiGraphics graphics, AllGuiTextures button) { - graphics.blit(button.location, getX(), getY(), button.startX, button.startY, button.width, button.height); + graphics.blit(button.location, getX(), getY(), button.getStartX(), button.getStartY(), button.getWidth(), + button.getHeight()); } public void setToolTip(Component text) { diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/Indicator.java b/src/main/java/com/simibubi/create/foundation/gui/widget/Indicator.java index 9a4aada86b..4be43c2bf5 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/Indicator.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/Indicator.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.gui.widget; import com.google.common.collect.ImmutableList; import com.simibubi.create.foundation.gui.AllGuiTextures; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; @@ -11,7 +12,7 @@ public class Indicator extends AbstractSimiWidget { public State state; public Indicator(int x, int y, Component tooltip) { - super(x, y, AllGuiTextures.INDICATOR.width, AllGuiTextures.INDICATOR.height); + super(x, y, AllGuiTextures.INDICATOR.getWidth(), AllGuiTextures.INDICATOR.getHeight()); this.toolTip = toolTip.isEmpty() ? ImmutableList.of() : ImmutableList.of(tooltip); this.state = State.OFF; } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/Label.java b/src/main/java/com/simibubi/create/foundation/gui/widget/Label.java index f8fe433dca..1689edb4ea 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/Label.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/Label.java @@ -3,8 +3,8 @@ package com.simibubi.create.foundation.gui.widget; import javax.annotation.Nonnull; import com.mojang.blaze3d.systems.RenderSystem; -import com.simibubi.create.foundation.utility.Components; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; @@ -22,7 +22,7 @@ public class Label extends AbstractSimiWidget { public Label(int x, int y, Component text) { super(x, y, Minecraft.getInstance().font.width(text), 10); font = Minecraft.getInstance().font; - this.text = Components.literal("Label"); + this.text = Component.literal("Label"); color = 0xFFFFFF; hasShadow = false; suffix = ""; @@ -62,8 +62,8 @@ public class Label extends AbstractSimiWidget { for (int i = startIndex; i != endIndex; i += step) { String sub = builder.substring(trimFront ? i : startIndex, trimFront ? endIndex + 1 : i + 1); - if (fontRenderer.width(Components.literal(sub).setStyle(newText.getStyle())) + trimWidth <= maxWidthPx) { - text = Components.literal(trimFront ? trim + sub : sub + trim).setStyle(newText.getStyle()); + if (fontRenderer.width(Component.literal(sub).setStyle(newText.getStyle())) + trimWidth <= maxWidthPx) { + text = Component.literal(trimFront ? trim + sub : sub + trim).setStyle(newText.getStyle()); return; } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java b/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java index ab96411322..55f95a25c6 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java @@ -6,9 +6,9 @@ import java.util.function.Function; import com.simibubi.create.AllKeys; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour.StepContext; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.sounds.SimpleSoundInstance; @@ -19,9 +19,9 @@ public class ScrollInput extends AbstractSimiWidget { protected Consumer onScroll; protected int state; - protected Component title = Lang.translateDirect("gui.scrollInput.defaultTitle"); - protected final Component scrollToModify = Lang.translateDirect("gui.scrollInput.scrollToModify"); - protected final Component shiftScrollsFaster = Lang.translateDirect("gui.scrollInput.shiftScrollsFaster"); + protected Component title = CreateLang.translateDirect("gui.scrollInput.defaultTitle"); + protected final Component scrollToModify = CreateLang.translateDirect("gui.scrollInput.scrollToModify"); + protected final Component shiftScrollsFaster = CreateLang.translateDirect("gui.scrollInput.shiftScrollsFaster"); protected Component hint = null; protected Label displayLabel; protected boolean inverted; @@ -39,7 +39,9 @@ public class ScrollInput extends AbstractSimiWidget { max = 1; shiftStep = 5; step = standardStep(); - formatter = i -> Components.literal(String.valueOf(i)); + formatter = i -> { + return Component.literal(String.valueOf(i)); + }; soundPlayed = false; } @@ -96,7 +98,7 @@ public class ScrollInput extends AbstractSimiWidget { writeToLabel(); return this; } - + @Override public void tick() { super.tick(); @@ -179,10 +181,10 @@ public class ScrollInput extends AbstractSimiWidget { if (title == null) return; toolTip.add(title.plainCopy() - .withStyle(s -> s.withColor(HEADER_RGB))); + .withStyle(s -> s.withColor(HEADER_RGB.getRGB()))); if (hint != null) toolTip.add(hint.plainCopy() - .withStyle(s -> s.withColor(HINT_RGB))); + .withStyle(s -> s.withColor(HINT_RGB.getRGB()))); toolTip.add(scrollToModify.plainCopy() .withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY)); toolTip.add(shiftScrollsFaster.plainCopy() diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java b/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java index 158175120d..0d5db5f93c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java @@ -3,8 +3,7 @@ package com.simibubi.create.foundation.gui.widget; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; @@ -12,7 +11,7 @@ import net.minecraft.network.chat.MutableComponent; public class SelectionScrollInput extends ScrollInput { - private final MutableComponent scrollToSelect = Lang.translateDirect("gui.scrollInput.scrollToSelect"); + private final MutableComponent scrollToSelect = CreateLang.translateDirect("gui.scrollInput.scrollToSelect"); protected List options; public SelectionScrollInput(int xIn, int yIn, int widthIn, int heightIn) { @@ -35,37 +34,39 @@ public class SelectionScrollInput extends ScrollInput { if (title == null) return; toolTip.add(title.plainCopy() - .withStyle(s -> s.withColor(HEADER_RGB))); + .withStyle(s -> s.withColor(HEADER_RGB.getRGB()))); int min = Math.min(this.max - 16, state - 7); int max = Math.max(this.min + 16, state + 8); min = Math.max(min, this.min); max = Math.min(max, this.max); if (this.min + 1 == min) min--; - if (min > this.min) - toolTip.add(Components.literal("> ...") + if (min > this.min) { + toolTip.add(Component.literal("> ...") .withStyle(ChatFormatting.GRAY)); + } if (this.max - 1 == max) max++; for (int i = min; i < max; i++) { if (i == state) - toolTip.add(Components.empty() + toolTip.add(Component.empty() .append("-> ") .append(options.get(i)) .withStyle(ChatFormatting.WHITE)); else - toolTip.add(Components.empty() + toolTip.add(Component.empty() .append("> ") .append(options.get(i)) .withStyle(ChatFormatting.GRAY)); } - if (max < this.max) - toolTip.add(Components.literal("> ...") + if (max < this.max) { + toolTip.add(Component.literal("> ...") .withStyle(ChatFormatting.GRAY)); + } if (hint != null) toolTip.add(hint.plainCopy() - .withStyle(s -> s.withColor(HINT_RGB))); + .withStyle(s -> s.withColor(HINT_RGB.getRGB()))); toolTip.add(scrollToSelect.plainCopy() .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC)); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/TooltipArea.java b/src/main/java/com/simibubi/create/foundation/gui/widget/TooltipArea.java index e734975b0a..45cef4ddad 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/TooltipArea.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/TooltipArea.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.gui.widget; import java.util.List; +import net.createmod.catnip.gui.widget.AbstractSimiWidget; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; diff --git a/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java b/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java index 224f6a0fcf..f8e10b81c6 100644 --- a/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java +++ b/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java @@ -8,8 +8,8 @@ import java.util.Set; import java.util.stream.Stream; import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.IntAttached; +import net.createmod.catnip.data.IntAttached; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -22,7 +22,7 @@ public class CountedItemStackList { public CountedItemStackList(IItemHandler inventory, FilteringBehaviour filteringBehaviour) { for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack extractItem = inventory.extractItem(slot, inventory.getSlotLimit(slot), true); + ItemStack extractItem = inventory.getStackInSlot(slot); if (filteringBehaviour.test(extractItem)) add(extractItem); } diff --git a/src/main/java/com/simibubi/create/foundation/item/CustomUseEffectsItem.java b/src/main/java/com/simibubi/create/foundation/item/CustomUseEffectsItem.java index 58c76c7536..9fa4267415 100644 --- a/src/main/java/com/simibubi/create/foundation/item/CustomUseEffectsItem.java +++ b/src/main/java/com/simibubi/create/foundation/item/CustomUseEffectsItem.java @@ -1,5 +1,6 @@ package com.simibubi.create.foundation.item; +import net.createmod.catnip.data.TriState; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; @@ -8,20 +9,20 @@ public interface CustomUseEffectsItem { /** * Called to determine if use effects should be applied for this item. * - * @param stack The ItemStack being used. + * @param stack The ItemStack being used. * @param entity The LivingEntity using the item. - * @return null for default behavior, or boolean to override default behavior + * @return {@link TriState#DEFAULT} for default behavior, or {@link TriState#TRUE}/{@link TriState#FALSE} to override default behavior */ - default Boolean shouldTriggerUseEffects(ItemStack stack, LivingEntity entity) { - return null; + default TriState shouldTriggerUseEffects(ItemStack stack, LivingEntity entity) { + return TriState.DEFAULT; } /** * Called when use effects should be applied for this item. * - * @param stack The ItemStack being used. + * @param stack The ItemStack being used. * @param entity The LivingEntity using the item. - * @param count The amount of times effects should be applied. Can safely be ignored. + * @param count The amount of times effects should be applied. Can safely be ignored. * @param random The LivingEntity's RandomSource. * @return if the default behavior should be cancelled or not */ diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java b/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java index 388184066a..6f6fca4eac 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java @@ -15,20 +15,22 @@ import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.Nullable; import com.google.common.collect.ImmutableList; -import com.simibubi.create.foundation.item.TooltipHelper.Palette; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.lang.FontHelper.Palette; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.Item; import net.minecraft.world.level.ItemLike; + import net.minecraftforge.event.entity.player.ItemTooltipEvent; -public record ItemDescription(ImmutableList lines, ImmutableList linesOnShift, ImmutableList linesOnCtrl) { +public record ItemDescription(ImmutableList lines, ImmutableList linesOnShift, + ImmutableList linesOnCtrl) { private static final Map> CUSTOM_TOOLTIP_KEYS = new IdentityHashMap<>(); @Nullable @@ -143,20 +145,20 @@ public record ItemDescription(ImmutableList lines, ImmutableList behaviourPair : behaviours) { String condition = behaviourPair.getLeft(); String behaviour = behaviourPair.getRight(); - linesOnShift.add(Components.literal(condition).withStyle(GRAY)); + linesOnShift.add(Component.literal(condition).withStyle(GRAY)); linesOnShift.addAll(TooltipHelper.cutStringTextComponent(behaviour, palette.primary(), palette.highlight(), 1)); } for (Pair actionPair : actions) { String condition = actionPair.getLeft(); String action = actionPair.getRight(); - linesOnCtrl.add(Components.literal(condition).withStyle(GRAY)); + linesOnCtrl.add(Component.literal(condition).withStyle(GRAY)); linesOnCtrl.addAll(TooltipHelper.cutStringTextComponent(action, palette.primary(), palette.highlight(), 1)); } @@ -164,43 +166,43 @@ public record ItemDescription(ImmutableList lines, ImmutableList list : Arrays.asList(lines, linesOnShift, linesOnCtrl)) { boolean shift = list == linesOnShift; boolean ctrl = list == linesOnCtrl; if (holdDesc.length != 2 || holdCtrl.length != 2) { - list.add(0, Components.literal("Invalid lang formatting!")); + list.add(0, Component.literal("Invalid lang formatting!")); continue; } if (hasControls) { - MutableComponent tabBuilder = Components.empty(); - tabBuilder.append(Components.literal(holdCtrl[0]).withStyle(DARK_GRAY)); + MutableComponent tabBuilder = Component.empty(); + tabBuilder.append(Component.literal(holdCtrl[0]).withStyle(DARK_GRAY)); tabBuilder.append(keyCtrl.plainCopy() .withStyle(ctrl ? WHITE : GRAY)); - tabBuilder.append(Components.literal(holdCtrl[1]).withStyle(DARK_GRAY)); + tabBuilder.append(Component.literal(holdCtrl[1]).withStyle(DARK_GRAY)); list.add(0, tabBuilder); } if (hasDescription) { - MutableComponent tabBuilder = Components.empty(); - tabBuilder.append(Components.literal(holdDesc[0]).withStyle(DARK_GRAY)); + MutableComponent tabBuilder = Component.empty(); + tabBuilder.append(Component.literal(holdDesc[0]).withStyle(DARK_GRAY)); tabBuilder.append(keyShift.plainCopy() .withStyle(shift ? WHITE : GRAY)); - tabBuilder.append(Components.literal(holdDesc[1]).withStyle(DARK_GRAY)); + tabBuilder.append(Component.literal(holdDesc[1]).withStyle(DARK_GRAY)); list.add(0, tabBuilder); } if (shift || ctrl) - list.add(hasDescription && hasControls ? 2 : 1, Components.immutableEmpty()); + list.add(hasDescription && hasControls ? 2 : 1, CommonComponents.EMPTY); } } diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java index d4cdb6151a..4c89e97028 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java @@ -2,30 +2,31 @@ package com.simibubi.create.foundation.item; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; import javax.annotation.Nullable; -import com.simibubi.create.foundation.block.IBE; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.capabilities.ForgeCapabilities; - import org.apache.commons.lang3.mutable.MutableInt; -import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.content.logistics.box.PackageEntity; +import com.simibubi.create.foundation.block.IBE; +import net.createmod.catnip.data.Pair; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.util.Mth; import net.minecraft.world.Containers; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemHandlerHelper; public class ItemHelper { @@ -82,9 +83,9 @@ public class ItemHelper { public static > int calcRedstoneFromBlockEntity(T ibe, Level level, BlockPos pos) { return ibe.getBlockEntityOptional(level, pos) - .map(be -> be.getCapability(ForgeCapabilities.ITEM_HANDLER)) - .map(lo -> lo.map(ItemHelper::calcRedstoneFromInventory).orElse(0)) - .orElse(0); + .map(be -> be.getCapability(ForgeCapabilities.ITEM_HANDLER)) + .map(lo -> lo.map(ItemHelper::calcRedstoneFromInventory).orElse(0)) + .orElse(0); } public static int calcRedstoneFromInventory(@Nullable IItemHandler inv) { @@ -116,7 +117,8 @@ public class ItemHelper { public static List> condenseIngredients(NonNullList recipeIngredients) { List> actualIngredients = new ArrayList<>(); - Ingredients: for (Ingredient igd : recipeIngredients) { + Ingredients: + for (Ingredient igd : recipeIngredients) { for (Pair pair : actualIngredients) { ItemStack[] stacks1 = pair.getFirst() .getItems(); @@ -177,7 +179,7 @@ public class ItemHelper { } public static ItemStack extract(IItemHandler inv, Predicate test, ExtractionCountMode mode, int amount, - boolean simulate) { + boolean simulate) { ItemStack extracting = ItemStack.EMPTY; boolean amountRequired = mode == ExtractionCountMode.EXACTLY; boolean checkHasEnoughItems = amountRequired; @@ -185,7 +187,8 @@ public class ItemHelper { boolean potentialOtherMatch = false; int maxExtractionCount = amount; - Extraction: do { + Extraction: + do { extracting = ItemStack.EMPTY; for (int slot = 0; slot < inv.getSlots(); slot++) { @@ -242,7 +245,7 @@ public class ItemHelper { } public static ItemStack extract(IItemHandler inv, Predicate test, - Function amountFunction, boolean simulate) { + Function amountFunction, boolean simulate) { ItemStack extracting = ItemStack.EMPTY; int maxExtractionCount = 64; @@ -298,7 +301,16 @@ public class ItemHelper { } return -1; } - + + public static ItemStack fromItemEntity(Entity entityIn) { + if (!entityIn.isAlive()) + return ItemStack.EMPTY; + if (entityIn instanceof PackageEntity packageEntity) { + return packageEntity.getBox(); + } + return entityIn instanceof ItemEntity ? ((ItemEntity) entityIn).getItem() : ItemStack.EMPTY; + } + public static ItemStack limitCountToMaxStackSize(ItemStack stack, boolean simulate) { int count = stack.getCount(); int max = stack.getMaxStackSize(); @@ -309,5 +321,14 @@ public class ItemHelper { stack.setCount(max); return remainder; } - + + public static void copyContents(IItemHandler from, IItemHandlerModifiable to) { + if (from.getSlots() != to.getSlots()) { + throw new IllegalArgumentException("Slot count mismatch"); + } + + for (int i = 0; i < from.getSlots(); i++) { + to.setStackInSlot(i, from.getStackInSlot(i).copy()); + } + } } diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemSlots.java b/src/main/java/com/simibubi/create/foundation/item/ItemSlots.java new file mode 100644 index 0000000000..d9f3c96c55 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/item/ItemSlots.java @@ -0,0 +1,115 @@ +package com.simibubi.create.foundation.item; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.IntFunction; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.foundation.utility.CreateCodecs; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +/** + * Utility class representing non-empty slots in an item inventory. + */ +public class ItemSlots { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.unboundedMap(CreateCodecs.boundedIntStr(0), ItemStack.CODEC).fieldOf("items").forGetter(ItemSlots::toBoxedMap), + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("size").forGetter(ItemSlots::getSize) + ).apply(instance, ItemSlots::deserialize)); + + private final Int2ObjectMap map; + private int size; + + public ItemSlots() { + this.map = new Int2ObjectOpenHashMap<>(); + this.size = 0; + } + + public void set(int slot, ItemStack stack) { + if (slot < 0) { + throw new IllegalArgumentException("Slot must be positive"); + } else if (!stack.isEmpty()) { + this.map.put(slot, stack); + this.size = Math.max(this.size, slot + 1); + } + } + + public int getSize() { + return this.size; + } + + public void setSize(int size) { + if (size <= this.getHighestSlot()) { + throw new IllegalStateException("cannot set size to below the highest slot"); + } + this.size = size; + } + + public void forEach(SlotConsumer consumer) { + for (Int2ObjectMap.Entry entry : this.map.int2ObjectEntrySet()) { + consumer.accept(entry.getIntKey(), entry.getValue()); + } + } + + private int getHighestSlot() { + return this.map.keySet().intStream().max().orElse(-1); + } + + public T toHandler(IntFunction factory) { + T handler = factory.apply(this.size); + this.forEach(handler::setStackInSlot); + return handler; + } + + public static ItemSlots fromHandler(IItemHandler handler) { + ItemSlots slots = new ItemSlots(); + slots.setSize(handler.getSlots()); + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.getStackInSlot(i); + if (!stack.isEmpty()) { + slots.set(i, stack.copy()); + } + } + return slots; + } + + public Map toBoxedMap() { + Map map = new HashMap<>(); + this.forEach(map::put); + return map; + } + + public static ItemSlots fromBoxedMap(Map map) { + ItemSlots slots = new ItemSlots(); + map.forEach(slots::set); + return slots; + } + + public static Codec maxSizeCodec(int maxSize) { + return ExtraCodecs.validate( + CODEC, + slots -> slots.size <= maxSize + ? DataResult.success(slots) + : DataResult.error(() -> "Slots above maximum of " + maxSize) + ); + } + + private static ItemSlots deserialize(Map map, int size) { + ItemSlots slots = fromBoxedMap(map); + slots.setSize(size); + return slots; + } + + @FunctionalInterface + public interface SlotConsumer { + void accept(int slot, ItemStack stack); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/item/KineticStats.java b/src/main/java/com/simibubi/create/foundation/item/KineticStats.java index 5cf6656c48..d9fc2280fb 100644 --- a/src/main/java/com/simibubi/create/foundation/item/KineticStats.java +++ b/src/main/java/com/simibubi/create/foundation/item/KineticStats.java @@ -9,24 +9,26 @@ import java.util.List; import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllBlocks; +import com.simibubi.create.api.stress.BlockStressValues; +import com.simibubi.create.api.stress.BlockStressValues.GeneratedRpm; import com.simibubi.create.content.equipment.goggles.GogglesItem; -import com.simibubi.create.content.kinetics.BlockStressValues; import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; import com.simibubi.create.content.kinetics.steamEngine.SteamEngineBlock; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.CKinetics; +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.lang.LangBuilder; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; + import net.minecraftforge.event.entity.player.ItemTooltipEvent; public class KineticStats implements TooltipModifier { @@ -52,7 +54,7 @@ public class KineticStats implements TooltipModifier { List kineticStats = getKineticStats(block, context.getEntity()); if (!kineticStats.isEmpty()) { List tooltip = context.getToolTip(); - tooltip.add(Components.immutableEmpty()); + tooltip.add(CommonComponents.EMPTY); tooltip.addAll(kineticStats); } } @@ -61,8 +63,8 @@ public class KineticStats implements TooltipModifier { List list = new ArrayList<>(); CKinetics config = AllConfigs.server().kinetics; - LangBuilder rpmUnit = Lang.translate("generic.unit.rpm"); - LangBuilder suUnit = Lang.translate("generic.unit.stress"); + LangBuilder rpmUnit = CreateLang.translate("generic.unit.rpm"); + LangBuilder suUnit = CreateLang.translate("generic.unit.stress"); boolean hasGoggles = GogglesItem.isWearingGoggles(player); @@ -78,22 +80,22 @@ public class KineticStats implements TooltipModifier { boolean hasStressImpact = StressImpact.isEnabled() && showStressImpact && BlockStressValues.getImpact(block) > 0; - boolean hasStressCapacity = StressImpact.isEnabled() && BlockStressValues.hasCapacity(block); + boolean hasStressCapacity = StressImpact.isEnabled() && BlockStressValues.getCapacity(block) > 0; if (hasStressImpact) { - Lang.translate("tooltip.stressImpact") + CreateLang.translate("tooltip.stressImpact") .style(GRAY) .addTo(list); double impact = BlockStressValues.getImpact(block); StressImpact impactId = impact >= config.highStressImpact.get() ? StressImpact.HIGH : (impact >= config.mediumStressImpact.get() ? StressImpact.MEDIUM : StressImpact.LOW); - LangBuilder builder = Lang.builder() - .add(Lang.text(TooltipHelper.makeProgressBar(3, impactId.ordinal() + 1)) + LangBuilder builder = CreateLang.builder() + .add(CreateLang.text(TooltipHelper.makeProgressBar(3, impactId.ordinal() + 1)) .style(impactId.getAbsoluteColor())); if (hasGoggles) { - builder.add(Lang.number(impact)) + builder.add(CreateLang.number(impact)) .text("x ") .add(rpmUnit) .addTo(list); @@ -103,32 +105,31 @@ public class KineticStats implements TooltipModifier { } if (hasStressCapacity) { - Lang.translate("tooltip.capacityProvided") + CreateLang.translate("tooltip.capacityProvided") .style(GRAY) .addTo(list); double capacity = BlockStressValues.getCapacity(block); - Couple generatedRPM = BlockStressValues.getGeneratedRPM(block); + GeneratedRpm generatedRPM = BlockStressValues.RPM.get(block); StressImpact impactId = capacity >= config.highCapacity.get() ? StressImpact.HIGH : (capacity >= config.mediumCapacity.get() ? StressImpact.MEDIUM : StressImpact.LOW); StressImpact opposite = StressImpact.values()[StressImpact.values().length - 2 - impactId.ordinal()]; - LangBuilder builder = Lang.builder() - .add(Lang.text(TooltipHelper.makeProgressBar(3, impactId.ordinal() + 1)) + LangBuilder builder = CreateLang.builder() + .add(CreateLang.text(TooltipHelper.makeProgressBar(3, impactId.ordinal() + 1)) .style(opposite.getAbsoluteColor())); if (hasGoggles) { - builder.add(Lang.number(capacity)) + builder.add(CreateLang.number(capacity)) .text("x ") .add(rpmUnit) .addTo(list); if (generatedRPM != null) { - LangBuilder amount = Lang.number(capacity * generatedRPM.getSecond()) + LangBuilder amount = CreateLang.number(capacity * generatedRPM.value()) .add(suUnit); - Lang.text(" -> ") - .add(!generatedRPM.getFirst() - .equals(generatedRPM.getSecond()) ? Lang.translate("tooltip.up_to", amount) : amount) + CreateLang.text(" -> ") + .add(generatedRPM.mayGenerateLess() ? CreateLang.translate("tooltip.up_to", amount) : amount) .style(DARK_GRAY) .addTo(list); } diff --git a/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java b/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java index a46a2f410a..42e80b228c 100644 --- a/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java @@ -6,10 +6,10 @@ import java.util.LinkedList; import java.util.List; import com.google.common.base.Strings; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.CreateLang; +import net.createmod.catnip.data.Couple; +import net.createmod.catnip.lang.FontHelper; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; @@ -21,18 +21,18 @@ public class TooltipHelper { public static final int MAX_WIDTH_PER_LINE = 200; - public static MutableComponent holdShift(Palette palette, boolean highlighted) { - return Lang.translateDirect("tooltip.holdForDescription", Lang.translateDirect("tooltip.keyShift") + public static MutableComponent holdShift(FontHelper.Palette palette, boolean highlighted) { + return CreateLang.translateDirect("tooltip.holdForDescription", CreateLang.translateDirect("tooltip.keyShift") .withStyle(ChatFormatting.GRAY)) .withStyle(ChatFormatting.DARK_GRAY); } public static void addHint(List tooltip, String hintKey, Object... messageParams) { - Lang.translate(hintKey + ".title").style(ChatFormatting.GOLD).forGoggles(tooltip); - Component hint = Lang.translateDirect(hintKey); - List cutComponent = cutTextComponent(hint, Palette.GRAY_AND_WHITE); + CreateLang.translate(hintKey + ".title").style(ChatFormatting.GOLD).forGoggles(tooltip); + Component hint = CreateLang.translateDirect(hintKey); + List cutComponent = cutTextComponent(hint, FontHelper.Palette.GRAY_AND_WHITE); for (Component component : cutComponent) - Lang.builder().add(component).forGoggles(tooltip); + CreateLang.builder().add(component).forGoggles(tooltip); } public static String makeProgressBar(int length, int filledLength) { @@ -53,17 +53,17 @@ public class TooltipHelper { return Style.EMPTY.withColor(hex); } - public static List cutStringTextComponent(String s, Palette palette) { - return cutTextComponent(Components.literal(s), palette); + public static List cutStringTextComponent(String s, FontHelper.Palette palette) { + return cutTextComponent(Component.literal(s), palette); } - public static List cutTextComponent(Component c, Palette palette) { + public static List cutTextComponent(Component c, FontHelper.Palette palette) { return cutTextComponent(c, palette.primary(), palette.highlight()); } public static List cutStringTextComponent(String s, Style primaryStyle, Style highlightStyle) { - return cutTextComponent(Components.literal(s), primaryStyle, highlightStyle); + return cutTextComponent(Component.literal(s), primaryStyle, highlightStyle); } public static List cutTextComponent(Component c, Style primaryStyle, @@ -73,7 +73,7 @@ public class TooltipHelper { public static List cutStringTextComponent(String c, Style primaryStyle, Style highlightStyle, int indent) { - return cutTextComponent(Components.literal(c), primaryStyle, highlightStyle, indent); + return cutTextComponent(Component.literal(c), primaryStyle, highlightStyle, indent); } public static List cutTextComponent(Component c, Style primaryStyle, @@ -116,7 +116,7 @@ public class TooltipHelper { } // Format - MutableComponent lineStart = Components.literal(Strings.repeat(" ", indent)); + MutableComponent lineStart = Component.literal(Strings.repeat(" ", indent)); lineStart.withStyle(primaryStyle); List formattedLines = new ArrayList<>(lines.size()); Couple