diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 7726363..a2056ad 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,7 +1,7 @@ -name: Bug Report +name: Report A Bug description: >- - Please use this template when you have encountered a bug in this mod. Please note that only the latest mod version for Minecraft 1.18.2, 1.19.2 and 1.20.1 is supported. -title: '[Bug]: ' + Only Minecraft versions listed on the main branch are supported. Support may additionally vary based on the severity of an issue. +title: "[Bug]: " labels: ["bug"] assignees: - Fuzss @@ -14,35 +14,49 @@ body: id: loader attributes: label: Mod Loader (Required) - description: What mod loader are you using the mod on? + description: What mod loader are you using to play the mod? multiple: false options: - - Forge - - Fabric - - Quilt + - "⸺" + - "Fabric" + - "NeoForge" + - "Forge" + - "Quilt" validations: required: true - type: input id: minecraft attributes: - label: Minecraft Version (Required) - description: What is the Minecraft version you are playing with? + label: Minecraft Version(s) (Required) + description: What Minecraft version(s) are you using the play the mod? placeholder: ex. 1.20.1 validations: required: true - type: input id: version attributes: - label: Mod Version (Required) - description: What version of the mod are you playing with? + label: Mod Version(s) (Required) + description: What mod version(s) are you using to play? placeholder: ex. v8.0.0 validations: required: true + - type: dropdown + id: mods + attributes: + label: Other Mods Involved (Required) + description: Can your issue be reproduced with a minimal set of mods (only this mod + dependencies)? + multiple: false + options: + - "⸺" + - "Yes" + - "No" + validations: + required: true - type: textarea id: notes attributes: label: Notes (Required) - description: Please explain what happens because of the bug (including all the steps required to cause the bug), and what behavior you would expect if the bug were fixed. + description: Please explain what happens because of the issue (including all the steps required to cause it), and what behavior you would expect if the issue were fixed. placeholder: >- ex. @@ -60,6 +74,8 @@ body: - type: input id: latest-log attributes: - label: latest.log (Optional) - description: Please paste the url to your shared `latest.log` file. [To share your `latest.log` here, please follow these steps.](https://gist.github.com/Fuzss/866b384d353912986e37b17eeef7a285) - placeholder: ex. https://gist.github.com// \ No newline at end of file + label: latest.log (Required) + description: Please paste the url to your shared `latest.log` file. Note that issue reports without this file are difficult to solve and unlikely to be processed. [To share your `latest.log` here, please follow these steps.](https://gist.github.com/Fuzss/866b384d353912986e37b17eeef7a285) + placeholder: ex. https://gist.github.com// + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e0133b0..cbe96b9 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - - name: Questions + - name: Ask A Question url: https://lunapixel.studio/discord - about: "Please ask questions on the Luna Pixel Studios Discord in #fuzs-projects." \ No newline at end of file + about: "Join the Luna Pixel Studios Discord Server in the #fuzs-projects channel for additional support." \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml index 5ca6180..20493b1 100644 --- a/.github/ISSUE_TEMPLATE/crash.yml +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -1,8 +1,8 @@ -name: Crash Report +name: Submit A Crash Report description: >- - Please use this template when this mod has caused your game to crash. Please note that only the latest mod version for Minecraft 1.18.2, 1.19.2 and 1.20.1 is supported. -title: '[Crash]: ' -labels: ["bug"] + Only Minecraft versions listed on the main branch are supported. Support may additionally vary based on the severity of an issue. +title: "[Crash]: " +labels: ["bug", "high priority"] assignees: - Fuzss body: @@ -14,35 +14,49 @@ body: id: loader attributes: label: Mod Loader (Required) - description: What mod loader are you using the mod on? + description: What mod loader are you using to play the mod? multiple: false options: - - Forge - - Fabric - - Quilt + - "⸺" + - "Fabric" + - "NeoForge" + - "Forge" + - "Quilt" validations: required: true - type: input id: minecraft attributes: - label: Minecraft Version (Required) - description: What is the Minecraft version you are playing with? + label: Minecraft Version(s) (Required) + description: What Minecraft version(s) are you using the play the mod? placeholder: ex. 1.20.1 validations: required: true - type: input id: version attributes: - label: Mod Version (Required) - description: What version of the mod are you playing with? + label: Mod Version(s) (Required) + description: What mod version(s) are you using to play? placeholder: ex. v8.0.0 validations: required: true + - type: dropdown + id: mods + attributes: + label: Other Mods Involved (Required) + description: Can your issue be reproduced with a minimal set of mods (only this mod + dependencies)? + multiple: false + options: + - "⸺" + - "Yes" + - "No" + validations: + required: true - type: textarea id: notes attributes: label: Notes (Required) - description: Please explain which steps we need to do to reproduce the crash. Please include anything else you'd like to say about the crash. + description: Please explain which steps we need to do to reproduce the issue. Please include anything else you'd like to say about it. placeholder: >- ex. @@ -58,7 +72,7 @@ body: attributes: label: Crash Report (Required) description: >- - Please paste the url to your shared crash report. [To share your crash report here, please follow these steps.](https://gist.github.com/Fuzss/9692f6ed5e8cca485a58004c28c9045b) + Please paste the url to your shared crash report. Note that issue reports without this file are difficult to solve and unlikely to be processed. [To share your crash report here, please follow these steps.](https://gist.github.com/Fuzss/9692f6ed5e8cca485a58004c28c9045b) placeholder: ex. https://gist.github.com// validations: required: true @@ -67,4 +81,4 @@ body: attributes: label: latest.log (Optional) description: Please paste the url to your shared `latest.log` file. [To share your `latest.log` here, please follow these steps.](https://gist.github.com/Fuzss/866b384d353912986e37b17eeef7a285) - placeholder: ex. https://gist.github.com// \ No newline at end of file + placeholder: ex. https://gist.github.com// diff --git a/.github/ISSUE_TEMPLATE/suggestion.yml b/.github/ISSUE_TEMPLATE/suggestion.yml index 0eb9a33..2a25400 100644 --- a/.github/ISSUE_TEMPLATE/suggestion.yml +++ b/.github/ISSUE_TEMPLATE/suggestion.yml @@ -1,11 +1,41 @@ -name: Suggestion +name: Leave A Suggestion description: >- - Please use this template when you want to suggest a feature. Please do not ask for mod updates or ports, they will come when they are ready. -title: '[Suggestion]: ' + Please do not ask for mod updates or ports, they will come when they are ready. +title: "[Suggestion]: " labels: ["enhancement"] assignees: - Fuzss body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this issue report! + - type: dropdown + id: loader + attributes: + label: Mod Loader (Optional) + description: What mod loader are you using to play the mod? + multiple: false + options: + - "⸺" + - "Fabric" + - "NeoForge" + - "Forge" + - "Quilt" + validations: + required: true + - type: input + id: minecraft + attributes: + label: Minecraft Version(s) (Optional) + description: What Minecraft version(s) are you using the play the mod? + placeholder: ex. 1.20.1 + - type: input + id: version + attributes: + label: Mod Version(s) (Optional) + description: What mod version(s) are you using to play? + placeholder: ex. v8.0.0 - type: textarea id: suggestion attributes: diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 311bce0..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/scopes/Fabric_sources.xml b/1.18.2/.idea/scopes/Fabric_sources.xml similarity index 100% rename from .idea/scopes/Fabric_sources.xml rename to 1.18.2/.idea/scopes/Fabric_sources.xml diff --git a/.idea/scopes/Forge_sources.xml b/1.18.2/.idea/scopes/Forge_sources.xml similarity index 100% rename from .idea/scopes/Forge_sources.xml rename to 1.18.2/.idea/scopes/Forge_sources.xml diff --git a/1.18/CHANGELOG.md b/1.18.2/CHANGELOG.md similarity index 100% rename from 1.18/CHANGELOG.md rename to 1.18.2/CHANGELOG.md diff --git a/1.18/Common/build.gradle b/1.18.2/Common/build.gradle similarity index 100% rename from 1.18/Common/build.gradle rename to 1.18.2/Common/build.gradle diff --git a/1.18/Common/src/main/java/fuzs/examplemod/ExampleMod.java b/1.18.2/Common/src/main/java/fuzs/examplemod/ExampleMod.java similarity index 100% rename from 1.18/Common/src/main/java/fuzs/examplemod/ExampleMod.java rename to 1.18.2/Common/src/main/java/fuzs/examplemod/ExampleMod.java diff --git a/1.18/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java b/1.18.2/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java similarity index 100% rename from 1.18/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java rename to 1.18.2/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java diff --git a/1.18/Common/src/main/resources/examplemod.common.mixins.json b/1.18.2/Common/src/main/resources/examplemod.common.mixins.json similarity index 100% rename from 1.18/Common/src/main/resources/examplemod.common.mixins.json rename to 1.18.2/Common/src/main/resources/examplemod.common.mixins.json diff --git a/1.18/Common/src/main/resources/mod_banner.png b/1.18.2/Common/src/main/resources/mod_banner.png similarity index 100% rename from 1.18/Common/src/main/resources/mod_banner.png rename to 1.18.2/Common/src/main/resources/mod_banner.png diff --git a/1.18/Common/src/main/resources/mod_logo.png b/1.18.2/Common/src/main/resources/mod_logo.png similarity index 100% rename from 1.18/Common/src/main/resources/mod_logo.png rename to 1.18.2/Common/src/main/resources/mod_logo.png diff --git a/1.18/Common/src/main/resources/pack.mcmeta b/1.18.2/Common/src/main/resources/pack.mcmeta similarity index 100% rename from 1.18/Common/src/main/resources/pack.mcmeta rename to 1.18.2/Common/src/main/resources/pack.mcmeta diff --git a/1.18/Fabric/build.gradle b/1.18.2/Fabric/build.gradle similarity index 100% rename from 1.18/Fabric/build.gradle rename to 1.18.2/Fabric/build.gradle diff --git a/1.18/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java b/1.18.2/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java similarity index 100% rename from 1.18/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java rename to 1.18.2/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java diff --git a/1.18/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java b/1.18.2/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java similarity index 100% rename from 1.18/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java rename to 1.18.2/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java diff --git a/1.18/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java b/1.18.2/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java similarity index 100% rename from 1.18/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java rename to 1.18.2/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java diff --git a/1.18/Fabric/src/main/resources/examplemod.fabric.mixins.json b/1.18.2/Fabric/src/main/resources/examplemod.fabric.mixins.json similarity index 100% rename from 1.18/Fabric/src/main/resources/examplemod.fabric.mixins.json rename to 1.18.2/Fabric/src/main/resources/examplemod.fabric.mixins.json diff --git a/1.18/Fabric/src/main/resources/fabric.mod.json b/1.18.2/Fabric/src/main/resources/fabric.mod.json similarity index 100% rename from 1.18/Fabric/src/main/resources/fabric.mod.json rename to 1.18.2/Fabric/src/main/resources/fabric.mod.json diff --git a/1.18/Forge/build.gradle b/1.18.2/Forge/build.gradle similarity index 100% rename from 1.18/Forge/build.gradle rename to 1.18.2/Forge/build.gradle diff --git a/1.18/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java b/1.18.2/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java similarity index 100% rename from 1.18/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java rename to 1.18.2/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java diff --git a/1.18/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java b/1.18.2/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java similarity index 100% rename from 1.18/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java rename to 1.18.2/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java diff --git a/1.18/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java b/1.18.2/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java similarity index 100% rename from 1.18/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java rename to 1.18.2/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java diff --git a/1.18/Forge/src/main/resources/META-INF/mods.toml b/1.18.2/Forge/src/main/resources/META-INF/mods.toml similarity index 100% rename from 1.18/Forge/src/main/resources/META-INF/mods.toml rename to 1.18.2/Forge/src/main/resources/META-INF/mods.toml diff --git a/1.18/Forge/src/main/resources/examplemod.forge.mixins.json b/1.18.2/Forge/src/main/resources/examplemod.forge.mixins.json similarity index 100% rename from 1.18/Forge/src/main/resources/examplemod.forge.mixins.json rename to 1.18.2/Forge/src/main/resources/examplemod.forge.mixins.json diff --git a/1.18/build.gradle b/1.18.2/build.gradle similarity index 100% rename from 1.18/build.gradle rename to 1.18.2/build.gradle diff --git a/1.18/gradle.properties b/1.18.2/gradle.properties similarity index 100% rename from 1.18/gradle.properties rename to 1.18.2/gradle.properties diff --git a/1.18/gradle/wrapper/gradle-wrapper.jar b/1.18.2/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from 1.18/gradle/wrapper/gradle-wrapper.jar rename to 1.18.2/gradle/wrapper/gradle-wrapper.jar diff --git a/1.18/gradle/wrapper/gradle-wrapper.properties b/1.18.2/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from 1.18/gradle/wrapper/gradle-wrapper.properties rename to 1.18.2/gradle/wrapper/gradle-wrapper.properties diff --git a/1.18/gradlew b/1.18.2/gradlew similarity index 100% rename from 1.18/gradlew rename to 1.18.2/gradlew diff --git a/1.18/gradlew.bat b/1.18.2/gradlew.bat similarity index 100% rename from 1.18/gradlew.bat rename to 1.18.2/gradlew.bat diff --git a/1.18/settings.gradle b/1.18.2/settings.gradle similarity index 100% rename from 1.18/settings.gradle rename to 1.18.2/settings.gradle diff --git a/1.18/.idea/scopes/Fabric_sources.xml b/1.19.2/.idea/scopes/Fabric_sources.xml similarity index 100% rename from 1.18/.idea/scopes/Fabric_sources.xml rename to 1.19.2/.idea/scopes/Fabric_sources.xml diff --git a/1.18/.idea/scopes/Forge_sources.xml b/1.19.2/.idea/scopes/Forge_sources.xml similarity index 100% rename from 1.18/.idea/scopes/Forge_sources.xml rename to 1.19.2/.idea/scopes/Forge_sources.xml diff --git a/1.19/CHANGELOG.md b/1.19.2/CHANGELOG.md similarity index 100% rename from 1.19/CHANGELOG.md rename to 1.19.2/CHANGELOG.md diff --git a/1.19/Common/build.gradle b/1.19.2/Common/build.gradle similarity index 100% rename from 1.19/Common/build.gradle rename to 1.19.2/Common/build.gradle diff --git a/1.19/Common/src/main/java/fuzs/examplemod/ExampleMod.java b/1.19.2/Common/src/main/java/fuzs/examplemod/ExampleMod.java similarity index 100% rename from 1.19/Common/src/main/java/fuzs/examplemod/ExampleMod.java rename to 1.19.2/Common/src/main/java/fuzs/examplemod/ExampleMod.java diff --git a/1.19/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java b/1.19.2/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java similarity index 100% rename from 1.19/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java rename to 1.19.2/Common/src/main/java/fuzs/examplemod/client/ExampleModClient.java diff --git a/1.19/Common/src/main/resources/examplemod.common.mixins.json b/1.19.2/Common/src/main/resources/examplemod.common.mixins.json similarity index 100% rename from 1.19/Common/src/main/resources/examplemod.common.mixins.json rename to 1.19.2/Common/src/main/resources/examplemod.common.mixins.json diff --git a/1.19/Common/src/main/resources/mod_banner.png b/1.19.2/Common/src/main/resources/mod_banner.png similarity index 100% rename from 1.19/Common/src/main/resources/mod_banner.png rename to 1.19.2/Common/src/main/resources/mod_banner.png diff --git a/1.19/Common/src/main/resources/mod_logo.png b/1.19.2/Common/src/main/resources/mod_logo.png similarity index 100% rename from 1.19/Common/src/main/resources/mod_logo.png rename to 1.19.2/Common/src/main/resources/mod_logo.png diff --git a/1.19/Common/src/main/resources/pack.mcmeta b/1.19.2/Common/src/main/resources/pack.mcmeta similarity index 100% rename from 1.19/Common/src/main/resources/pack.mcmeta rename to 1.19.2/Common/src/main/resources/pack.mcmeta diff --git a/1.19/Fabric/build.gradle b/1.19.2/Fabric/build.gradle similarity index 100% rename from 1.19/Fabric/build.gradle rename to 1.19.2/Fabric/build.gradle diff --git a/1.19/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java b/1.19.2/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java similarity index 100% rename from 1.19/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java rename to 1.19.2/Fabric/src/main/java/fuzs/examplemod/ExampleModFabric.java diff --git a/1.19/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java b/1.19.2/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java similarity index 100% rename from 1.19/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java rename to 1.19.2/Fabric/src/main/java/fuzs/examplemod/client/ExampleModFabricClient.java diff --git a/1.19/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java b/1.19.2/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java similarity index 100% rename from 1.19/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java rename to 1.19.2/Fabric/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java diff --git a/1.19/Fabric/src/main/resources/examplemod.fabric.mixins.json b/1.19.2/Fabric/src/main/resources/examplemod.fabric.mixins.json similarity index 100% rename from 1.19/Fabric/src/main/resources/examplemod.fabric.mixins.json rename to 1.19.2/Fabric/src/main/resources/examplemod.fabric.mixins.json diff --git a/1.19/Fabric/src/main/resources/fabric.mod.json b/1.19.2/Fabric/src/main/resources/fabric.mod.json similarity index 100% rename from 1.19/Fabric/src/main/resources/fabric.mod.json rename to 1.19.2/Fabric/src/main/resources/fabric.mod.json diff --git a/1.19/Forge/build.gradle b/1.19.2/Forge/build.gradle similarity index 100% rename from 1.19/Forge/build.gradle rename to 1.19.2/Forge/build.gradle diff --git a/1.19/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java b/1.19.2/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java similarity index 100% rename from 1.19/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java rename to 1.19.2/Forge/src/main/java/fuzs/examplemod/ExampleModForge.java diff --git a/1.19/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java b/1.19.2/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java similarity index 100% rename from 1.19/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java rename to 1.19.2/Forge/src/main/java/fuzs/examplemod/client/ExampleModForgeClient.java diff --git a/1.19/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java b/1.19.2/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java similarity index 100% rename from 1.19/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java rename to 1.19.2/Forge/src/main/java/fuzs/examplemod/mixin/ModMixinConfigPlugin.java diff --git a/1.19/Forge/src/main/resources/META-INF/mods.toml b/1.19.2/Forge/src/main/resources/META-INF/mods.toml similarity index 100% rename from 1.19/Forge/src/main/resources/META-INF/mods.toml rename to 1.19.2/Forge/src/main/resources/META-INF/mods.toml diff --git a/1.19/Forge/src/main/resources/examplemod.forge.mixins.json b/1.19.2/Forge/src/main/resources/examplemod.forge.mixins.json similarity index 100% rename from 1.19/Forge/src/main/resources/examplemod.forge.mixins.json rename to 1.19.2/Forge/src/main/resources/examplemod.forge.mixins.json diff --git a/1.19/build.gradle b/1.19.2/build.gradle similarity index 100% rename from 1.19/build.gradle rename to 1.19.2/build.gradle diff --git a/1.19/gradle.properties b/1.19.2/gradle.properties similarity index 100% rename from 1.19/gradle.properties rename to 1.19.2/gradle.properties diff --git a/1.19/gradle/wrapper/gradle-wrapper.jar b/1.19.2/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from 1.19/gradle/wrapper/gradle-wrapper.jar rename to 1.19.2/gradle/wrapper/gradle-wrapper.jar diff --git a/1.19/gradle/wrapper/gradle-wrapper.properties b/1.19.2/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from 1.19/gradle/wrapper/gradle-wrapper.properties rename to 1.19.2/gradle/wrapper/gradle-wrapper.properties diff --git a/1.19/gradlew b/1.19.2/gradlew similarity index 100% rename from 1.19/gradlew rename to 1.19.2/gradlew diff --git a/1.19/gradlew.bat b/1.19.2/gradlew.bat similarity index 100% rename from 1.19/gradlew.bat rename to 1.19.2/gradlew.bat diff --git a/1.19/settings.gradle b/1.19.2/settings.gradle similarity index 100% rename from 1.19/settings.gradle rename to 1.19.2/settings.gradle diff --git a/1.19/.idea/scopes/Fabric_sources.xml b/1.20.1/.idea/scopes/Fabric_sources.xml similarity index 100% rename from 1.19/.idea/scopes/Fabric_sources.xml rename to 1.20.1/.idea/scopes/Fabric_sources.xml diff --git a/1.19/.idea/scopes/Forge_sources.xml b/1.20.1/.idea/scopes/Forge_sources.xml similarity index 100% rename from 1.19/.idea/scopes/Forge_sources.xml rename to 1.20.1/.idea/scopes/Forge_sources.xml diff --git a/1.20/CHANGELOG.md b/1.20.1/CHANGELOG.md similarity index 100% rename from 1.20/CHANGELOG.md rename to 1.20.1/CHANGELOG.md diff --git a/1.20/Common/build.gradle b/1.20.1/Common/build.gradle similarity index 100% rename from 1.20/Common/build.gradle rename to 1.20.1/Common/build.gradle diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/WorkbenchBlockEntityRenderer.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/WorkbenchBlockEntityRenderer.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/WorkbenchBlockEntityRenderer.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/WorkbenchBlockEntityRenderer.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/config/JsonConfigBuilder.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/config/JsonConfigBuilder.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/config/JsonConfigBuilder.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/config/JsonConfigBuilder.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/core/CommonAbstractions.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/core/CommonAbstractions.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/core/CommonAbstractions.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/core/CommonAbstractions.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/handler/OpenMenuHandler.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/handler/OpenMenuHandler.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/handler/OpenMenuHandler.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/handler/OpenMenuHandler.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/mixin/CraftingTableBlockMixin.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/mixin/CraftingTableBlockMixin.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/mixin/CraftingTableBlockMixin.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/mixin/CraftingTableBlockMixin.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/mixin/accessor/CraftingMenuAccessor.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/mixin/accessor/CraftingMenuAccessor.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/mixin/accessor/CraftingMenuAccessor.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/mixin/accessor/CraftingMenuAccessor.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/util/MathHelper.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/util/MathHelper.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/util/MathHelper.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/util/MathHelper.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/world/inventory/ForwardingCraftingContainer.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/world/inventory/ForwardingCraftingContainer.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/world/inventory/ForwardingCraftingContainer.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/world/inventory/ForwardingCraftingContainer.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/world/inventory/ModCraftingMenu.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/world/inventory/ModCraftingMenu.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/world/inventory/ModCraftingMenu.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/world/inventory/ModCraftingMenu.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/world/level/block/VisualCraftingTableBlock.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/VisualCraftingTableBlock.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/world/level/block/VisualCraftingTableBlock.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/VisualCraftingTableBlock.java diff --git a/1.20/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java b/1.20.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java similarity index 100% rename from 1.20/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java rename to 1.20.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java diff --git a/1.20/Common/src/main/resources/mod_banner.png b/1.20.1/Common/src/main/resources/mod_banner.png similarity index 100% rename from 1.20/Common/src/main/resources/mod_banner.png rename to 1.20.1/Common/src/main/resources/mod_banner.png diff --git a/1.20/Common/src/main/resources/mod_logo.png b/1.20.1/Common/src/main/resources/mod_logo.png similarity index 100% rename from 1.20/Common/src/main/resources/mod_logo.png rename to 1.20.1/Common/src/main/resources/mod_logo.png diff --git a/1.20/Common/src/main/resources/pack.mcmeta b/1.20.1/Common/src/main/resources/pack.mcmeta similarity index 100% rename from 1.20/Common/src/main/resources/pack.mcmeta rename to 1.20.1/Common/src/main/resources/pack.mcmeta diff --git a/1.20/Common/src/main/resources/visualworkbench.common.mixins.json b/1.20.1/Common/src/main/resources/visualworkbench.common.mixins.json similarity index 100% rename from 1.20/Common/src/main/resources/visualworkbench.common.mixins.json rename to 1.20.1/Common/src/main/resources/visualworkbench.common.mixins.json diff --git a/1.20/Fabric/build.gradle b/1.20.1/Fabric/build.gradle similarity index 100% rename from 1.20/Fabric/build.gradle rename to 1.20.1/Fabric/build.gradle diff --git a/1.20/Fabric/src/main/java/fuzs/visualworkbench/VisualWorkbenchFabric.java b/1.20.1/Fabric/src/main/java/fuzs/visualworkbench/VisualWorkbenchFabric.java similarity index 100% rename from 1.20/Fabric/src/main/java/fuzs/visualworkbench/VisualWorkbenchFabric.java rename to 1.20.1/Fabric/src/main/java/fuzs/visualworkbench/VisualWorkbenchFabric.java diff --git a/1.20/Fabric/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchFabricClient.java b/1.20.1/Fabric/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchFabricClient.java similarity index 100% rename from 1.20/Fabric/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchFabricClient.java rename to 1.20.1/Fabric/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchFabricClient.java diff --git a/1.20/Fabric/src/main/java/fuzs/visualworkbench/core/FabricAbstractions.java b/1.20.1/Fabric/src/main/java/fuzs/visualworkbench/core/FabricAbstractions.java similarity index 100% rename from 1.20/Fabric/src/main/java/fuzs/visualworkbench/core/FabricAbstractions.java rename to 1.20.1/Fabric/src/main/java/fuzs/visualworkbench/core/FabricAbstractions.java diff --git a/1.20/Fabric/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java b/1.20.1/Fabric/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java similarity index 100% rename from 1.20/Fabric/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java rename to 1.20.1/Fabric/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java diff --git a/1.20/Fabric/src/main/java/fuzs/visualworkbench/mixin/accessor/BlockEntityTypeFabricAccessor.java b/1.20.1/Fabric/src/main/java/fuzs/visualworkbench/mixin/accessor/BlockEntityTypeFabricAccessor.java similarity index 100% rename from 1.20/Fabric/src/main/java/fuzs/visualworkbench/mixin/accessor/BlockEntityTypeFabricAccessor.java rename to 1.20.1/Fabric/src/main/java/fuzs/visualworkbench/mixin/accessor/BlockEntityTypeFabricAccessor.java diff --git a/1.20/Fabric/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions b/1.20.1/Fabric/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions similarity index 100% rename from 1.20/Fabric/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions rename to 1.20.1/Fabric/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions diff --git a/1.20/Fabric/src/main/resources/fabric.mod.json b/1.20.1/Fabric/src/main/resources/fabric.mod.json similarity index 100% rename from 1.20/Fabric/src/main/resources/fabric.mod.json rename to 1.20.1/Fabric/src/main/resources/fabric.mod.json diff --git a/1.20/Fabric/src/main/resources/visualworkbench.fabric.mixins.json b/1.20.1/Fabric/src/main/resources/visualworkbench.fabric.mixins.json similarity index 100% rename from 1.20/Fabric/src/main/resources/visualworkbench.fabric.mixins.json rename to 1.20.1/Fabric/src/main/resources/visualworkbench.fabric.mixins.json diff --git a/1.20/Forge/build.gradle b/1.20.1/Forge/build.gradle similarity index 100% rename from 1.20/Forge/build.gradle rename to 1.20.1/Forge/build.gradle diff --git a/1.20/Forge/src/main/java/fuzs/visualworkbench/VisualWorkbenchForge.java b/1.20.1/Forge/src/main/java/fuzs/visualworkbench/VisualWorkbenchForge.java similarity index 100% rename from 1.20/Forge/src/main/java/fuzs/visualworkbench/VisualWorkbenchForge.java rename to 1.20.1/Forge/src/main/java/fuzs/visualworkbench/VisualWorkbenchForge.java diff --git a/1.20/Forge/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchForgeClient.java b/1.20.1/Forge/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchForgeClient.java similarity index 100% rename from 1.20/Forge/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchForgeClient.java rename to 1.20.1/Forge/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchForgeClient.java diff --git a/1.20/Forge/src/main/java/fuzs/visualworkbench/core/ForgeAbstractions.java b/1.20.1/Forge/src/main/java/fuzs/visualworkbench/core/ForgeAbstractions.java similarity index 100% rename from 1.20/Forge/src/main/java/fuzs/visualworkbench/core/ForgeAbstractions.java rename to 1.20.1/Forge/src/main/java/fuzs/visualworkbench/core/ForgeAbstractions.java diff --git a/1.20/Forge/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java b/1.20.1/Forge/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java similarity index 100% rename from 1.20/Forge/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java rename to 1.20.1/Forge/src/main/java/fuzs/visualworkbench/mixin/ModMixinConfigPlugin.java diff --git a/1.20/Forge/src/main/resources/META-INF/mods.toml b/1.20.1/Forge/src/main/resources/META-INF/mods.toml similarity index 100% rename from 1.20/Forge/src/main/resources/META-INF/mods.toml rename to 1.20.1/Forge/src/main/resources/META-INF/mods.toml diff --git a/1.20/Forge/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions b/1.20.1/Forge/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions similarity index 100% rename from 1.20/Forge/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions rename to 1.20.1/Forge/src/main/resources/META-INF/services/fuzs.visualworkbench.core.CommonAbstractions diff --git a/1.20/build.gradle b/1.20.1/build.gradle similarity index 100% rename from 1.20/build.gradle rename to 1.20.1/build.gradle diff --git a/1.20/gradle.properties b/1.20.1/gradle.properties similarity index 100% rename from 1.20/gradle.properties rename to 1.20.1/gradle.properties diff --git a/1.20/gradle/wrapper/gradle-wrapper.jar b/1.20.1/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from 1.20/gradle/wrapper/gradle-wrapper.jar rename to 1.20.1/gradle/wrapper/gradle-wrapper.jar diff --git a/1.20/gradle/wrapper/gradle-wrapper.properties b/1.20.1/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from 1.20/gradle/wrapper/gradle-wrapper.properties rename to 1.20.1/gradle/wrapper/gradle-wrapper.properties diff --git a/1.20/gradlew b/1.20.1/gradlew similarity index 100% rename from 1.20/gradlew rename to 1.20.1/gradlew diff --git a/1.20/gradlew.bat b/1.20.1/gradlew.bat similarity index 100% rename from 1.20/gradlew.bat rename to 1.20.1/gradlew.bat diff --git a/1.20/settings.gradle b/1.20.1/settings.gradle similarity index 100% rename from 1.20/settings.gradle rename to 1.20.1/settings.gradle diff --git a/1.20.4/CHANGELOG.md b/1.20.4/CHANGELOG.md new file mode 100644 index 0000000..eaf4a33 --- /dev/null +++ b/1.20.4/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v20.4.2-1.20.4] - 2024-05-16 +### Fixed +- Fix right-clicking halving recipe output + +## [v20.4.1-1.20.4] - 2024-02-05 +### Fixed +- Fix rendered crafting tables contents failing to rotate towards the closest player + +## [v20.4.0-1.20.4] - 2024-01-27 +- Rewritten for Minecraft 1.20.4 +- All modded crafting tables are supported automatically, use `visualworkbench:unaltered_workbenches` for individual exclusions +- New implementation should work much more reliably with mods like CraftTweaker +- Greatly reduce number of update packets send to clients +- Publish for NeoForge diff --git a/1.20.4/Common/build.gradle b/1.20.4/Common/build.gradle new file mode 100644 index 0000000..141a7aa --- /dev/null +++ b/1.20.4/Common/build.gradle @@ -0,0 +1,13 @@ +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/v2/common.gradle" + +dependencies { + // Puzzles Lib + modApi libs.puzzleslib.common + + // Just Enough Items + compileOnly libs.jeiapi.common +} + +tasks.withType(net.fabricmc.loom.task.AbstractRemapJarTask).configureEach { + targetNamespace = "named" +} diff --git a/1.20.4/Common/src/generated/resources/.cache/190dc8cc9e260d5273a6d094a2d5cfe3ccdbd9b6 b/1.20.4/Common/src/generated/resources/.cache/190dc8cc9e260d5273a6d094a2d5cfe3ccdbd9b6 new file mode 100644 index 0000000..c9c8c3d --- /dev/null +++ b/1.20.4/Common/src/generated/resources/.cache/190dc8cc9e260d5273a6d094a2d5cfe3ccdbd9b6 @@ -0,0 +1,2 @@ +// 1.20.4 2024-01-24T23:42:33.58688 Language (en_us) +df9da4d2378015f87d23586f120ab375074989f6 assets/visualworkbench/lang/en_us.json diff --git a/1.20.4/Common/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 b/1.20.4/Common/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 new file mode 100644 index 0000000..3bdc066 --- /dev/null +++ b/1.20.4/Common/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 @@ -0,0 +1,2 @@ +// 1.20.4 2024-01-24T23:42:33.58585 Tags for minecraft:block mod id vanilla +d00da1153a305b41cd0709e40bbab70031f6f7fb data/visualworkbench/tags/blocks/unaltered_workbenches.json diff --git a/1.20.4/Common/src/generated/resources/assets/visualworkbench/lang/en_us.json b/1.20.4/Common/src/generated/resources/assets/visualworkbench/lang/en_us.json new file mode 100644 index 0000000..89746d3 --- /dev/null +++ b/1.20.4/Common/src/generated/resources/assets/visualworkbench/lang/en_us.json @@ -0,0 +1,3 @@ +{ + "container.invalidBlock": "Unable to open. Break and replace to use." +} \ No newline at end of file diff --git a/1.20.4/Common/src/generated/resources/data/visualworkbench/tags/blocks/unaltered_workbenches.json b/1.20.4/Common/src/generated/resources/data/visualworkbench/tags/blocks/unaltered_workbenches.json new file mode 100644 index 0000000..a9e9b4d --- /dev/null +++ b/1.20.4/Common/src/generated/resources/data/visualworkbench/tags/blocks/unaltered_workbenches.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:smithing_table", + "minecraft:fletching_table" + ] +} \ No newline at end of file diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java new file mode 100644 index 0000000..1ae89c2 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java @@ -0,0 +1,40 @@ +package fuzs.visualworkbench; + +import fuzs.puzzleslib.api.config.v3.ConfigHolder; +import fuzs.puzzleslib.api.core.v1.ModConstructor; +import fuzs.puzzleslib.api.event.v1.RegistryEntryAddedCallback; +import fuzs.puzzleslib.api.event.v1.core.EventPhase; +import fuzs.puzzleslib.api.event.v1.entity.player.PlayerInteractEvents; +import fuzs.puzzleslib.api.event.v1.server.TagsUpdatedCallback; +import fuzs.visualworkbench.config.ClientConfig; +import fuzs.visualworkbench.config.ServerConfig; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import fuzs.visualworkbench.init.ModRegistry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VisualWorkbench implements ModConstructor { + public static final String MOD_ID = "visualworkbench"; + public static final String MOD_NAME = "Visual Workbench"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_NAME); + + public static final ConfigHolder CONFIG = ConfigHolder.builder(MOD_ID).client(ClientConfig.class).server(ServerConfig.class); + + @Override + public void onConstructMod() { + ModRegistry.touch(); + registerHandlers(); + } + + private static void registerHandlers() { + RegistryEntryAddedCallback.registryEntryAdded(Registries.BLOCK).register(BlockConversionHandler::onRegistryEntryAdded); + PlayerInteractEvents.USE_BLOCK.register(BlockConversionHandler::onUseBlock); + TagsUpdatedCallback.EVENT.register(EventPhase.FIRST, BlockConversionHandler::onTagsUpdated); + } + + public static ResourceLocation id(String path) { + return new ResourceLocation(MOD_ID, path); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java new file mode 100644 index 0000000..502fdc0 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java @@ -0,0 +1,44 @@ +package fuzs.visualworkbench.client; + +import fuzs.puzzleslib.api.client.core.v1.ClientModConstructor; +import fuzs.puzzleslib.api.client.core.v1.context.BlockEntityRenderersContext; +import fuzs.puzzleslib.api.client.core.v1.context.MenuScreensContext; +import fuzs.puzzleslib.api.client.event.v1.ModelEvents; +import fuzs.puzzleslib.api.core.v1.context.PackRepositorySourcesContext; +import fuzs.puzzleslib.api.event.v1.LoadCompleteCallback; +import fuzs.puzzleslib.api.resources.v1.DynamicPackResources; +import fuzs.puzzleslib.api.resources.v1.PackResourcesHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.client.handler.BlockModelHandler; +import fuzs.visualworkbench.client.renderer.blockentity.CraftingTableBlockEntityRenderer; +import fuzs.visualworkbench.data.client.DynamicModelProvider; +import fuzs.visualworkbench.init.ModRegistry; +import net.minecraft.client.gui.screens.inventory.CraftingScreen; + +public class VisualWorkbenchClient implements ClientModConstructor { + + @Override + public void onConstructMod() { + registerHandlers(); + } + + private static void registerHandlers() { + ModelEvents.MODIFY_UNBAKED_MODEL.register(BlockModelHandler::onModifyUnbakedModel); + LoadCompleteCallback.EVENT.register(BlockModelHandler::onLoadComplete); + } + + @Override + public void onRegisterMenuScreens(MenuScreensContext context) { + context.registerMenuScreen(ModRegistry.CRAFTING_MENU_TYPE.value(), CraftingScreen::new); + } + + @Override + public void onRegisterBlockEntityRenderers(BlockEntityRenderersContext context) { + context.registerBlockEntityRenderer(ModRegistry.CRAFTING_TABLE_BLOCK_ENTITY.value(), CraftingTableBlockEntityRenderer::new); + } + + @Override + public void onAddResourcePackFinders(PackRepositorySourcesContext context) { + context.addRepositorySource(PackResourcesHelper.buildClientPack(VisualWorkbench.id("default_block_models"), DynamicPackResources.create(DynamicModelProvider::new), true)); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/handler/BlockModelHandler.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/handler/BlockModelHandler.java new file mode 100644 index 0000000..8725d34 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/handler/BlockModelHandler.java @@ -0,0 +1,76 @@ +package fuzs.visualworkbench.client.handler; + +import com.google.common.base.Suppliers; +import com.google.common.collect.Maps; +import fuzs.puzzleslib.api.client.core.v1.ClientAbstractions; +import fuzs.puzzleslib.api.event.v1.core.EventResultHolder; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import net.minecraft.Util; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.BlockModelShaper; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.Property; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class BlockModelHandler { + private static final Supplier> MODEL_LOCATIONS; + + static { + MODEL_LOCATIONS = Suppliers.memoize(() -> { + return BlockConversionHandler.BLOCK_CONVERSIONS.inverse().entrySet().stream().flatMap(entry -> { + return convertAllBlockStates(entry.getKey(), entry.getValue()).entrySet().stream(); + }).collect(Util.toMap()); + }); + } + + public static void onLoadComplete() { + // run a custom implementation here, the appropriate method in client mod constructor runs together with other mods, so we might miss some entries + for (Map.Entry entry : BlockConversionHandler.BLOCK_CONVERSIONS.entrySet()) { + RenderType renderType = ClientAbstractions.INSTANCE.getRenderType(entry.getKey()); + ClientAbstractions.INSTANCE.registerRenderType(entry.getValue(), renderType); + } + } + + public static EventResultHolder onModifyUnbakedModel(ResourceLocation modelLocation, Supplier unbakedModel, Function modelGetter, BiConsumer modelAdder) { + if (MODEL_LOCATIONS.get().containsKey(modelLocation)) { + return EventResultHolder.interrupt(modelGetter.apply(MODEL_LOCATIONS.get().get(modelLocation))); + } else { + return EventResultHolder.pass(); + } + } + + private static Map convertAllBlockStates(Block oldBlock, Block newBlock) { + Map modelLocations = Maps.newHashMap(); + for (BlockState oldBlockState : oldBlock.getStateDefinition().getPossibleStates()) { + BlockState newBlockState = convertBlockState(newBlock.getStateDefinition(), oldBlockState); + modelLocations.put(BlockModelShaper.stateToModelLocation(oldBlockState), BlockModelShaper.stateToModelLocation(newBlockState)); + } + return modelLocations; + } + + private static BlockState convertBlockState(StateDefinition newStateDefinition, BlockState oldBlockState) { + BlockState newBlockState = newStateDefinition.any(); + for (Map.Entry, Comparable> entry : oldBlockState.getValues().entrySet()) { + newBlockState = setBlockStateValue(entry.getKey(), entry.getValue(), newStateDefinition::getProperty, newBlockState); + } + return newBlockState; + } + + private static , V extends T> BlockState setBlockStateValue(Property oldProperty, Comparable oldValue, Function> propertyGetter, BlockState blockState) { + Property newProperty = propertyGetter.apply(oldProperty.getName()); + if (newProperty != null) { + return blockState.setValue((Property) newProperty, (V) oldValue); + } + return blockState; + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/CraftingTableBlockEntityRenderer.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/CraftingTableBlockEntityRenderer.java new file mode 100644 index 0000000..da38e5f --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/CraftingTableBlockEntityRenderer.java @@ -0,0 +1,95 @@ +package fuzs.visualworkbench.client.renderer.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableAnimationController; +import fuzs.visualworkbench.world.level.block.entity.WorkbenchVisualsProvider; +import fuzs.visualworkbench.config.ClientConfig; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.util.Mth; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.Nullable; + +public class CraftingTableBlockEntityRenderer implements BlockEntityRenderer { + private final ItemRenderer itemRenderer; + + public CraftingTableBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + this.itemRenderer = context.getItemRenderer(); + } + + @Override + public void render(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight, int packedOverlay) { + // light is normally always 0 since it checks inside the crafting table block which is solid, but contents are rendered in the block above + packedLight = blockEntity.getLevel() != null ? LevelRenderer.getLightColor(blockEntity.getLevel(), blockEntity.getBlockPos().above()) : 15728880; + for (int i = 0; i < blockEntity.getContainerSize(); ++i) { + ItemStack itemStack = blockEntity.getItem(i); + if (!itemStack.isEmpty()) { + this.renderIngredientItem(blockEntity, partialTick, poseStack, multiBufferSource, packedLight, packedOverlay, i, itemStack); + } + } + ItemStack itemStack = blockEntity.getCraftingResult(); + if (!itemStack.isEmpty()) { + this.renderResultItem(itemStack, blockEntity.getLevel(), blockEntity.getAnimationController().ticks + partialTick, poseStack, multiBufferSource, packedLight); + } + } + + private void renderIngredientItem(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight, int packedOverlay, int i, ItemStack itemStack) { + poseStack.pushPose(); + if (VisualWorkbench.CONFIG.get(ClientConfig.class).flatRendering) { + this.setupFlatRenderer(blockEntity.getAnimationController(), partialTick, poseStack, itemStack, i); + } else { + this.setupFloatingRenderer(blockEntity.getAnimationController(), partialTick, poseStack, itemStack, i); + } + this.itemRenderer.renderStatic(itemStack, ItemDisplayContext.FIXED, packedLight, packedOverlay, poseStack, multiBufferSource, blockEntity.getLevel(), (int) blockEntity.getBlockPos().asLong() + i); + poseStack.popPose(); + } + + private void setupFloatingRenderer(CraftingTableAnimationController animationController, float partialTick, PoseStack poseStack, ItemStack itemStack, int index) { + // -0.0125 to 0.0125 + float shift = (float) Math.abs(((animationController.ticks + partialTick) * 50.0 + (index * 1000L)) % 5000L - 2500L) / 200000.0F; + BakedModel model = this.itemRenderer.getModel(itemStack, null, null, 0); + boolean blockItem = model.isGui3d(); + poseStack.translate(0.5, shift, 0.5); + poseStack.mulPose(Axis.YP.rotationDegrees(Mth.lerp(partialTick, animationController.currentAngle, animationController.nextAngle))); + poseStack.translate((double) (index % 3) * 3.0 / 16.0 + 0.3125 - 0.5, 1.09375, (double) (index / 3) * 3.0 / 16.0 + 0.3125 - 0.5); + float scale = blockItem ? 0.24F : 0.18F; + poseStack.scale(scale, scale, scale); + } + + private void setupFlatRenderer(CraftingTableAnimationController animationController, float partialTick, PoseStack poseStack, ItemStack itemStack, int index) { + BakedModel bakedModel = this.itemRenderer.getModel(itemStack, null, null, 0); + boolean gui3d = bakedModel.isGui3d(); + poseStack.translate(0.5, 0.0, 0.5); + poseStack.mulPose(Axis.YP.rotationDegrees(Mth.lerp(partialTick, animationController.currentAngle, animationController.nextAngle))); + poseStack.translate((double) (index % 3) * 3.0 / 16.0 + 0.3125 - 0.5, gui3d ? 1.0625 : 1.005, (double) (index / 3) * 3.0 / 16.0 + 0.3125 - 0.5); + poseStack.mulPose(Axis.XP.rotationDegrees(90.0F)); + poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F)); + float scale = gui3d ? 0.25F : 0.175F; + poseStack.scale(scale, scale, scale); + } + + private void renderResultItem(ItemStack itemStack, @Nullable Level level, float time, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight) { + if (!VisualWorkbench.CONFIG.get(ClientConfig.class).renderResult) return; + poseStack.pushPose(); + poseStack.translate(0.5F, 1.15F, 0.5F); + BakedModel model = this.itemRenderer.getModel(itemStack, level, null, 0); + float hoverOffset = Mth.sin(time / 10.0F) * 0.04F + 0.1F; + float modelYScale = model.getTransforms().getTransform(ItemDisplayContext.GROUND).scale.y(); + poseStack.translate(0.0, hoverOffset + 0.25F * modelYScale, 0.0); + poseStack.mulPose(Axis.YP.rotation(time / 20.0F)); + if (!model.isGui3d()) poseStack.scale(0.75F, 0.75F, 0.75F); + this.itemRenderer.render(itemStack, ItemDisplayContext.GROUND, false, poseStack, multiBufferSource, packedLight, OverlayTexture.NO_OVERLAY, model); + poseStack.popPose(); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java new file mode 100644 index 0000000..6a3b315 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java @@ -0,0 +1,17 @@ +package fuzs.visualworkbench.config; + +import fuzs.puzzleslib.api.config.v3.Config; +import fuzs.puzzleslib.api.config.v3.ConfigCore; + +public class ClientConfig implements ConfigCore { + @Config(description = "Makes crafting table contents lay flat on the table instead of floating above.") + public boolean flatRendering = false; + @Config(description = "Render the result of the crafting operation in addition to crafting table contents.") + public boolean renderResult = true; + @Config(description = "Rotate crafting table contents so they always face the closest player.") + public RotateIngredients rotateIngredients = RotateIngredients.CLOSEST_PLAYER; + + public enum RotateIngredients { + CLOSEST_PLAYER, CRAFTING_PLAYER, NEVER + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/config/ServerConfig.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/config/ServerConfig.java new file mode 100644 index 0000000..f9f8358 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/config/ServerConfig.java @@ -0,0 +1,9 @@ +package fuzs.visualworkbench.config; + +import fuzs.puzzleslib.api.config.v3.Config; +import fuzs.puzzleslib.api.config.v3.ConfigCore; + +public class ServerConfig implements ConfigCore { + @Config(description = "Leftover vanilla crafting tables in a world become unusable until they are broken and replaced.") + public boolean disableVanillaWorkbench = true; +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/ModBlockTagsProvider.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/ModBlockTagsProvider.java new file mode 100644 index 0000000..6453f43 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/ModBlockTagsProvider.java @@ -0,0 +1,19 @@ +package fuzs.visualworkbench.data; + +import fuzs.puzzleslib.api.data.v2.AbstractTagProvider; +import fuzs.puzzleslib.api.data.v2.core.DataProviderContext; +import fuzs.visualworkbench.init.ModRegistry; +import net.minecraft.core.HolderLookup; +import net.minecraft.world.level.block.Blocks; + +public class ModBlockTagsProvider extends AbstractTagProvider.Blocks { + + public ModBlockTagsProvider(DataProviderContext context) { + super(context); + } + + @Override + public void addTags(HolderLookup.Provider provider) { + this.tag(ModRegistry.UNALTERED_WORKBENCHES_BLOCK_TAG).add(Blocks.SMITHING_TABLE, Blocks.FLETCHING_TABLE); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/client/DynamicModelProvider.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/client/DynamicModelProvider.java new file mode 100644 index 0000000..57aaff6 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/client/DynamicModelProvider.java @@ -0,0 +1,31 @@ +package fuzs.visualworkbench.data.client; + +import fuzs.puzzleslib.api.client.data.v2.AbstractModelProvider; +import fuzs.puzzleslib.api.data.v2.core.DataProviderContext; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import net.minecraft.data.models.BlockModelGenerators; +import net.minecraft.data.models.blockstates.MultiVariantGenerator; +import net.minecraft.data.models.blockstates.Variant; +import net.minecraft.data.models.blockstates.VariantProperties; +import net.minecraft.data.models.model.ModelLocationUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; + +public class DynamicModelProvider extends AbstractModelProvider { + + public DynamicModelProvider(DataProviderContext context) { + super(context); + } + + @Override + public void addBlockModels(BlockModelGenerators builder) { + // dynamically generate a basic stone block model for every diagonal block so the model bakery logs no missing model + // don't use an air model so the blocks remain visible + ResourceLocation resourceLocation = ModelLocationUtils.getModelLocation(Blocks.STONE); + BlockConversionHandler.BLOCK_CONVERSIONS.values().forEach((Block block) -> { + builder.blockStateOutput.accept(MultiVariantGenerator.multiVariant(block, Variant.variant().with(VariantProperties.MODEL, resourceLocation))); + builder.skipAutoItemBlock(block); + }); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/client/ModLanguageProvider.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/client/ModLanguageProvider.java new file mode 100644 index 0000000..07595b1 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/data/client/ModLanguageProvider.java @@ -0,0 +1,17 @@ +package fuzs.visualworkbench.data.client; + +import fuzs.puzzleslib.api.client.data.v2.AbstractLanguageProvider; +import fuzs.puzzleslib.api.data.v2.core.DataProviderContext; +import fuzs.visualworkbench.handler.BlockConversionHandler; + +public class ModLanguageProvider extends AbstractLanguageProvider { + + public ModLanguageProvider(DataProviderContext context) { + super(context); + } + + @Override + public void addTranslations(TranslationBuilder builder) { + builder.add(BlockConversionHandler.INVALID_BLOCK_COMPONENT, "Unable to open. Break and replace to use."); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/handler/BlockConversionHandler.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/handler/BlockConversionHandler.java new file mode 100644 index 0000000..bf52e91 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/handler/BlockConversionHandler.java @@ -0,0 +1,100 @@ +package fuzs.visualworkbench.handler; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import fuzs.puzzleslib.api.block.v1.BlockConversionHelper; +import fuzs.puzzleslib.api.event.v1.core.EventResultHolder; +import fuzs.puzzleslib.api.init.v3.registry.RegistryHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.config.ServerConfig; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.level.block.CraftingTableWithInventoryBlock; +import net.minecraft.ChatFormatting; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.CraftingTableBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +public class BlockConversionHandler { + public static final Component INVALID_BLOCK_COMPONENT = Component.translatable("container.invalidBlock"); + public static final BiMap BLOCK_CONVERSIONS = HashBiMap.create(); + + public static void onRegistryEntryAdded(Registry registry, ResourceLocation id, Block block, BiConsumer> registrar) { + if (block instanceof CraftingTableBlock) { + ResourceLocation resourceLocation = VisualWorkbench.id(id.getNamespace() + "/" + id.getPath()); + registrar.accept(resourceLocation, () -> { + Block newBlock = new CraftingTableWithInventoryBlock(block); + BLOCK_CONVERSIONS.put(block, newBlock); + return newBlock; + }); + } + } + + public static EventResultHolder onUseBlock(Player player, Level level, InteractionHand interactionHand, BlockHitResult hitResult) { + if (!VisualWorkbench.CONFIG.get(ServerConfig.class).disableVanillaWorkbench) return EventResultHolder.pass(); + BlockState blockState = level.getBlockState(hitResult.getBlockPos()); + if (BLOCK_CONVERSIONS.containsKey(blockState.getBlock()) && !blockState.is(ModRegistry.UNALTERED_WORKBENCHES_BLOCK_TAG)) { + player.displayClientMessage(Component.empty().append(INVALID_BLOCK_COMPONENT).withStyle(ChatFormatting.RED), true); + return EventResultHolder.interrupt(InteractionResult.sidedSuccess(level.isClientSide)); + } else { + return EventResultHolder.pass(); + } + } + + public static void onTagsUpdated(RegistryAccess registryAccess, boolean client) { + for (Map.Entry, Item> entry : BuiltInRegistries.ITEM.entrySet()) { + if (entry.getValue() instanceof BlockItem blockItem) { + Block block = blockItem.getBlock(); + setItemForBlock(entry.getKey().location(), blockItem, block); + setBlockForItem(blockItem, block); + } + } + copyBoundTags(); + } + + private static void setItemForBlock(ResourceLocation resourceLocation, BlockItem blockItem, Block block) { + if (block instanceof CraftingTableBlock) { + BlockConversionHelper.setItemForBlock(BLOCK_CONVERSIONS.get(block), blockItem); + } + } + + private static void setBlockForItem(BlockItem blockItem, Block block) { + Block baseBlock; + Block diagonalBlock = BLOCK_CONVERSIONS.get(block); + if (diagonalBlock != null) { + baseBlock = block; + } else { + baseBlock = BLOCK_CONVERSIONS.inverse().get(block); + if (baseBlock != null) { + diagonalBlock = block; + } else { + return; + } + } + if (RegistryHelper.is(ModRegistry.UNALTERED_WORKBENCHES_BLOCK_TAG, baseBlock)) { + BlockConversionHelper.setBlockForItem(blockItem, baseBlock); + } else { + BlockConversionHelper.setBlockForItem(blockItem, diagonalBlock); + } + } + + private static void copyBoundTags() { + BLOCK_CONVERSIONS.forEach(BlockConversionHelper::copyBoundTags); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java new file mode 100644 index 0000000..fa484be --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java @@ -0,0 +1,30 @@ +package fuzs.visualworkbench.init; + +import fuzs.puzzleslib.api.init.v3.registry.RegistryManager; +import fuzs.puzzleslib.api.init.v3.tags.BoundTagFactory; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import fuzs.visualworkbench.world.inventory.VisualCraftingMenu; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableBlockEntity; +import net.minecraft.core.Holder; +import net.minecraft.tags.TagKey; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; + +public class ModRegistry { + static final RegistryManager REGISTRY = RegistryManager.from(VisualWorkbench.MOD_ID); + public static final Holder.Reference> CRAFTING_TABLE_BLOCK_ENTITY = REGISTRY.registerBlockEntityType("crafting_table", () -> { + BlockEntityType.Builder builder = BlockEntityType.Builder.of(CraftingTableBlockEntity::new); + builder.validBlocks = BlockConversionHandler.BLOCK_CONVERSIONS.values(); + return builder; + }); + public static final Holder.Reference> CRAFTING_MENU_TYPE = REGISTRY.registerMenuType("crafting", () -> VisualCraftingMenu::new); + + static final BoundTagFactory TAGS = BoundTagFactory.make(VisualWorkbench.MOD_ID); + public static final TagKey UNALTERED_WORKBENCHES_BLOCK_TAG = TAGS.registerBlockTag("unaltered_workbenches"); + + public static void touch() { + + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java new file mode 100644 index 0000000..e104dde --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java @@ -0,0 +1,24 @@ +package fuzs.visualworkbench.integration.jei; + +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.inventory.VisualCraftingMenu; +import mezz.jei.api.IModPlugin; +import mezz.jei.api.JeiPlugin; +import mezz.jei.api.constants.RecipeTypes; +import mezz.jei.api.registration.IRecipeTransferRegistration; +import net.minecraft.resources.ResourceLocation; + +@JeiPlugin +public class VisualWorkbenchJEIPlugin implements IModPlugin { + + @Override + public ResourceLocation getPluginUid() { + return new ResourceLocation(VisualWorkbench.MOD_ID, "crafting"); + } + + @Override + public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { + registration.addRecipeTransferHandler(VisualCraftingMenu.class, ModRegistry.CRAFTING_MENU_TYPE.value(), RecipeTypes.CRAFTING, 1, 9, 10, 36); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualCraftingMenu.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualCraftingMenu.java new file mode 100644 index 0000000..b8e23d7 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualCraftingMenu.java @@ -0,0 +1,59 @@ +package fuzs.visualworkbench.world.inventory; + +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableBlockEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.*; + +public class VisualCraftingMenu extends CraftingMenu { + + public VisualCraftingMenu(int id, Inventory inventory) { + super(id, inventory); + } + + public VisualCraftingMenu(int id, Inventory inventory, CraftingTableBlockEntity blockEntity, ContainerLevelAccess access) { + super(id, inventory, access); + this.craftSlots = new VisualTransientCraftingContainer(this, 3, 3, blockEntity.getItems(), blockEntity); + this.resultSlots = new VisualResultContainer(blockEntity.getResultItems(), blockEntity); + this.setCraftingSlotsContainer(); + // always update recipe output when opening menu, otherwise could be missing or outdated if the block entity didn't save it correctly + this.refreshRecipeResult(); + } + + private void setCraftingSlotsContainer() { + for (int i = 0; i < 10; i++) { + Slot slot = this.getSlot(i); + if (slot instanceof ResultSlot resultSlot) { + resultSlot.craftSlots = this.craftSlots; + slot.container = this.resultSlots; + } else if (slot.container instanceof TransientCraftingContainer) { + slot.container = this.craftSlots; + } + } + } + + private void refreshRecipeResult() { + this.slotsChanged(this.craftSlots); + } + + @Override + public MenuType getType() { + return ModRegistry.CRAFTING_MENU_TYPE.value(); + } + + @Override + public void removed(Player player) { + // prevent items from being cleared out of the container + ContainerLevelAccess containerLevelAccess = this.access; + this.access = ContainerLevelAccess.NULL; + super.removed(player); + this.access = containerLevelAccess; + } + + @Override + public boolean stillValid(Player player) { + // craft slots are extended to forward this to the block entity, normally in vanilla this would always return true + return this.craftSlots.stillValid(player); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualResultContainer.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualResultContainer.java new file mode 100644 index 0000000..06c03ca --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualResultContainer.java @@ -0,0 +1,40 @@ +package fuzs.visualworkbench.world.inventory; + +import net.minecraft.core.NonNullList; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ResultContainer; +import net.minecraft.world.item.ItemStack; + +public class VisualResultContainer extends ResultContainer { + private final Container container; + + public VisualResultContainer(NonNullList items, Container container) { + this.container = container; + this.itemStacks = items; + } + + @Override + public ItemStack removeItem(int slot, int amount) { + ItemStack result = super.removeItem(slot, amount); + if (!result.isEmpty()) this.setChanged(); + return result; + } + + @Override + public void setItem(int slot, ItemStack stack) { + super.setItem(slot, stack); + this.setChanged(); + } + + @Override + public void setChanged() { + super.setChanged(); + this.container.setChanged(); + } + + @Override + public boolean stillValid(Player player) { + return this.container.stillValid(player); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualTransientCraftingContainer.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualTransientCraftingContainer.java new file mode 100644 index 0000000..9f24398 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualTransientCraftingContainer.java @@ -0,0 +1,41 @@ +package fuzs.visualworkbench.world.inventory; + +import net.minecraft.core.NonNullList; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.TransientCraftingContainer; +import net.minecraft.world.item.ItemStack; + +public class VisualTransientCraftingContainer extends TransientCraftingContainer { + private final Container container; + + public VisualTransientCraftingContainer(AbstractContainerMenu menu, int width, int height, NonNullList items, Container container) { + super(menu, width, height, items); + this.container = container; + } + + @Override + public ItemStack removeItem(int slot, int amount) { + ItemStack itemStack = super.removeItem(slot, amount); + if (!itemStack.isEmpty()) this.setChanged(); + return itemStack; + } + + @Override + public void setItem(int slot, ItemStack stack) { + super.setItem(slot, stack); + this.setChanged(); + } + + @Override + public void setChanged() { + super.setChanged(); + this.container.setChanged(); + } + + @Override + public boolean stillValid(Player player) { + return this.container.stillValid(player); + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/CraftingTableWithInventoryBlock.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/CraftingTableWithInventoryBlock.java new file mode 100644 index 0000000..6fbd582 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/CraftingTableWithInventoryBlock.java @@ -0,0 +1,90 @@ +package fuzs.visualworkbench.world.level.block; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import fuzs.puzzleslib.api.block.v1.entity.TickingEntityBlock; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.stats.Stats; +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.Level; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BlockTypes; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +import java.util.function.Predicate; + +public class CraftingTableWithInventoryBlock extends BaseEntityBlock implements TickingEntityBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( + instance -> instance.group(BlockTypes.CODEC.fieldOf("block").forGetter(block -> block.block)).apply(instance, CraftingTableWithInventoryBlock::new) + ); + + private final Block block; + + public CraftingTableWithInventoryBlock(Block block) { + super(BlockBehaviour.Properties.ofFullCopy(block).dropsLike(block)); + this.block = block; + } + + @Override + public String getDescriptionId() { + return this.block.getDescriptionId(); + } + + @Override + protected MapCodec codec() { + return CODEC; + } + + @Override + public RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Override + public BlockEntityType getBlockEntityType() { + return ModRegistry.CRAFTING_TABLE_BLOCK_ENTITY.value(); + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else if (level.getBlockEntity(pos) instanceof CraftingTableBlockEntity blockEntity) { + player.openMenu(blockEntity); + player.awardStat(Stats.INTERACT_WITH_CRAFTING_TABLE); + } + return InteractionResult.CONSUME; + } + + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { + Containers.dropContentsOnDestroy(state, newState, level, pos); + super.onRemove(state, level, pos, newState, movedByPiston); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState blockState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos blockPos) { + // similar to Crafter + if (level.getBlockEntity(blockPos) instanceof CraftingTableBlockEntity blockEntity) { + return (int) blockEntity.getItems().stream().filter(Predicate.not(ItemStack::isEmpty)).count(); + } else { + return 0; + } + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableAnimationController.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableAnimationController.java new file mode 100644 index 0000000..2091af1 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableAnimationController.java @@ -0,0 +1,116 @@ +package fuzs.visualworkbench.world.level.block.entity; + +import fuzs.puzzleslib.api.core.v1.Proxy; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.config.ClientConfig; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.CraftingScreen; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +/** + * A client-side provider for ticking and storing crafting table item animations on a block entity. + *

Initialize an instance in your block entity constructor, then implement a call for {@link CraftingTableAnimationController#tick(Level)} on the client. + *

Make sure the code is never accidentally called on the server as it accesses client-only classes. + *

All animation code in this class is taken from the old RealBench mod. + */ +public class CraftingTableAnimationController { + private final Vec3 position; + public int ticks; + public float currentAngle; + public float nextAngle; + public int sector; + public boolean animating; + public float animationAngleStart; + public float animationAngleEnd; + public double startTicks; + public double playerAngle; + + public CraftingTableAnimationController(BlockPos blockPos) { + this.position = blockPos.getCenter(); + } + + public void tick(Level level) { + ++this.ticks; + this.setPlayerAngle(level); + this.setCurrentSector(); + this.tryAnimate(); + } + + private void setPlayerAngle(Level level) { + Player player; + if (VisualWorkbench.CONFIG.get(ClientConfig.class).rotateIngredients != ClientConfig.RotateIngredients.NEVER) { + player = level.getNearestPlayer(this.position.x(), this.position.y(), this.position.z(), 3.0, (Entity entity) -> { + if (entity.isSpectator()) { + return false; + } else if (VisualWorkbench.CONFIG.get(ClientConfig.class).rotateIngredients == ClientConfig.RotateIngredients.CLOSEST_PLAYER) { + return true; + } else { + if (entity == Proxy.INSTANCE.getClientPlayer()) { + return Minecraft.getInstance().screen instanceof CraftingScreen; + } else { + return false; + } + } + }); + } else { + player = null; + } + if (player != null) { + double d0 = player.getX() - this.position.x(); + double d1 = player.getZ() - this.position.z(); + this.playerAngle = (Math.atan2(-d0, -d1) + 3.9269908169872414D) % 6.283185307179586D; + } + } + + private void setCurrentSector() { + int sector = (int) (this.playerAngle * 2.0 / Math.PI); + if (this.sector != sector) { + this.animating = true; + this.animationAngleStart = this.currentAngle; + float delta1 = sector * 90.0F - this.currentAngle; + float abs1 = Math.abs(delta1); + float delta2 = delta1 + 360.0F; + float shift = Math.abs(delta2); + float delta3 = delta1 - 360.0F; + float abs3 = Math.abs(delta3); + if (abs3 < abs1 && abs3 < shift) { + this.animationAngleEnd = delta3 + this.currentAngle; + } else if (shift < abs1 && shift < abs3) { + this.animationAngleEnd = delta2 + this.currentAngle; + } else { + this.animationAngleEnd = delta1 + this.currentAngle; + } + this.startTicks = this.ticks; + this.sector = sector; + } + } + + private void tryAnimate() { + if (this.animating) { + if (this.ticks >= this.startTicks + 20) { + this.animating = false; + this.currentAngle = this.nextAngle = (this.animationAngleEnd + 360.0F) % 360.0F; + } else { + this.currentAngle = (calcEaseOutQuad(this.ticks - this.startTicks, this.animationAngleStart, this.animationAngleEnd - this.animationAngleStart, 20.0) + 360.0F) % 360.0F; + this.nextAngle = (calcEaseOutQuad(Math.min(this.ticks + 1 - this.startTicks, 20), this.animationAngleStart, this.animationAngleEnd - this.animationAngleStart, 20.0) + 360.0F) % 360.0F; + if (this.currentAngle != 0.0F || this.nextAngle != 0.0F) { + if (this.currentAngle == 0.0F && this.nextAngle >= 180.0F) { + this.currentAngle = 360.0F; + } + if (this.nextAngle == 0.0F && this.currentAngle >= 180.0F) { + this.nextAngle = 360.0F; + } + } + } + } + } + + private static float calcEaseOutQuad(double t, float b, float c, double d) { + float z = (float) t / (float) d; + return -c * z * (z - 2.0F) + b; + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java new file mode 100644 index 0000000..db19dba --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java @@ -0,0 +1,126 @@ +package fuzs.visualworkbench.world.level.block.entity; + +import fuzs.puzzleslib.api.block.v1.entity.TickingBlockEntity; +import fuzs.puzzleslib.api.container.v1.ContainerSerializationHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.inventory.VisualCraftingMenu; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +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.ContainerLevelAccess; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +public class CraftingTableBlockEntity extends RandomizableContainerBlockEntity implements TickingBlockEntity, WorkbenchVisualsProvider { + public static final MutableComponent COMPONENT_CRAFTING = Component.translatable("container.crafting"); + public static final String TAG_RESULT = VisualWorkbench.id("result").toString(); + + private final CraftingTableAnimationController animationController; + private final NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY); + private final NonNullList resultItems = NonNullList.withSize(1, ItemStack.EMPTY); + + public CraftingTableBlockEntity(BlockPos pos, BlockState blockState) { + super(ModRegistry.CRAFTING_TABLE_BLOCK_ENTITY.value(), pos, blockState); + this.animationController = new CraftingTableAnimationController(pos); + } + + @Override + public void load(CompoundTag tag) { + super.load(tag); + this.items.clear(); + this.resultItems.clear(); + if (!this.tryLoadLootTable(tag)) { + ContainerHelper.loadAllItems(tag, this.items); + ContainerSerializationHelper.loadAllItems(TAG_RESULT, tag, this.resultItems); + } + } + + @Override + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); + if (!this.trySaveLootTable(tag)) { + ContainerHelper.saveAllItems(tag, this.items); + ContainerSerializationHelper.saveAllItems(TAG_RESULT, tag, this.resultItems); + } + } + + @Override + @Nullable + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + + @Override + public void setChanged() { + super.setChanged(); + if (this.level != null) { + this.level.sendBlockUpdated(this.worldPosition, this.getBlockState(), this.getBlockState(), 3); + } + } + + @Override + public NonNullList getItems() { + return this.items; + } + + @Override + protected void setItems(NonNullList itemStacks) { + // why does this event exist... + throw new UnsupportedOperationException(); + } + + @Override + protected Component getDefaultName() { + return COMPONENT_CRAFTING; + } + + @Override + protected AbstractContainerMenu createMenu(int containerId, Inventory inventory) { + return new VisualCraftingMenu(containerId, inventory, this, ContainerLevelAccess.create(this.getLevel(), this.getBlockPos())); + } + + @Override + public int getContainerSize() { + return this.items.size(); + } + + @Override + public boolean stillValid(Player player) { + return Container.stillValidBlockEntity(this, player); + } + + @Override + public void clientTick() { + this.animationController.tick(this.getLevel()); + } + + public NonNullList getResultItems() { + return this.resultItems; + } + + @Override + public ItemStack getCraftingResult() { + return this.resultItems.get(0); + } + + @Override + public CraftingTableAnimationController getAnimationController() { + return this.animationController; + } +} diff --git a/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/WorkbenchVisualsProvider.java b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/WorkbenchVisualsProvider.java new file mode 100644 index 0000000..3962ba5 --- /dev/null +++ b/1.20.4/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/WorkbenchVisualsProvider.java @@ -0,0 +1,22 @@ +package fuzs.visualworkbench.world.level.block.entity; + +import net.minecraft.world.item.ItemStack; + +/** + * An extension for a {@link net.minecraft.world.level.block.entity.BlockEntity} providing access to data required for rendering. + */ +public interface WorkbenchVisualsProvider { + + /** + * Get the crafting result for the currently stored ingredients. + *

Can return {@link ItemStack#EMPTY} to not render anything. + * + * @return the crafting result + */ + ItemStack getCraftingResult(); + + /** + * @return storage for animation data + */ + CraftingTableAnimationController getAnimationController(); +} diff --git a/1.20.4/Common/src/main/resources/architectury.common.json b/1.20.4/Common/src/main/resources/architectury.common.json new file mode 100644 index 0000000..822cfd0 --- /dev/null +++ b/1.20.4/Common/src/main/resources/architectury.common.json @@ -0,0 +1,3 @@ +{ + "accessWidener": "visualworkbench.accesswidener" +} \ No newline at end of file diff --git a/1.20.4/Common/src/main/resources/common.mixins.json b/1.20.4/Common/src/main/resources/common.mixins.json new file mode 100644 index 0000000..77fc8f4 --- /dev/null +++ b/1.20.4/Common/src/main/resources/common.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "minVersion": "0.8", + "compatibilityLevel": "JAVA_17", + "package": "${modGroup}.mixin", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/1.20.4/Common/src/main/resources/mod_banner.png b/1.20.4/Common/src/main/resources/mod_banner.png new file mode 100644 index 0000000..7b83155 Binary files /dev/null and b/1.20.4/Common/src/main/resources/mod_banner.png differ diff --git a/1.20.4/Common/src/main/resources/mod_logo.png b/1.20.4/Common/src/main/resources/mod_logo.png new file mode 100644 index 0000000..6715625 Binary files /dev/null and b/1.20.4/Common/src/main/resources/mod_logo.png differ diff --git a/1.20.4/Common/src/main/resources/pack.mcmeta b/1.20.4/Common/src/main/resources/pack.mcmeta new file mode 100755 index 0000000..546f4f1 --- /dev/null +++ b/1.20.4/Common/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "${modDescription}", + "pack_format": ${resourcePackFormat} + } +} diff --git a/1.20.4/Common/src/main/resources/visualworkbench.accesswidener b/1.20.4/Common/src/main/resources/visualworkbench.accesswidener new file mode 100644 index 0000000..f6b21e6 --- /dev/null +++ b/1.20.4/Common/src/main/resources/visualworkbench.accesswidener @@ -0,0 +1,14 @@ +accessWidener v2 named +accessible field net/minecraft/world/level/block/entity/BlockEntityType$Builder validBlocks Ljava/util/Set; +mutable field net/minecraft/world/level/block/entity/BlockEntityType$Builder validBlocks Ljava/util/Set; +accessible field net/minecraft/world/inventory/CraftingMenu craftSlots Lnet/minecraft/world/inventory/CraftingContainer; +mutable field net/minecraft/world/inventory/CraftingMenu craftSlots Lnet/minecraft/world/inventory/CraftingContainer; +accessible field net/minecraft/world/inventory/CraftingMenu resultSlots Lnet/minecraft/world/inventory/ResultContainer; +mutable field net/minecraft/world/inventory/CraftingMenu resultSlots Lnet/minecraft/world/inventory/ResultContainer; +accessible field net/minecraft/world/inventory/CraftingMenu access Lnet/minecraft/world/inventory/ContainerLevelAccess; +mutable field net/minecraft/world/inventory/CraftingMenu access Lnet/minecraft/world/inventory/ContainerLevelAccess; +accessible field net/minecraft/world/inventory/ResultContainer itemStacks Lnet/minecraft/core/NonNullList; +mutable field net/minecraft/world/inventory/ResultContainer itemStacks Lnet/minecraft/core/NonNullList; +accessible field net/minecraft/world/inventory/ResultSlot craftSlots Lnet/minecraft/world/inventory/CraftingContainer; +mutable field net/minecraft/world/inventory/ResultSlot craftSlots Lnet/minecraft/world/inventory/CraftingContainer; +mutable field net/minecraft/world/inventory/Slot container Lnet/minecraft/world/Container; diff --git a/1.20.4/Fabric/build.gradle b/1.20.4/Fabric/build.gradle new file mode 100644 index 0000000..1123f46 --- /dev/null +++ b/1.20.4/Fabric/build.gradle @@ -0,0 +1,16 @@ +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/v2/fabric.gradle" + +dependencies { + // Fabric Api + modApi libs.fabricapi.fabric + + // Puzzles Lib + modApi libs.puzzleslib.fabric + + // Extensible Enums +// modApi(include(libs.extensibleenums.fabric.get())) + + // Just Enough Items + compileOnly libs.jeiapi.common + modLocalRuntime libs.jei.fabric +} diff --git a/1.20.4/Fabric/src/main/java/fuzs/visualworkbench/fabric/VisualWorkbenchFabric.java b/1.20.4/Fabric/src/main/java/fuzs/visualworkbench/fabric/VisualWorkbenchFabric.java new file mode 100644 index 0000000..3d458b9 --- /dev/null +++ b/1.20.4/Fabric/src/main/java/fuzs/visualworkbench/fabric/VisualWorkbenchFabric.java @@ -0,0 +1,13 @@ +package fuzs.visualworkbench.fabric; + +import fuzs.puzzleslib.api.core.v1.ModConstructor; +import fuzs.visualworkbench.VisualWorkbench; +import net.fabricmc.api.ModInitializer; + +public class VisualWorkbenchFabric implements ModInitializer { + + @Override + public void onInitialize() { + ModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbench::new); + } +} diff --git a/1.20.4/Fabric/src/main/java/fuzs/visualworkbench/fabric/client/VisualWorkbenchFabricClient.java b/1.20.4/Fabric/src/main/java/fuzs/visualworkbench/fabric/client/VisualWorkbenchFabricClient.java new file mode 100644 index 0000000..11075e8 --- /dev/null +++ b/1.20.4/Fabric/src/main/java/fuzs/visualworkbench/fabric/client/VisualWorkbenchFabricClient.java @@ -0,0 +1,14 @@ +package fuzs.visualworkbench.fabric.client; + +import fuzs.puzzleslib.api.client.core.v1.ClientModConstructor; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.client.VisualWorkbenchClient; +import net.fabricmc.api.ClientModInitializer; + +public class VisualWorkbenchFabricClient implements ClientModInitializer { + + @Override + public void onInitializeClient() { + ClientModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbenchClient::new); + } +} diff --git a/1.20.4/Fabric/src/main/resources/fabric.mixins.json b/1.20.4/Fabric/src/main/resources/fabric.mixins.json new file mode 100644 index 0000000..6bf7940 --- /dev/null +++ b/1.20.4/Fabric/src/main/resources/fabric.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "compatibilityLevel": "JAVA_17", + "package": "${modGroup}.fabric.mixin", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "${modId}.fabric.refmap.json" +} diff --git a/1.20.4/Fabric/src/main/resources/fabric.mod.json b/1.20.4/Fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..243503b --- /dev/null +++ b/1.20.4/Fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,48 @@ +{ + "schemaVersion": 1, + "id": "${modId}", + "version": "${modVersion}", + + "name": "${modName}", + "description": "${modDescription}", + + "authors": [ + "${modAuthor}" + ], + + "contact": { + "homepage": "${modPageUrl}", + "issues": "${modIssueUrl}", + "sources": "${modPageUrl}" + }, + + "license": "${modLicense}", + "icon": "mod_logo.png", + + "environment": "${modFabricEnvironment}", + + "entrypoints": { + "main": [ + "${mainEntryPoint}" + ], + "client": [ + "${clientEntryPoint}" + ], + "jei_mod_plugin": [ + "${modGroup}.integration.jei.VisualWorkbenchJEIPlugin" + ] + }, + + "mixins": [ + "${modId}.common.mixins.json", + "${modId}.fabric.mixins.json" + ], + + "depends": { + "fabricloader": ">=${minFabricVersion}", + "fabric-api": ">=${minFabricApiVersion}", + "puzzleslib": ">=${minPuzzlesVersion}", + "minecraft": "${minecraftVersion}", + "java": ">=17" + } +} diff --git a/1.20.4/Forge/build.gradle b/1.20.4/Forge/build.gradle new file mode 100644 index 0000000..de59471 --- /dev/null +++ b/1.20.4/Forge/build.gradle @@ -0,0 +1,10 @@ +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/v2/forge.gradle" + +dependencies { + // Puzzles Lib + modApi libs.puzzleslib.forge + + // Just Enough Items + compileOnly libs.jeiapi.common + modLocalRuntime libs.jei.forge +} diff --git a/1.20.4/Forge/gradle.properties b/1.20.4/Forge/gradle.properties new file mode 100644 index 0000000..32f842a --- /dev/null +++ b/1.20.4/Forge/gradle.properties @@ -0,0 +1 @@ +loom.platform=forge \ No newline at end of file diff --git a/1.20.4/Forge/src/main/java/fuzs/visualworkbench/forge/VisualWorkbenchForge.java b/1.20.4/Forge/src/main/java/fuzs/visualworkbench/forge/VisualWorkbenchForge.java new file mode 100644 index 0000000..ed04091 --- /dev/null +++ b/1.20.4/Forge/src/main/java/fuzs/visualworkbench/forge/VisualWorkbenchForge.java @@ -0,0 +1,17 @@ +package fuzs.visualworkbench.forge; + +import fuzs.puzzleslib.api.core.v1.ModConstructor; +import fuzs.visualworkbench.VisualWorkbench; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLConstructModEvent; + +@Mod(VisualWorkbench.MOD_ID) +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class VisualWorkbenchForge { + + @SubscribeEvent + public static void onConstructMod(final FMLConstructModEvent evt) { + ModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbench::new); + } +} diff --git a/1.20.4/Forge/src/main/java/fuzs/visualworkbench/forge/client/VisualWorkbenchForgeClient.java b/1.20.4/Forge/src/main/java/fuzs/visualworkbench/forge/client/VisualWorkbenchForgeClient.java new file mode 100644 index 0000000..79b7760 --- /dev/null +++ b/1.20.4/Forge/src/main/java/fuzs/visualworkbench/forge/client/VisualWorkbenchForgeClient.java @@ -0,0 +1,18 @@ +package fuzs.visualworkbench.forge.client; + +import fuzs.puzzleslib.api.client.core.v1.ClientModConstructor; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.client.VisualWorkbenchClient; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLConstructModEvent; + +@Mod.EventBusSubscriber(modid = VisualWorkbench.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class VisualWorkbenchForgeClient { + + @SubscribeEvent + public static void onConstructMod(final FMLConstructModEvent evt) { + ClientModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbenchClient::new); + } +} diff --git a/1.20.4/Forge/src/main/resources/META-INF/mods.toml b/1.20.4/Forge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..6c2e585 --- /dev/null +++ b/1.20.4/Forge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,51 @@ +modLoader = "javafml" +loaderVersion = "*" +license = "${modLicense}" +issueTrackerURL = "${modIssueUrl}" + +[[mods]] +modId = "${modId}" +displayName = "${modName}" +description = "${modDescription}" +version = "${modVersion}" +authors = "${modAuthor}" +logoFile = "mod_banner.png" +logoBlur = false +displayURL = "${modPageUrl}" +updateJSONURL = "${modUpdateUrl}" +displayTest = "${modForgeDisplayTest}" + +[[dependencies.${ modId }]] +modId = "forge" +mandatory = true +type = "required" +versionRange = "[${minForgeVersion},)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${ modId }]] +modId = "minecraft" +mandatory = true +type = "required" +versionRange = "[${minecraftVersion}]" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${ modId }]] +modId = "forgeconfigapiport" +mandatory = true +type = "required" +versionRange = "*" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${ modId }]] +modId = "puzzleslib" +mandatory = true +type = "required" +versionRange = "[${minPuzzlesVersion},)" +ordering = "NONE" +side = "BOTH" + +[modproperties.${ modId }] +catalogueImageIcon = "mod_logo.png" diff --git a/1.20.4/Forge/src/main/resources/forge.mixins.json b/1.20.4/Forge/src/main/resources/forge.mixins.json new file mode 100644 index 0000000..f2b4276 --- /dev/null +++ b/1.20.4/Forge/src/main/resources/forge.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "compatibilityLevel": "JAVA_17", + "package": "${modGroup}.forge.mixin", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "${modId}.forge.refmap.json" +} diff --git a/1.20.4/NeoForge/build.gradle b/1.20.4/NeoForge/build.gradle new file mode 100644 index 0000000..15447df --- /dev/null +++ b/1.20.4/NeoForge/build.gradle @@ -0,0 +1,10 @@ +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/v2/neoforge.gradle" + +dependencies { + // Puzzles Lib + modApi libs.puzzleslib.neoforge + + // Just Enough Items + compileOnly libs.jeiapi.common + modLocalRuntime libs.jei.neoforge +} diff --git a/1.20.4/NeoForge/gradle.properties b/1.20.4/NeoForge/gradle.properties new file mode 100644 index 0000000..2914393 --- /dev/null +++ b/1.20.4/NeoForge/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge \ No newline at end of file diff --git a/1.20.4/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/VisualWorkbenchNeoForge.java b/1.20.4/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/VisualWorkbenchNeoForge.java new file mode 100644 index 0000000..4266164 --- /dev/null +++ b/1.20.4/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/VisualWorkbenchNeoForge.java @@ -0,0 +1,21 @@ +package fuzs.visualworkbench.neoforge; + +import fuzs.puzzleslib.api.core.v1.ModConstructor; +import fuzs.puzzleslib.neoforge.api.data.v2.core.DataProviderHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.data.ModBlockTagsProvider; +import fuzs.visualworkbench.data.client.ModLanguageProvider; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLConstructModEvent; + +@Mod(VisualWorkbench.MOD_ID) +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class VisualWorkbenchNeoForge { + + @SubscribeEvent + public static void onConstructMod(final FMLConstructModEvent evt) { + ModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbench::new); + DataProviderHelper.registerDataProviders(VisualWorkbench.MOD_ID, ModBlockTagsProvider::new, ModLanguageProvider::new); + } +} diff --git a/1.20.4/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/client/VisualWorkbenchNeoForgeClient.java b/1.20.4/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/client/VisualWorkbenchNeoForgeClient.java new file mode 100644 index 0000000..b27cd11 --- /dev/null +++ b/1.20.4/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/client/VisualWorkbenchNeoForgeClient.java @@ -0,0 +1,18 @@ +package fuzs.visualworkbench.neoforge.client; + +import fuzs.puzzleslib.api.client.core.v1.ClientModConstructor; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.client.VisualWorkbenchClient; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLConstructModEvent; + +@Mod.EventBusSubscriber(modid = VisualWorkbench.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class VisualWorkbenchNeoForgeClient { + + @SubscribeEvent + public static void onConstructMod(final FMLConstructModEvent evt) { + ClientModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbenchClient::new); + } +} diff --git a/1.20.4/NeoForge/src/main/resources/META-INF/mods.toml b/1.20.4/NeoForge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..ef10121 --- /dev/null +++ b/1.20.4/NeoForge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,49 @@ +modLoader = "javafml" +loaderVersion = "*" +license = "${modLicense}" +issueTrackerURL = "${modIssueUrl}" + +[[mods]] +modId = "${modId}" +displayName = "${modName}" +description = "${modDescription}" +version = "${modVersion}" +authors = "${modAuthor}" +logoFile = "mod_banner.png" +logoBlur = false +displayURL = "${modPageUrl}" +updateJSONURL = "${modUpdateUrl}" +displayTest = "${modForgeDisplayTest}" + +[[mixins]] +config="${modId}.common.mixins.json" + +[[mixins]] +config="${modId}.neoforge.mixins.json" + +[[dependencies.${ modId }]] +modId = "neoforge" +mandatory = true +type = "required" +versionRange = "[${minNeoForgeVersion},)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${ modId }]] +modId = "minecraft" +mandatory = true +type = "required" +versionRange = "[${minecraftVersion}]" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${ modId }]] +modId = "puzzleslib" +mandatory = true +type = "required" +versionRange = "[${minPuzzlesVersion},)" +ordering = "NONE" +side = "BOTH" + +[modproperties.${ modId }] +catalogueImageIcon = "mod_logo.png" diff --git a/1.20.4/NeoForge/src/main/resources/neoforge.mixins.json b/1.20.4/NeoForge/src/main/resources/neoforge.mixins.json new file mode 100644 index 0000000..1fb3919 --- /dev/null +++ b/1.20.4/NeoForge/src/main/resources/neoforge.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "minVersion": "0.8", + "compatibilityLevel": "JAVA_17", + "package": "${modGroup}.neoforge.mixin", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/1.20.4/build.gradle b/1.20.4/build.gradle new file mode 100644 index 0000000..2417d2e --- /dev/null +++ b/1.20.4/build.gradle @@ -0,0 +1,9 @@ +plugins { + alias libs.plugins.architecturyloom apply false + alias libs.plugins.architecturyplugin apply false + alias libs.plugins.shadow apply false + alias libs.plugins.cursegradle apply false + alias libs.plugins.minotaur apply false +} + +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/v2/main.gradle" diff --git a/1.20.4/gradle.properties b/1.20.4/gradle.properties new file mode 100755 index 0000000..eab00e2 --- /dev/null +++ b/1.20.4/gradle.properties @@ -0,0 +1,46 @@ +org.gradle.jvmargs=-Xmx4G +org.gradle.daemon=false +copyBuildJar=true + +# Mod Attributes +modId=visualworkbench +modName=Visual Workbench +modVersion=20.4.2 +modAuthor=Fuzs +modDescription=Items stay inside crafting tables and are also rendered on top. It's really fancy! +modLicense=MPL-2.0 +modSourceUrl=https://github.com/Fuzss/visualworkbench +modIssueUrl=https://github.com/Fuzss/visualworkbench/issues +modUpdateUrl=https://raw.githubusercontent.com/Fuzss/modresources/main/update/visualworkbench.json +modMavenGroup=fuzs.visualworkbench +# "MATCH_VERSION" for a mod required on both sides, "IGNORE_SERVER_VERSION" for a server only mod, "IGNORE_ALL_VERSION" for a client only mod +modForgeDisplayTest=MATCH_VERSION +# "*" for a mod loaded on both sides, "server" for a server only mod, "client" for a client only mod +modFabricEnvironment=* + +# Version Catalog +dependenciesVersionCatalog=1.20.4-v40 +#dependenciesPuzzlesLibVersion=20.4.9 +#dependenciesMinPuzzlesLibVersion=20.4.9 + +# Mod Publishing +projectReleaseType=release +projectCurseForgeId=500273 +projectModrinthId=kfqD1JRw + +dependenciesRequiredFabricCurseForge=fabric-api, forge-config-api-port-fabric, puzzles-lib +dependenciesRequiredNeoForgeCurseForge=puzzles-lib +dependenciesRequiredForgeCurseForge=forge-config-api-port-fabric, puzzles-lib +dependenciesRequiredFabricModrinth=fabric-api, forge-config-api-port, puzzles-lib +dependenciesRequiredNeoForgeModrinth=puzzles-lib +dependenciesRequiredForgeModrinth=forge-config-api-port, puzzles-lib + +dependenciesOptionalFabricCurseForge=config-menus-forge +dependenciesOptionalNeoForgeCurseForge=config-menus-forge +dependenciesOptionalForgeCurseForge=config-menus-forge +dependenciesOptionalFabricModrinth=forge-config-screens +dependenciesOptionalNeoForgeModrinth=forge-config-screens +dependenciesOptionalForgeModrinth=forge-config-screens + +#dependenciesEmbeddedFabricCurseForge=cardinal-components-api +#dependenciesEmbeddedFabricModrinth=cardinal-components-api diff --git a/1.20.4/gradle/wrapper/gradle-wrapper.jar b/1.20.4/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..943f0cb Binary files /dev/null and b/1.20.4/gradle/wrapper/gradle-wrapper.jar differ diff --git a/1.20.4/gradle/wrapper/gradle-wrapper.properties b/1.20.4/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3499ded --- /dev/null +++ b/1.20.4/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/1.20.4/gradlew b/1.20.4/gradlew new file mode 100755 index 0000000..65dcd68 --- /dev/null +++ b/1.20.4/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# 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 +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/1.20.4/gradlew.bat b/1.20.4/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/1.20.4/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% 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. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +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. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/1.20.4/settings.gradle b/1.20.4/settings.gradle new file mode 100644 index 0000000..e401f79 --- /dev/null +++ b/1.20.4/settings.gradle @@ -0,0 +1,13 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven { url "https://maven.architectury.dev/" } + maven { url "https://maven.fabricmc.net/" } + maven { url "https://maven.neoforged.net/releases/" } + maven { url "https://maven.minecraftforge.net/" } + } +} + +include("Common", "Fabric", "NeoForge", "Forge") + +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/v2/settings.gradle" diff --git a/1.20/.idea/scopes/Fabric_sources.xml b/1.20/.idea/scopes/Fabric_sources.xml deleted file mode 100644 index 0448412..0000000 --- a/1.20/.idea/scopes/Fabric_sources.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/1.20/.idea/scopes/Forge_sources.xml b/1.20/.idea/scopes/Forge_sources.xml deleted file mode 100644 index 7b5f24d..0000000 --- a/1.20/.idea/scopes/Forge_sources.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/1.21.1/CHANGELOG.md b/1.21.1/CHANGELOG.md new file mode 100644 index 0000000..c36ef0b --- /dev/null +++ b/1.21.1/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v21.1.0-1.21.1] - 2024-09-11 +- Port to Minecraft 1.21.1 diff --git a/1.21.1/Common/build.gradle b/1.21.1/Common/build.gradle new file mode 100644 index 0000000..73d65b1 --- /dev/null +++ b/1.21.1/Common/build.gradle @@ -0,0 +1,13 @@ +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/${libs.versions.minecraft.get()}/common.gradle" + +dependencies { + // Puzzles Lib + modApi libs.puzzleslib.common + + // Just Enough Items + compileOnly libs.jeiapi.common +} + +tasks.withType(net.fabricmc.loom.task.AbstractRemapJarTask).configureEach { + targetNamespace = "named" +} diff --git a/1.21.1/Common/src/generated/resources/.cache/190dc8cc9e260d5273a6d094a2d5cfe3ccdbd9b6 b/1.21.1/Common/src/generated/resources/.cache/190dc8cc9e260d5273a6d094a2d5cfe3ccdbd9b6 new file mode 100644 index 0000000..381f28e --- /dev/null +++ b/1.21.1/Common/src/generated/resources/.cache/190dc8cc9e260d5273a6d094a2d5cfe3ccdbd9b6 @@ -0,0 +1,2 @@ +// 1.21 2024-07-06T22:52:38.447202 Language (en_us) +7383cbefca98a20426cf709fdfe773e860fc5f23 assets/visualworkbench/lang/en_us.json diff --git a/1.21.1/Common/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 b/1.21.1/Common/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 new file mode 100644 index 0000000..becbd2f --- /dev/null +++ b/1.21.1/Common/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 @@ -0,0 +1,2 @@ +// 1.21 2024-07-06T21:57:20.433682 Tags for minecraft:block mod id vanilla +d00da1153a305b41cd0709e40bbab70031f6f7fb data/visualworkbench/tags/block/unaltered_workbenches.json diff --git a/1.21.1/Common/src/generated/resources/assets/visualworkbench/lang/en_us.json b/1.21.1/Common/src/generated/resources/assets/visualworkbench/lang/en_us.json new file mode 100644 index 0000000..e3d7d8d --- /dev/null +++ b/1.21.1/Common/src/generated/resources/assets/visualworkbench/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "container.invalidBlock": "Unable to open. Break and replace to use.", + "tag.block.visualworkbench.unaltered_workbenches": "Unaltered Workbenches" +} \ No newline at end of file diff --git a/1.21.1/Common/src/generated/resources/assets/visualworkbench/lang/ja_jp.json b/1.21.1/Common/src/generated/resources/assets/visualworkbench/lang/ja_jp.json new file mode 100644 index 0000000..96e8e9e --- /dev/null +++ b/1.21.1/Common/src/generated/resources/assets/visualworkbench/lang/ja_jp.json @@ -0,0 +1,4 @@ +{ + "container.invalidBlock": "使用不可。回収し交換してください。", + "tag.block.visualworkbench.unaltered_workbenches": "変更前の作業台" +} diff --git a/1.21.1/Common/src/generated/resources/data/visualworkbench/tags/block/unaltered_workbenches.json b/1.21.1/Common/src/generated/resources/data/visualworkbench/tags/block/unaltered_workbenches.json new file mode 100644 index 0000000..a9e9b4d --- /dev/null +++ b/1.21.1/Common/src/generated/resources/data/visualworkbench/tags/block/unaltered_workbenches.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:smithing_table", + "minecraft:fletching_table" + ] +} \ No newline at end of file diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java new file mode 100644 index 0000000..4391673 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/VisualWorkbench.java @@ -0,0 +1,62 @@ +package fuzs.visualworkbench; + +import fuzs.puzzleslib.api.config.v3.ConfigHolder; +import fuzs.puzzleslib.api.core.v1.ModConstructor; +import fuzs.puzzleslib.api.core.v1.utility.ResourceLocationHelper; +import fuzs.puzzleslib.api.event.v1.AddBlockEntityTypeBlocksCallback; +import fuzs.puzzleslib.api.event.v1.RegistryEntryAddedCallback; +import fuzs.puzzleslib.api.event.v1.core.EventPhase; +import fuzs.puzzleslib.api.event.v1.entity.player.PlayerInteractEvents; +import fuzs.puzzleslib.api.event.v1.server.TagsUpdatedCallback; +import fuzs.visualworkbench.config.ClientConfig; +import fuzs.visualworkbench.config.CommonConfig; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.level.block.CraftingTableWithInventoryBlock; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.CraftingTableBlock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.function.Predicate; + +public class VisualWorkbench implements ModConstructor { + public static final String MOD_ID = "visualworkbench"; + public static final String MOD_NAME = "Visual Workbench"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_NAME); + + public static final ConfigHolder CONFIG = ConfigHolder.builder(MOD_ID) + .client(ClientConfig.class) + .common(CommonConfig.class); + public static final Predicate BLOCK_PREDICATE = (Block block) -> { + return block instanceof CraftingTableBlock && !(block instanceof CraftingTableWithInventoryBlock); + }; + + @Override + public void onConstructMod() { + ModRegistry.touch(); + registerEventHandlers(); + } + + private static void registerEventHandlers() { + RegistryEntryAddedCallback.registryEntryAdded(Registries.BLOCK) + .register(BlockConversionHandler.onRegistryEntryAdded(BLOCK_PREDICATE, + CraftingTableWithInventoryBlock::new, MOD_ID + )); + AddBlockEntityTypeBlocksCallback.EVENT.register( + BlockConversionHandler.onAddBlockEntityTypeBlocks(ModRegistry.CRAFTING_TABLE_BLOCK_ENTITY_TYPE)); + PlayerInteractEvents.USE_BLOCK.register( + BlockConversionHandler.onUseBlock(ModRegistry.UNALTERED_WORKBENCHES_BLOCK_TAG, + () -> CONFIG.get(CommonConfig.class).disableVanillaWorkbench + )); + TagsUpdatedCallback.EVENT.register(EventPhase.FIRST, + BlockConversionHandler.onTagsUpdated(ModRegistry.UNALTERED_WORKBENCHES_BLOCK_TAG, BLOCK_PREDICATE) + ); + } + + public static ResourceLocation id(String path) { + return ResourceLocationHelper.fromNamespaceAndPath(MOD_ID, path); + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java new file mode 100644 index 0000000..c8a8d8c --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/VisualWorkbenchClient.java @@ -0,0 +1,48 @@ +package fuzs.visualworkbench.client; + +import fuzs.puzzleslib.api.client.core.v1.ClientModConstructor; +import fuzs.puzzleslib.api.client.core.v1.context.BlockEntityRenderersContext; +import fuzs.puzzleslib.api.client.core.v1.context.MenuScreensContext; +import fuzs.puzzleslib.api.client.event.v1.ModelEvents; +import fuzs.puzzleslib.api.core.v1.context.PackRepositorySourcesContext; +import fuzs.puzzleslib.api.event.v1.LoadCompleteCallback; +import fuzs.puzzleslib.api.resources.v1.DynamicPackResources; +import fuzs.puzzleslib.api.resources.v1.PackResourcesHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.client.handler.BlockModelHandler; +import fuzs.visualworkbench.client.renderer.blockentity.CraftingTableBlockEntityRenderer; +import fuzs.visualworkbench.data.client.DynamicModelProvider; +import fuzs.visualworkbench.init.ModRegistry; +import net.minecraft.client.gui.screens.inventory.CraftingScreen; + +public class VisualWorkbenchClient implements ClientModConstructor { + + @Override + public void onConstructMod() { + registerHandlers(); + } + + private static void registerHandlers() { + ModelEvents.MODIFY_UNBAKED_MODEL.register(BlockModelHandler::onModifyUnbakedModel); + LoadCompleteCallback.EVENT.register(BlockModelHandler::onLoadComplete); + } + + @Override + public void onRegisterMenuScreens(MenuScreensContext context) { + context.registerMenuScreen(ModRegistry.CRAFTING_MENU_TYPE.value(), CraftingScreen::new); + } + + @Override + public void onRegisterBlockEntityRenderers(BlockEntityRenderersContext context) { + context.registerBlockEntityRenderer(ModRegistry.CRAFTING_TABLE_BLOCK_ENTITY_TYPE.value(), + CraftingTableBlockEntityRenderer::new + ); + } + + @Override + public void onAddResourcePackFinders(PackRepositorySourcesContext context) { + context.addRepositorySource(PackResourcesHelper.buildClientPack(VisualWorkbench.id("default_block_models"), + DynamicPackResources.create(DynamicModelProvider::new), true + )); + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/handler/BlockModelHandler.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/handler/BlockModelHandler.java new file mode 100644 index 0000000..ff12847 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/handler/BlockModelHandler.java @@ -0,0 +1,76 @@ +package fuzs.visualworkbench.client.handler; + +import com.google.common.base.Suppliers; +import com.google.common.collect.Maps; +import fuzs.puzzleslib.api.client.core.v1.ClientAbstractions; +import fuzs.puzzleslib.api.event.v1.core.EventResultHolder; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import net.minecraft.Util; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.BlockModelShaper; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.Property; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class BlockModelHandler { + private static final Supplier> MODEL_LOCATIONS; + + static { + MODEL_LOCATIONS = Suppliers.memoize(() -> { + return BlockConversionHandler.getBlockConversions().entrySet().stream().flatMap(entry -> { + return convertAllBlockStates(entry.getValue(), entry.getKey()).entrySet().stream(); + }).collect(Util.toMap()); + }); + } + + public static void onLoadComplete() { + // run a custom implementation here, the appropriate method in client mod constructor runs together with other mods, so we might miss some entries + for (Map.Entry entry : BlockConversionHandler.getBlockConversions().entrySet()) { + RenderType renderType = ClientAbstractions.INSTANCE.getRenderType(entry.getKey()); + ClientAbstractions.INSTANCE.registerRenderType(entry.getValue(), renderType); + } + } + + public static EventResultHolder onModifyUnbakedModel(ModelResourceLocation modelLocation, Supplier unbakedModel, Function modelGetter, BiConsumer modelAdder) { + if (MODEL_LOCATIONS.get().containsKey(modelLocation)) { + return EventResultHolder.interrupt(modelGetter.apply(MODEL_LOCATIONS.get().get(modelLocation))); + } else { + return EventResultHolder.pass(); + } + } + + private static Map convertAllBlockStates(Block oldBlock, Block newBlock) { + Map modelLocations = Maps.newHashMap(); + for (BlockState oldBlockState : oldBlock.getStateDefinition().getPossibleStates()) { + BlockState newBlockState = convertBlockState(newBlock.getStateDefinition(), oldBlockState); + modelLocations.put(BlockModelShaper.stateToModelLocation(oldBlockState), BlockModelShaper.stateToModelLocation(newBlockState)); + } + return modelLocations; + } + + private static BlockState convertBlockState(StateDefinition newStateDefinition, BlockState oldBlockState) { + BlockState newBlockState = newStateDefinition.any(); + for (Map.Entry, Comparable> entry : oldBlockState.getValues().entrySet()) { + newBlockState = setBlockStateValue(entry.getKey(), entry.getValue(), newStateDefinition::getProperty, newBlockState); + } + return newBlockState; + } + + private static , V extends T> BlockState setBlockStateValue(Property oldProperty, Comparable oldValue, Function> propertyGetter, BlockState blockState) { + Property newProperty = propertyGetter.apply(oldProperty.getName()); + if (newProperty != null) { + return blockState.setValue((Property) newProperty, (V) oldValue); + } + return blockState; + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/CraftingTableBlockEntityRenderer.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/CraftingTableBlockEntityRenderer.java new file mode 100644 index 0000000..da38e5f --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/client/renderer/blockentity/CraftingTableBlockEntityRenderer.java @@ -0,0 +1,95 @@ +package fuzs.visualworkbench.client.renderer.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableAnimationController; +import fuzs.visualworkbench.world.level.block.entity.WorkbenchVisualsProvider; +import fuzs.visualworkbench.config.ClientConfig; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.util.Mth; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.Nullable; + +public class CraftingTableBlockEntityRenderer implements BlockEntityRenderer { + private final ItemRenderer itemRenderer; + + public CraftingTableBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + this.itemRenderer = context.getItemRenderer(); + } + + @Override + public void render(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight, int packedOverlay) { + // light is normally always 0 since it checks inside the crafting table block which is solid, but contents are rendered in the block above + packedLight = blockEntity.getLevel() != null ? LevelRenderer.getLightColor(blockEntity.getLevel(), blockEntity.getBlockPos().above()) : 15728880; + for (int i = 0; i < blockEntity.getContainerSize(); ++i) { + ItemStack itemStack = blockEntity.getItem(i); + if (!itemStack.isEmpty()) { + this.renderIngredientItem(blockEntity, partialTick, poseStack, multiBufferSource, packedLight, packedOverlay, i, itemStack); + } + } + ItemStack itemStack = blockEntity.getCraftingResult(); + if (!itemStack.isEmpty()) { + this.renderResultItem(itemStack, blockEntity.getLevel(), blockEntity.getAnimationController().ticks + partialTick, poseStack, multiBufferSource, packedLight); + } + } + + private void renderIngredientItem(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight, int packedOverlay, int i, ItemStack itemStack) { + poseStack.pushPose(); + if (VisualWorkbench.CONFIG.get(ClientConfig.class).flatRendering) { + this.setupFlatRenderer(blockEntity.getAnimationController(), partialTick, poseStack, itemStack, i); + } else { + this.setupFloatingRenderer(blockEntity.getAnimationController(), partialTick, poseStack, itemStack, i); + } + this.itemRenderer.renderStatic(itemStack, ItemDisplayContext.FIXED, packedLight, packedOverlay, poseStack, multiBufferSource, blockEntity.getLevel(), (int) blockEntity.getBlockPos().asLong() + i); + poseStack.popPose(); + } + + private void setupFloatingRenderer(CraftingTableAnimationController animationController, float partialTick, PoseStack poseStack, ItemStack itemStack, int index) { + // -0.0125 to 0.0125 + float shift = (float) Math.abs(((animationController.ticks + partialTick) * 50.0 + (index * 1000L)) % 5000L - 2500L) / 200000.0F; + BakedModel model = this.itemRenderer.getModel(itemStack, null, null, 0); + boolean blockItem = model.isGui3d(); + poseStack.translate(0.5, shift, 0.5); + poseStack.mulPose(Axis.YP.rotationDegrees(Mth.lerp(partialTick, animationController.currentAngle, animationController.nextAngle))); + poseStack.translate((double) (index % 3) * 3.0 / 16.0 + 0.3125 - 0.5, 1.09375, (double) (index / 3) * 3.0 / 16.0 + 0.3125 - 0.5); + float scale = blockItem ? 0.24F : 0.18F; + poseStack.scale(scale, scale, scale); + } + + private void setupFlatRenderer(CraftingTableAnimationController animationController, float partialTick, PoseStack poseStack, ItemStack itemStack, int index) { + BakedModel bakedModel = this.itemRenderer.getModel(itemStack, null, null, 0); + boolean gui3d = bakedModel.isGui3d(); + poseStack.translate(0.5, 0.0, 0.5); + poseStack.mulPose(Axis.YP.rotationDegrees(Mth.lerp(partialTick, animationController.currentAngle, animationController.nextAngle))); + poseStack.translate((double) (index % 3) * 3.0 / 16.0 + 0.3125 - 0.5, gui3d ? 1.0625 : 1.005, (double) (index / 3) * 3.0 / 16.0 + 0.3125 - 0.5); + poseStack.mulPose(Axis.XP.rotationDegrees(90.0F)); + poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F)); + float scale = gui3d ? 0.25F : 0.175F; + poseStack.scale(scale, scale, scale); + } + + private void renderResultItem(ItemStack itemStack, @Nullable Level level, float time, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight) { + if (!VisualWorkbench.CONFIG.get(ClientConfig.class).renderResult) return; + poseStack.pushPose(); + poseStack.translate(0.5F, 1.15F, 0.5F); + BakedModel model = this.itemRenderer.getModel(itemStack, level, null, 0); + float hoverOffset = Mth.sin(time / 10.0F) * 0.04F + 0.1F; + float modelYScale = model.getTransforms().getTransform(ItemDisplayContext.GROUND).scale.y(); + poseStack.translate(0.0, hoverOffset + 0.25F * modelYScale, 0.0); + poseStack.mulPose(Axis.YP.rotation(time / 20.0F)); + if (!model.isGui3d()) poseStack.scale(0.75F, 0.75F, 0.75F); + this.itemRenderer.render(itemStack, ItemDisplayContext.GROUND, false, poseStack, multiBufferSource, packedLight, OverlayTexture.NO_OVERLAY, model); + poseStack.popPose(); + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java new file mode 100644 index 0000000..6a3b315 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/config/ClientConfig.java @@ -0,0 +1,17 @@ +package fuzs.visualworkbench.config; + +import fuzs.puzzleslib.api.config.v3.Config; +import fuzs.puzzleslib.api.config.v3.ConfigCore; + +public class ClientConfig implements ConfigCore { + @Config(description = "Makes crafting table contents lay flat on the table instead of floating above.") + public boolean flatRendering = false; + @Config(description = "Render the result of the crafting operation in addition to crafting table contents.") + public boolean renderResult = true; + @Config(description = "Rotate crafting table contents so they always face the closest player.") + public RotateIngredients rotateIngredients = RotateIngredients.CLOSEST_PLAYER; + + public enum RotateIngredients { + CLOSEST_PLAYER, CRAFTING_PLAYER, NEVER + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/config/CommonConfig.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/config/CommonConfig.java new file mode 100644 index 0000000..d431c09 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/config/CommonConfig.java @@ -0,0 +1,11 @@ +package fuzs.visualworkbench.config; + +import fuzs.puzzleslib.api.config.v3.Config; +import fuzs.puzzleslib.api.config.v3.ConfigCore; + +public class CommonConfig implements ConfigCore { + @Config(description = "Leftover vanilla crafting tables in a world become unusable until they are broken and replaced.") + public boolean disableVanillaWorkbench = true; + @Config(description = "Replace vanilla crafting tables created in structures during world generation. Does not affect already generated blocks.") + public boolean convertVanillaWorkbenchDuringWorldGen = true; +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/ModBlockTagsProvider.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/ModBlockTagsProvider.java new file mode 100644 index 0000000..1920a4c --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/ModBlockTagsProvider.java @@ -0,0 +1,21 @@ +package fuzs.visualworkbench.data; + +import fuzs.puzzleslib.api.data.v2.core.DataProviderContext; +import fuzs.puzzleslib.api.data.v2.tags.AbstractTagProvider; +import fuzs.visualworkbench.init.ModRegistry; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; + +public class ModBlockTagsProvider extends AbstractTagProvider { + + public ModBlockTagsProvider(DataProviderContext context) { + super(Registries.BLOCK, context); + } + + @Override + public void addTags(HolderLookup.Provider provider) { + this.add(ModRegistry.UNALTERED_WORKBENCHES_BLOCK_TAG).add(Blocks.SMITHING_TABLE, Blocks.FLETCHING_TABLE); + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/client/DynamicModelProvider.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/client/DynamicModelProvider.java new file mode 100644 index 0000000..59b9810 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/client/DynamicModelProvider.java @@ -0,0 +1,31 @@ +package fuzs.visualworkbench.data.client; + +import fuzs.puzzleslib.api.client.data.v2.AbstractModelProvider; +import fuzs.puzzleslib.api.data.v2.core.DataProviderContext; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import net.minecraft.data.models.BlockModelGenerators; +import net.minecraft.data.models.blockstates.MultiVariantGenerator; +import net.minecraft.data.models.blockstates.Variant; +import net.minecraft.data.models.blockstates.VariantProperties; +import net.minecraft.data.models.model.ModelLocationUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; + +public class DynamicModelProvider extends AbstractModelProvider { + + public DynamicModelProvider(DataProviderContext context) { + super(context); + } + + @Override + public void addBlockModels(BlockModelGenerators builder) { + // dynamically generate a basic stone block model for every diagonal block so the model bakery logs no missing model + // don't use an air model so the blocks remain visible + ResourceLocation resourceLocation = ModelLocationUtils.getModelLocation(Blocks.STONE); + BlockConversionHandler.getBlockConversions().values().forEach((Block block) -> { + builder.blockStateOutput.accept(MultiVariantGenerator.multiVariant(block, Variant.variant().with(VariantProperties.MODEL, resourceLocation))); + builder.skipAutoItemBlock(block); + }); + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/client/ModLanguageProvider.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/client/ModLanguageProvider.java new file mode 100644 index 0000000..59b5923 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/data/client/ModLanguageProvider.java @@ -0,0 +1,19 @@ +package fuzs.visualworkbench.data.client; + +import fuzs.puzzleslib.api.client.data.v2.AbstractLanguageProvider; +import fuzs.puzzleslib.api.data.v2.core.DataProviderContext; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import fuzs.visualworkbench.init.ModRegistry; + +public class ModLanguageProvider extends AbstractLanguageProvider { + + public ModLanguageProvider(DataProviderContext context) { + super(context); + } + + @Override + public void addTranslations(TranslationBuilder builder) { + builder.add(BlockConversionHandler.INVALID_BLOCK_COMPONENT, "Unable to open. Break and replace to use."); + builder.add(ModRegistry.UNALTERED_WORKBENCHES_BLOCK_TAG, "Unaltered Workbenches"); + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/handler/BlockConversionHandler.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/handler/BlockConversionHandler.java new file mode 100644 index 0000000..73dacc3 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/handler/BlockConversionHandler.java @@ -0,0 +1,164 @@ +package fuzs.visualworkbench.handler; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Maps; +import fuzs.puzzleslib.api.block.v1.BlockConversionHelper; +import fuzs.puzzleslib.api.core.v1.utility.ResourceLocationHelper; +import fuzs.puzzleslib.api.event.v1.AddBlockEntityTypeBlocksCallback; +import fuzs.puzzleslib.api.event.v1.RegistryEntryAddedCallback; +import fuzs.puzzleslib.api.event.v1.core.EventResultHolder; +import fuzs.puzzleslib.api.event.v1.entity.player.PlayerInteractEvents; +import fuzs.puzzleslib.api.event.v1.server.TagsUpdatedCallback; +import fuzs.puzzleslib.api.init.v3.registry.RegistryHelper; +import net.minecraft.ChatFormatting; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +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.block.state.properties.Property; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.*; + +public class BlockConversionHandler { + public static final Component INVALID_BLOCK_COMPONENT = Component.translatable("container.invalidBlock"); + private static final BiMap BLOCK_CONVERSIONS = HashBiMap.create(); + private static final Map BLOCK_STATE_CONVERSIONS_CACHE = new MapMaker().weakKeys().weakValues().makeMap(); + + public static RegistryEntryAddedCallback onRegistryEntryAdded(Predicate filter, UnaryOperator factory, String modId) { + return (Registry registry, ResourceLocation id, Block block, BiConsumer> registrar) -> { + if (filter.test(block)) { + ResourceLocation resourceLocation = ResourceLocationHelper.fromNamespaceAndPath(modId, + id.getNamespace() + "/" + id.getPath() + ); + registrar.accept(resourceLocation, () -> { + Block newBlock = factory.apply(block); + BLOCK_CONVERSIONS.put(block, newBlock); + return newBlock; + }); + } + }; + } + + public static BiMap getBlockConversions() { + return Maps.unmodifiableBiMap(BLOCK_CONVERSIONS); + } + + public static AddBlockEntityTypeBlocksCallback onAddBlockEntityTypeBlocks(Holder.Reference> blockEntityType) { + return (BiConsumer, Block> consumer) -> { + for (Map.Entry entry : BLOCK_CONVERSIONS.entrySet()) { + consumer.accept(blockEntityType.value(), entry.getValue()); + } + }; + } + + public static PlayerInteractEvents.UseBlock onUseBlock(TagKey unalteredBlocks, BooleanSupplier disableVanillaBlock) { + return (Player player, Level level, InteractionHand interactionHand, BlockHitResult hitResult) -> { + if (!disableVanillaBlock.getAsBoolean()) return EventResultHolder.pass(); + BlockState blockState = level.getBlockState(hitResult.getBlockPos()); + if (BLOCK_CONVERSIONS.containsKey(blockState.getBlock()) && !blockState.is(unalteredBlocks)) { + player.displayClientMessage( + Component.empty().append(INVALID_BLOCK_COMPONENT).withStyle(ChatFormatting.RED), true); + return EventResultHolder.interrupt(InteractionResult.sidedSuccess(level.isClientSide)); + } else { + return EventResultHolder.pass(); + } + }; + } + + public static TagsUpdatedCallback onTagsUpdated(TagKey unalteredBlocks, Predicate filter) { + return (RegistryAccess registryAccess, boolean client) -> { + for (Map.Entry, Item> entry : BuiltInRegistries.ITEM.entrySet()) { + if (entry.getValue() instanceof BlockItem blockItem) { + Block block = blockItem.getBlock(); + setItemForBlock(filter, blockItem, block); + setBlockForItem(unalteredBlocks, blockItem, block); + } + } + BLOCK_CONVERSIONS.forEach(BlockConversionHelper::copyBoundTags); + }; + } + + private static void setItemForBlock(Predicate filter, BlockItem blockItem, Block block) { + if (filter.test(block)) { + BlockConversionHelper.setItemForBlock(BLOCK_CONVERSIONS.get(block), blockItem); + } + } + + private static void setBlockForItem(TagKey tagKey, BlockItem blockItem, Block block) { + Block oldBlock; + Block newBlock = BLOCK_CONVERSIONS.get(block); + if (newBlock != null) { + oldBlock = block; + } else { + oldBlock = BLOCK_CONVERSIONS.inverse().get(block); + if (oldBlock != null) { + newBlock = block; + } else { + return; + } + } + if (RegistryHelper.is(tagKey, oldBlock)) { + BlockConversionHelper.setBlockForItem(blockItem, oldBlock); + } else { + BlockConversionHelper.setBlockForItem(blockItem, newBlock); + } + } + + @Nullable + public static BlockState convertToVanillaBlock(@Nullable BlockState blockState) { + // mod replacement block coming in, we need to forward the original + return applyBlockConversion(blockState, true); + } + + @Nullable + public static BlockState convertFromVanillaBlock(@Nullable BlockState blockState) { + // original block coming in, we need to convert back to our replacement + return applyBlockConversion(blockState, false); + } + + @Nullable + private static BlockState applyBlockConversion(@Nullable BlockState blockState, boolean inverse) { + if (blockState != null) { + return BLOCK_STATE_CONVERSIONS_CACHE.computeIfAbsent(blockState, applyBlockConversion(inverse)); + } else { + return null; + } + } + + private static UnaryOperator applyBlockConversion(boolean inverse) { + return (BlockState blockState) -> { + BiMap blockConversions = inverse ? BLOCK_CONVERSIONS.inverse() : BLOCK_CONVERSIONS; + if (blockState != null && blockConversions.containsKey(blockState.getBlock())) { + Block block = blockConversions.get(blockState.getBlock()); + return copyAllProperties(blockState, block.defaultBlockState()); + } else { + return blockState; + } + }; + } + + private static , V extends T> BlockState copyAllProperties(BlockState oldBlockState, BlockState newBlockState) { + for (Map.Entry, Comparable> entry : oldBlockState.getValues().entrySet()) { + newBlockState = newBlockState.trySetValue((Property) entry.getKey(), (V) entry.getValue()); + } + return newBlockState; + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java new file mode 100644 index 0000000..bc81904 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/init/ModRegistry.java @@ -0,0 +1,27 @@ +package fuzs.visualworkbench.init; + +import fuzs.puzzleslib.api.init.v3.registry.RegistryManager; +import fuzs.puzzleslib.api.init.v3.tags.BoundTagFactory; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.world.inventory.VisualCraftingMenu; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableBlockEntity; +import net.minecraft.core.Holder; +import net.minecraft.tags.TagKey; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; + +public class ModRegistry { + static final RegistryManager REGISTRIES = RegistryManager.from(VisualWorkbench.MOD_ID); + public static final Holder.Reference> CRAFTING_TABLE_BLOCK_ENTITY_TYPE = REGISTRIES.registerBlockEntityType( + "crafting_table", () -> BlockEntityType.Builder.of(CraftingTableBlockEntity::new)); + public static final Holder.Reference> CRAFTING_MENU_TYPE = REGISTRIES.registerMenuType( + "crafting", () -> VisualCraftingMenu::new); + + static final BoundTagFactory TAGS = BoundTagFactory.make(VisualWorkbench.MOD_ID); + public static final TagKey UNALTERED_WORKBENCHES_BLOCK_TAG = TAGS.registerBlockTag("unaltered_workbenches"); + + public static void touch() { + // NO-OP + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java new file mode 100644 index 0000000..9696586 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/integration/jei/VisualWorkbenchJEIPlugin.java @@ -0,0 +1,24 @@ +package fuzs.visualworkbench.integration.jei; + +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.inventory.VisualCraftingMenu; +import mezz.jei.api.IModPlugin; +import mezz.jei.api.JeiPlugin; +import mezz.jei.api.constants.RecipeTypes; +import mezz.jei.api.registration.IRecipeTransferRegistration; +import net.minecraft.resources.ResourceLocation; + +@JeiPlugin +public class VisualWorkbenchJEIPlugin implements IModPlugin { + + @Override + public ResourceLocation getPluginUid() { + return VisualWorkbench.id("crafting"); + } + + @Override + public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { + registration.addRecipeTransferHandler(VisualCraftingMenu.class, ModRegistry.CRAFTING_MENU_TYPE.value(), RecipeTypes.CRAFTING, 1, 9, 10, 36); + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/mixin/WorldGenRegionMixin.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/mixin/WorldGenRegionMixin.java new file mode 100644 index 0000000..14c64ab --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/mixin/WorldGenRegionMixin.java @@ -0,0 +1,23 @@ +package fuzs.visualworkbench.mixin; + +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.config.CommonConfig; +import fuzs.visualworkbench.handler.BlockConversionHandler; +import net.minecraft.server.level.WorldGenRegion; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(WorldGenRegion.class) +abstract class WorldGenRegionMixin { + + @ModifyVariable(method = "setBlock", at = @At(value = "LOAD", ordinal = 0), argsOnly = true) + public BlockState setBlock(BlockState blockState) { + if (VisualWorkbench.CONFIG.get(CommonConfig.class).convertVanillaWorkbenchDuringWorldGen) { + return BlockConversionHandler.convertFromVanillaBlock(blockState); + } else { + return blockState; + } + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualCraftingMenu.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualCraftingMenu.java new file mode 100644 index 0000000..b4371fa --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/inventory/VisualCraftingMenu.java @@ -0,0 +1,77 @@ +package fuzs.visualworkbench.world.inventory; + +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.*; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class VisualCraftingMenu extends CraftingMenu implements ContainerListener { + private final Container blockEntity; + + public VisualCraftingMenu(int id, Inventory inventory) { + super(id, inventory); + this.blockEntity = new SimpleContainer(); + } + + public VisualCraftingMenu(int id, Inventory inventory, CraftingTableBlockEntity blockEntity, ContainerLevelAccess access) { + super(id, inventory, access); + ((TransientCraftingContainer) this.craftSlots).items = blockEntity.getItems(); + this.resultSlots.itemStacks = blockEntity.getResultItems(); + this.blockEntity = blockEntity; + this.addSlotListener(this); + // always update recipe output when opening menu, otherwise could be missing or outdated if the block entity didn't save it correctly + this.slotsChanged(this.craftSlots); + } + + @Override + public MenuType getType() { + return ModRegistry.CRAFTING_MENU_TYPE.value(); + } + + @Override + public void slotsChanged(Container container) { + super.slotsChanged(container); + if (container == this.craftSlots || container == this.resultSlots) { + this.access.execute((Level level, BlockPos blockPos) -> { + this.blockEntity.setChanged(); + }); + } + } + + @Override + public void removed(Player player) { + // prevent items from being cleared out of the container + ContainerLevelAccess containerLevelAccess = this.access; + this.access = ContainerLevelAccess.NULL; + super.removed(player); + this.access = containerLevelAccess; + } + + @Override + public boolean stillValid(Player player) { + return this.access.evaluate((Level level, BlockPos blockPos) -> { + // craft slots are extended to forward this to the block entity, normally in vanilla this would always return true + return this.blockEntity.stillValid(player); + }, true); + } + + @Override + public void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack itemStack) { + this.access.execute((Level level, BlockPos blockPos) -> { + if (dataSlotIndex >= 0 && dataSlotIndex < this.getSize()) { + this.blockEntity.setChanged(); + } + }); + } + + @Override + public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) { + // NO-OP + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/CraftingTableWithInventoryBlock.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/CraftingTableWithInventoryBlock.java new file mode 100644 index 0000000..caf409a --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/CraftingTableWithInventoryBlock.java @@ -0,0 +1,90 @@ +package fuzs.visualworkbench.world.level.block; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import fuzs.puzzleslib.api.block.v1.entity.TickingEntityBlock; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.level.block.entity.CraftingTableBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.stats.Stats; +import net.minecraft.world.Containers; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BlockTypes; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +import java.util.function.Predicate; + +public class CraftingTableWithInventoryBlock extends BaseEntityBlock implements TickingEntityBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( + instance -> instance.group(BlockTypes.CODEC.fieldOf("block").forGetter(block -> block.block)).apply(instance, CraftingTableWithInventoryBlock::new) + ); + + private final Block block; + + public CraftingTableWithInventoryBlock(Block block) { + super(BlockBehaviour.Properties.ofFullCopy(block).dropsLike(block)); + this.block = block; + } + + @Override + public String getDescriptionId() { + return this.block.getDescriptionId(); + } + + @Override + protected MapCodec codec() { + return CODEC; + } + + @Override + public RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Override + public BlockEntityType getBlockEntityType() { + return ModRegistry.CRAFTING_TABLE_BLOCK_ENTITY_TYPE.value(); + } + + @Override + protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else if (level.getBlockEntity(pos) instanceof CraftingTableBlockEntity blockEntity) { + player.openMenu(blockEntity); + player.awardStat(Stats.INTERACT_WITH_CRAFTING_TABLE); + } + + return InteractionResult.CONSUME; + } + + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { + Containers.dropContentsOnDestroy(state, newState, level, pos); + super.onRemove(state, level, pos, newState, movedByPiston); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState blockState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos blockPos) { + // similar to Crafter + if (level.getBlockEntity(blockPos) instanceof CraftingTableBlockEntity blockEntity) { + return (int) blockEntity.getItems().stream().filter(Predicate.not(ItemStack::isEmpty)).count(); + } else { + return 0; + } + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableAnimationController.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableAnimationController.java new file mode 100644 index 0000000..2091af1 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableAnimationController.java @@ -0,0 +1,116 @@ +package fuzs.visualworkbench.world.level.block.entity; + +import fuzs.puzzleslib.api.core.v1.Proxy; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.config.ClientConfig; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.CraftingScreen; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +/** + * A client-side provider for ticking and storing crafting table item animations on a block entity. + *

Initialize an instance in your block entity constructor, then implement a call for {@link CraftingTableAnimationController#tick(Level)} on the client. + *

Make sure the code is never accidentally called on the server as it accesses client-only classes. + *

All animation code in this class is taken from the old RealBench mod. + */ +public class CraftingTableAnimationController { + private final Vec3 position; + public int ticks; + public float currentAngle; + public float nextAngle; + public int sector; + public boolean animating; + public float animationAngleStart; + public float animationAngleEnd; + public double startTicks; + public double playerAngle; + + public CraftingTableAnimationController(BlockPos blockPos) { + this.position = blockPos.getCenter(); + } + + public void tick(Level level) { + ++this.ticks; + this.setPlayerAngle(level); + this.setCurrentSector(); + this.tryAnimate(); + } + + private void setPlayerAngle(Level level) { + Player player; + if (VisualWorkbench.CONFIG.get(ClientConfig.class).rotateIngredients != ClientConfig.RotateIngredients.NEVER) { + player = level.getNearestPlayer(this.position.x(), this.position.y(), this.position.z(), 3.0, (Entity entity) -> { + if (entity.isSpectator()) { + return false; + } else if (VisualWorkbench.CONFIG.get(ClientConfig.class).rotateIngredients == ClientConfig.RotateIngredients.CLOSEST_PLAYER) { + return true; + } else { + if (entity == Proxy.INSTANCE.getClientPlayer()) { + return Minecraft.getInstance().screen instanceof CraftingScreen; + } else { + return false; + } + } + }); + } else { + player = null; + } + if (player != null) { + double d0 = player.getX() - this.position.x(); + double d1 = player.getZ() - this.position.z(); + this.playerAngle = (Math.atan2(-d0, -d1) + 3.9269908169872414D) % 6.283185307179586D; + } + } + + private void setCurrentSector() { + int sector = (int) (this.playerAngle * 2.0 / Math.PI); + if (this.sector != sector) { + this.animating = true; + this.animationAngleStart = this.currentAngle; + float delta1 = sector * 90.0F - this.currentAngle; + float abs1 = Math.abs(delta1); + float delta2 = delta1 + 360.0F; + float shift = Math.abs(delta2); + float delta3 = delta1 - 360.0F; + float abs3 = Math.abs(delta3); + if (abs3 < abs1 && abs3 < shift) { + this.animationAngleEnd = delta3 + this.currentAngle; + } else if (shift < abs1 && shift < abs3) { + this.animationAngleEnd = delta2 + this.currentAngle; + } else { + this.animationAngleEnd = delta1 + this.currentAngle; + } + this.startTicks = this.ticks; + this.sector = sector; + } + } + + private void tryAnimate() { + if (this.animating) { + if (this.ticks >= this.startTicks + 20) { + this.animating = false; + this.currentAngle = this.nextAngle = (this.animationAngleEnd + 360.0F) % 360.0F; + } else { + this.currentAngle = (calcEaseOutQuad(this.ticks - this.startTicks, this.animationAngleStart, this.animationAngleEnd - this.animationAngleStart, 20.0) + 360.0F) % 360.0F; + this.nextAngle = (calcEaseOutQuad(Math.min(this.ticks + 1 - this.startTicks, 20), this.animationAngleStart, this.animationAngleEnd - this.animationAngleStart, 20.0) + 360.0F) % 360.0F; + if (this.currentAngle != 0.0F || this.nextAngle != 0.0F) { + if (this.currentAngle == 0.0F && this.nextAngle >= 180.0F) { + this.currentAngle = 360.0F; + } + if (this.nextAngle == 0.0F && this.currentAngle >= 180.0F) { + this.nextAngle = 360.0F; + } + } + } + } + } + + private static float calcEaseOutQuad(double t, float b, float c, double d) { + float z = (float) t / (float) d; + return -c * z * (z - 2.0F) + b; + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java new file mode 100644 index 0000000..8939321 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/CraftingTableBlockEntity.java @@ -0,0 +1,131 @@ +package fuzs.visualworkbench.world.level.block.entity; + +import fuzs.puzzleslib.api.block.v1.entity.TickingBlockEntity; +import fuzs.puzzleslib.api.container.v1.ContainerMenuHelper; +import fuzs.puzzleslib.api.container.v1.ContainerSerializationHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.init.ModRegistry; +import fuzs.visualworkbench.world.inventory.VisualCraftingMenu; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +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.ContainerLevelAccess; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +public class CraftingTableBlockEntity extends RandomizableContainerBlockEntity implements TickingBlockEntity, WorkbenchVisualsProvider { + public static final MutableComponent COMPONENT_CRAFTING = Component.translatable("container.crafting"); + public static final String TAG_RESULT = VisualWorkbench.id("result").toString(); + + private final CraftingTableAnimationController animationController; + private final NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY); + private final NonNullList resultItems = NonNullList.withSize(1, ItemStack.EMPTY); + + public CraftingTableBlockEntity(BlockPos pos, BlockState blockState) { + super(ModRegistry.CRAFTING_TABLE_BLOCK_ENTITY_TYPE.value(), pos, blockState); + this.animationController = new CraftingTableAnimationController(pos); + } + + @Override + public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + super.loadAdditional(tag, registries); + this.items.clear(); + this.resultItems.clear(); + if (!this.tryLoadLootTable(tag)) { + ContainerHelper.loadAllItems(tag, this.items, registries); + ContainerSerializationHelper.loadAllItems(TAG_RESULT, tag, this.resultItems, registries); + } + } + + @Override + protected void saveAdditional(CompoundTag compoundTag, HolderLookup.Provider registries) { + super.saveAdditional(compoundTag, registries); + if (!this.trySaveLootTable(compoundTag)) { + ContainerHelper.saveAllItems(compoundTag, this.items, registries); + ContainerSerializationHelper.saveAllItems(TAG_RESULT, compoundTag, this.resultItems, registries); + } + } + + @Override + @Nullable + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + return this.saveWithoutMetadata(registries); + } + + @Override + public void setChanged() { + super.setChanged(); + if (this.level != null) { + this.level.sendBlockUpdated(this.worldPosition, this.getBlockState(), this.getBlockState(), 3); + } + } + + @Override + public NonNullList getItems() { + return this.items; + } + + @Override + protected void setItems(NonNullList items) { + ContainerMenuHelper.copyItemsIntoContainer(items, this); + } + + @Override + protected Component getDefaultName() { + return COMPONENT_CRAFTING; + } + + @Override + protected AbstractContainerMenu createMenu(int containerId, Inventory inventory) { + return new VisualCraftingMenu(containerId, + inventory, + this, + ContainerLevelAccess.create(this.getLevel(), this.getBlockPos()) + ); + } + + @Override + public int getContainerSize() { + return this.items.size(); + } + + @Override + public boolean stillValid(Player player) { + return Container.stillValidBlockEntity(this, player); + } + + @Override + public void clientTick() { + this.animationController.tick(this.getLevel()); + } + + public NonNullList getResultItems() { + return this.resultItems; + } + + @Override + public ItemStack getCraftingResult() { + return this.resultItems.get(0); + } + + @Override + public CraftingTableAnimationController getAnimationController() { + return this.animationController; + } +} diff --git a/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/WorkbenchVisualsProvider.java b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/WorkbenchVisualsProvider.java new file mode 100644 index 0000000..3962ba5 --- /dev/null +++ b/1.21.1/Common/src/main/java/fuzs/visualworkbench/world/level/block/entity/WorkbenchVisualsProvider.java @@ -0,0 +1,22 @@ +package fuzs.visualworkbench.world.level.block.entity; + +import net.minecraft.world.item.ItemStack; + +/** + * An extension for a {@link net.minecraft.world.level.block.entity.BlockEntity} providing access to data required for rendering. + */ +public interface WorkbenchVisualsProvider { + + /** + * Get the crafting result for the currently stored ingredients. + *

Can return {@link ItemStack#EMPTY} to not render anything. + * + * @return the crafting result + */ + ItemStack getCraftingResult(); + + /** + * @return storage for animation data + */ + CraftingTableAnimationController getAnimationController(); +} diff --git a/1.21.1/Common/src/main/resources/architectury.common.json b/1.21.1/Common/src/main/resources/architectury.common.json new file mode 100644 index 0000000..822cfd0 --- /dev/null +++ b/1.21.1/Common/src/main/resources/architectury.common.json @@ -0,0 +1,3 @@ +{ + "accessWidener": "visualworkbench.accesswidener" +} \ No newline at end of file diff --git a/1.21.1/Common/src/main/resources/common.mixins.json b/1.21.1/Common/src/main/resources/common.mixins.json new file mode 100644 index 0000000..bf44b95 --- /dev/null +++ b/1.21.1/Common/src/main/resources/common.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "compatibilityLevel": "JAVA_17", + "package": "${modGroup}.mixin", + "mixins": [ + "WorldGenRegionMixin" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/1.21.1/Common/src/main/resources/mod_banner.png b/1.21.1/Common/src/main/resources/mod_banner.png new file mode 100644 index 0000000..7b83155 Binary files /dev/null and b/1.21.1/Common/src/main/resources/mod_banner.png differ diff --git a/1.21.1/Common/src/main/resources/mod_logo.png b/1.21.1/Common/src/main/resources/mod_logo.png new file mode 100644 index 0000000..6715625 Binary files /dev/null and b/1.21.1/Common/src/main/resources/mod_logo.png differ diff --git a/1.21.1/Common/src/main/resources/pack.mcmeta b/1.21.1/Common/src/main/resources/pack.mcmeta new file mode 100755 index 0000000..546f4f1 --- /dev/null +++ b/1.21.1/Common/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "${modDescription}", + "pack_format": ${resourcePackFormat} + } +} diff --git a/1.21.1/Common/src/main/resources/visualworkbench.accesswidener b/1.21.1/Common/src/main/resources/visualworkbench.accesswidener new file mode 100644 index 0000000..6608cde --- /dev/null +++ b/1.21.1/Common/src/main/resources/visualworkbench.accesswidener @@ -0,0 +1,9 @@ +accessWidener v2 named +accessible field net/minecraft/world/inventory/CraftingMenu craftSlots Lnet/minecraft/world/inventory/CraftingContainer; +accessible field net/minecraft/world/inventory/CraftingMenu resultSlots Lnet/minecraft/world/inventory/ResultContainer; +accessible field net/minecraft/world/inventory/CraftingMenu access Lnet/minecraft/world/inventory/ContainerLevelAccess; +mutable field net/minecraft/world/inventory/CraftingMenu access Lnet/minecraft/world/inventory/ContainerLevelAccess; +accessible field net/minecraft/world/inventory/TransientCraftingContainer items Lnet/minecraft/core/NonNullList; +mutable field net/minecraft/world/inventory/TransientCraftingContainer items Lnet/minecraft/core/NonNullList; +accessible field net/minecraft/world/inventory/ResultContainer itemStacks Lnet/minecraft/core/NonNullList; +mutable field net/minecraft/world/inventory/ResultContainer itemStacks Lnet/minecraft/core/NonNullList; diff --git a/1.21.1/Fabric/build.gradle b/1.21.1/Fabric/build.gradle new file mode 100644 index 0000000..3bbd65c --- /dev/null +++ b/1.21.1/Fabric/build.gradle @@ -0,0 +1,13 @@ +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/${libs.versions.minecraft.get()}/fabric.gradle" + +dependencies { + // Fabric Api + modApi libs.fabricapi.fabric + + // Puzzles Lib + modApi libs.puzzleslib.fabric + + // Just Enough Items + compileOnly libs.jeiapi.common + modLocalRuntime libs.jei.fabric +} diff --git a/1.21.1/Fabric/src/main/java/fuzs/visualworkbench/fabric/VisualWorkbenchFabric.java b/1.21.1/Fabric/src/main/java/fuzs/visualworkbench/fabric/VisualWorkbenchFabric.java new file mode 100644 index 0000000..3d458b9 --- /dev/null +++ b/1.21.1/Fabric/src/main/java/fuzs/visualworkbench/fabric/VisualWorkbenchFabric.java @@ -0,0 +1,13 @@ +package fuzs.visualworkbench.fabric; + +import fuzs.puzzleslib.api.core.v1.ModConstructor; +import fuzs.visualworkbench.VisualWorkbench; +import net.fabricmc.api.ModInitializer; + +public class VisualWorkbenchFabric implements ModInitializer { + + @Override + public void onInitialize() { + ModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbench::new); + } +} diff --git a/1.21.1/Fabric/src/main/java/fuzs/visualworkbench/fabric/client/VisualWorkbenchFabricClient.java b/1.21.1/Fabric/src/main/java/fuzs/visualworkbench/fabric/client/VisualWorkbenchFabricClient.java new file mode 100644 index 0000000..11075e8 --- /dev/null +++ b/1.21.1/Fabric/src/main/java/fuzs/visualworkbench/fabric/client/VisualWorkbenchFabricClient.java @@ -0,0 +1,14 @@ +package fuzs.visualworkbench.fabric.client; + +import fuzs.puzzleslib.api.client.core.v1.ClientModConstructor; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.client.VisualWorkbenchClient; +import net.fabricmc.api.ClientModInitializer; + +public class VisualWorkbenchFabricClient implements ClientModInitializer { + + @Override + public void onInitializeClient() { + ClientModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbenchClient::new); + } +} diff --git a/1.21.1/Fabric/src/main/resources/fabric.mixins.json b/1.21.1/Fabric/src/main/resources/fabric.mixins.json new file mode 100644 index 0000000..6bf7940 --- /dev/null +++ b/1.21.1/Fabric/src/main/resources/fabric.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "compatibilityLevel": "JAVA_17", + "package": "${modGroup}.fabric.mixin", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "${modId}.fabric.refmap.json" +} diff --git a/1.21.1/Fabric/src/main/resources/fabric.mod.json b/1.21.1/Fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..243503b --- /dev/null +++ b/1.21.1/Fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,48 @@ +{ + "schemaVersion": 1, + "id": "${modId}", + "version": "${modVersion}", + + "name": "${modName}", + "description": "${modDescription}", + + "authors": [ + "${modAuthor}" + ], + + "contact": { + "homepage": "${modPageUrl}", + "issues": "${modIssueUrl}", + "sources": "${modPageUrl}" + }, + + "license": "${modLicense}", + "icon": "mod_logo.png", + + "environment": "${modFabricEnvironment}", + + "entrypoints": { + "main": [ + "${mainEntryPoint}" + ], + "client": [ + "${clientEntryPoint}" + ], + "jei_mod_plugin": [ + "${modGroup}.integration.jei.VisualWorkbenchJEIPlugin" + ] + }, + + "mixins": [ + "${modId}.common.mixins.json", + "${modId}.fabric.mixins.json" + ], + + "depends": { + "fabricloader": ">=${minFabricVersion}", + "fabric-api": ">=${minFabricApiVersion}", + "puzzleslib": ">=${minPuzzlesVersion}", + "minecraft": "${minecraftVersion}", + "java": ">=17" + } +} diff --git a/1.21.1/NeoForge/build.gradle b/1.21.1/NeoForge/build.gradle new file mode 100644 index 0000000..15a3f5c --- /dev/null +++ b/1.21.1/NeoForge/build.gradle @@ -0,0 +1,10 @@ +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/${libs.versions.minecraft.get()}/neoforge.gradle" + +dependencies { + // Puzzles Lib + modApi libs.puzzleslib.neoforge + + // Just Enough Items + compileOnly libs.jeiapi.common + modLocalRuntime libs.jei.neoforge +} diff --git a/1.21.1/NeoForge/gradle.properties b/1.21.1/NeoForge/gradle.properties new file mode 100644 index 0000000..2914393 --- /dev/null +++ b/1.21.1/NeoForge/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge \ No newline at end of file diff --git a/1.21.1/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/VisualWorkbenchNeoForge.java b/1.21.1/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/VisualWorkbenchNeoForge.java new file mode 100644 index 0000000..9d33e3f --- /dev/null +++ b/1.21.1/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/VisualWorkbenchNeoForge.java @@ -0,0 +1,16 @@ +package fuzs.visualworkbench.neoforge; + +import fuzs.puzzleslib.api.core.v1.ModConstructor; +import fuzs.puzzleslib.neoforge.api.data.v2.core.DataProviderHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.data.ModBlockTagsProvider; +import net.neoforged.fml.common.Mod; + +@Mod(VisualWorkbench.MOD_ID) +public class VisualWorkbenchNeoForge { + + public VisualWorkbenchNeoForge() { + ModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbench::new); + DataProviderHelper.registerDataProviders(VisualWorkbench.MOD_ID, ModBlockTagsProvider::new); + } +} diff --git a/1.21.1/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/client/VisualWorkbenchNeoForgeClient.java b/1.21.1/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/client/VisualWorkbenchNeoForgeClient.java new file mode 100644 index 0000000..7f1c0db --- /dev/null +++ b/1.21.1/NeoForge/src/main/java/fuzs/visualworkbench/neoforge/client/VisualWorkbenchNeoForgeClient.java @@ -0,0 +1,18 @@ +package fuzs.visualworkbench.neoforge.client; + +import fuzs.puzzleslib.api.client.core.v1.ClientModConstructor; +import fuzs.puzzleslib.neoforge.api.data.v2.core.DataProviderHelper; +import fuzs.visualworkbench.VisualWorkbench; +import fuzs.visualworkbench.client.VisualWorkbenchClient; +import fuzs.visualworkbench.data.client.ModLanguageProvider; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.common.Mod; + +@Mod(value = VisualWorkbench.MOD_ID, dist = Dist.CLIENT) +public class VisualWorkbenchNeoForgeClient { + + public VisualWorkbenchNeoForgeClient() { + ClientModConstructor.construct(VisualWorkbench.MOD_ID, VisualWorkbenchClient::new); + DataProviderHelper.registerDataProviders(VisualWorkbench.MOD_ID, ModLanguageProvider::new); + } +} diff --git a/1.21.1/NeoForge/src/main/resources/META-INF/neoforge.mods.toml b/1.21.1/NeoForge/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 0000000..ef10121 --- /dev/null +++ b/1.21.1/NeoForge/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,49 @@ +modLoader = "javafml" +loaderVersion = "*" +license = "${modLicense}" +issueTrackerURL = "${modIssueUrl}" + +[[mods]] +modId = "${modId}" +displayName = "${modName}" +description = "${modDescription}" +version = "${modVersion}" +authors = "${modAuthor}" +logoFile = "mod_banner.png" +logoBlur = false +displayURL = "${modPageUrl}" +updateJSONURL = "${modUpdateUrl}" +displayTest = "${modForgeDisplayTest}" + +[[mixins]] +config="${modId}.common.mixins.json" + +[[mixins]] +config="${modId}.neoforge.mixins.json" + +[[dependencies.${ modId }]] +modId = "neoforge" +mandatory = true +type = "required" +versionRange = "[${minNeoForgeVersion},)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${ modId }]] +modId = "minecraft" +mandatory = true +type = "required" +versionRange = "[${minecraftVersion}]" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${ modId }]] +modId = "puzzleslib" +mandatory = true +type = "required" +versionRange = "[${minPuzzlesVersion},)" +ordering = "NONE" +side = "BOTH" + +[modproperties.${ modId }] +catalogueImageIcon = "mod_logo.png" diff --git a/1.21.1/NeoForge/src/main/resources/neoforge.mixins.json b/1.21.1/NeoForge/src/main/resources/neoforge.mixins.json new file mode 100644 index 0000000..1fb3919 --- /dev/null +++ b/1.21.1/NeoForge/src/main/resources/neoforge.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "minVersion": "0.8", + "compatibilityLevel": "JAVA_17", + "package": "${modGroup}.neoforge.mixin", + "mixins": [ + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/1.21.1/build.gradle b/1.21.1/build.gradle new file mode 100644 index 0000000..dea2bca --- /dev/null +++ b/1.21.1/build.gradle @@ -0,0 +1,9 @@ +plugins { + alias libs.plugins.architecturyloom apply false + alias libs.plugins.architecturyplugin apply false + alias libs.plugins.shadow apply false + alias libs.plugins.cursegradle apply false + alias libs.plugins.minotaur apply false +} + +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/${libs.versions.minecraft.get()}/main.gradle" diff --git a/1.21.1/gradle.properties b/1.21.1/gradle.properties new file mode 100755 index 0000000..1d8f9be --- /dev/null +++ b/1.21.1/gradle.properties @@ -0,0 +1,45 @@ +org.gradle.jvmargs=-Xmx4G +org.gradle.daemon=false +copyBuildJar=true + +# Mod Attributes +modId=visualworkbench +modName=Visual Workbench +modVersion=21.1.0 +modAuthor=Fuzs +modDescription=Items stay inside crafting tables and are also rendered on top. It's really fancy! +modLicense=MPL-2.0 +modSourceUrl=https://github.com/Fuzss/visualworkbench +modIssueUrl=https://github.com/Fuzss/visualworkbench/issues +modUpdateUrl=https://raw.githubusercontent.com/Fuzss/modresources/main/update/visualworkbench.json +modMavenGroup=fuzs.visualworkbench +# "MATCH_VERSION" for a mod required on both sides, "IGNORE_SERVER_VERSION" for a server only mod, "IGNORE_ALL_VERSION" for a client only mod +modForgeDisplayTest=MATCH_VERSION +# "*" for a mod loaded on both sides, "server" for a server only mod, "client" for a client only mod +modFabricEnvironment=* + +# Version Catalog +dependenciesVersionCatalog=1.21.1-v4 +#dependenciesPuzzlesLibVersion=21.0.8 +#dependenciesMinPuzzlesLibVersion=21.0.8 + +# Mod Publishing +projectReleaseType=release +projectCurseForgeId=500273 +projectModrinthId=kfqD1JRw + +# Required Dependencies +dependenciesRequiredFabricCurseForge=fabric-api, forge-config-api-port-fabric, puzzles-lib +dependenciesRequiredNeoForgeCurseForge=puzzles-lib +dependenciesRequiredForgeCurseForge=forge-config-api-port-fabric, puzzles-lib +dependenciesRequiredFabricModrinth=fabric-api, forge-config-api-port, puzzles-lib +dependenciesRequiredNeoForgeModrinth=puzzles-lib +dependenciesRequiredForgeModrinth=forge-config-api-port, puzzles-lib + +# Optional Dependencies +dependenciesOptionalFabricCurseForge=config-menus-forge +dependenciesOptionalNeoForgeCurseForge=config-menus-forge +dependenciesOptionalForgeCurseForge=config-menus-forge +dependenciesOptionalFabricModrinth=forge-config-screens +dependenciesOptionalNeoForgeModrinth=forge-config-screens +dependenciesOptionalForgeModrinth=forge-config-screens diff --git a/1.21.1/gradle/wrapper/gradle-wrapper.jar b/1.21.1/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..943f0cb Binary files /dev/null and b/1.21.1/gradle/wrapper/gradle-wrapper.jar differ diff --git a/1.21.1/gradle/wrapper/gradle-wrapper.properties b/1.21.1/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..2617362 --- /dev/null +++ b/1.21.1/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/1.21.1/gradlew b/1.21.1/gradlew new file mode 100755 index 0000000..65dcd68 --- /dev/null +++ b/1.21.1/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# 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 +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/1.21.1/gradlew.bat b/1.21.1/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/1.21.1/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% 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. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +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. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/1.21.1/settings.gradle b/1.21.1/settings.gradle new file mode 100644 index 0000000..5cfe5eb --- /dev/null +++ b/1.21.1/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven { url "https://maven.architectury.dev/" } + maven { url "https://maven.fabricmc.net/" } + maven { url "https://maven.neoforged.net/releases/" } + maven { url "https://maven.minecraftforge.net/" } + } +} + +include "Common" +include "Fabric" +include "NeoForge" +//include "Forge" + +apply from: "https://raw.githubusercontent.com/Fuzss/modresources/main/gradle/v2/settings.gradle"