diff --git a/build.gradle b/build.gradle index 9ea24a0b..6ee8fa49 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.2-SNAPSHOT' + id 'fabric-loom' version '1.7-SNAPSHOT' id 'maven-publish' } @@ -11,10 +11,8 @@ version = project.mod_version group = project.maven_group repositories { - maven { url = "https://maven.terraformersmc.com/" } - maven { url = "https://ueaj.dev/maven/" } - maven { url = "https://api.modrinth.com/maven/" } - maven { url = "https://maven.gegy.dev/" } + maven { url = 'https://maven.terraformersmc.com/' } + maven { url = 'https://api.modrinth.com/maven/' } } dependencies { @@ -26,22 +24,11 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - // ARRP. This is for generating a runtime resource pack (conditionally, as well) - modImplementation "net.devtech:arrp:${project.arrp_version}" - include "net.devtech:arrp:${project.arrp_version}" - // Mod Menu because config screen access from another place modApi "com.terraformersmc:modmenu:${project.modmenu_version}" - // Dashloader (compatibility) - modCompileOnly "maven.modrinth:dashloader:${project.dashloader_version}" - - // a bit less load time - modLocalRuntime "maven.modrinth:lazydfu:0.1.3" - - // UI library - modImplementation "dev.lambdaurora:spruceui:${project.spruceui_version}" - include "dev.lambdaurora:spruceui:${project.spruceui_version}" + // Sodium for compatibility + modCompileOnlyApi "maven.modrinth:sodium:${project.sodium_version}" } processResources { diff --git a/gradle.properties b/gradle.properties index bb64544c..e773b66b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,14 @@ org.gradle.jvmargs=-Xmx2G minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.1 -loader_version=0.14.21 +yarn_mappings=1.20.1+build.10 +loader_version=0.15.11 -fabric_version=0.84.0+1.20.1 +fabric_version=0.92.2+1.20.1 -mod_version = 0.9+1.20 +mod_version = 0.10.1+1.20 maven_group = foundationgames archives_base_name = enhancedblockentities -arrp_version=0.6.7 -modmenu_version=7.1.0 -spruceui_version=5.0.0+1.20 -dashloader_version=5.0.0-beta.1+1.20.0 +modmenu_version=7.2.2 +sodium_version=mc1.20.1-0.5.10 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a..e6441136 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 59bc51a2..a4413138 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c7873..b740cf13 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. 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=SC2039,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=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then 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. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ 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. diff --git a/gradlew.bat b/gradlew.bat index 107acd32..25da30db 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/src/main/java/foundationgames/enhancedblockentities/EBESetup.java b/src/main/java/foundationgames/enhancedblockentities/EBESetup.java index 6145b0ff..a3a16809 100644 --- a/src/main/java/foundationgames/enhancedblockentities/EBESetup.java +++ b/src/main/java/foundationgames/enhancedblockentities/EBESetup.java @@ -1,7 +1,7 @@ package foundationgames.enhancedblockentities; import foundationgames.enhancedblockentities.client.model.DynamicModelEffects; -import foundationgames.enhancedblockentities.client.model.DynamicModelProvider; +import foundationgames.enhancedblockentities.client.model.DynamicModelProvidingPlugin; import foundationgames.enhancedblockentities.client.model.DynamicUnbakedModel; import foundationgames.enhancedblockentities.client.model.ModelIdentifiers; import foundationgames.enhancedblockentities.client.model.ModelSelector; @@ -16,10 +16,9 @@ import foundationgames.enhancedblockentities.util.DateUtil; import foundationgames.enhancedblockentities.util.EBEUtil; import foundationgames.enhancedblockentities.util.ResourceUtil; -import foundationgames.enhancedblockentities.util.duck.BakedModelManagerAccess; -import net.devtech.arrp.json.models.JModel; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; -import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; +import net.fabricmc.fabric.api.client.model.loading.v1.FabricBakedModelManager; +import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.block.ShulkerBoxBlock; @@ -30,8 +29,6 @@ import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.model.BakedModel; import net.minecraft.registry.Registries; -import net.minecraft.registry.RegistryKey; -import net.minecraft.resource.ResourceType; import net.minecraft.state.property.Properties; import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; @@ -49,19 +46,17 @@ public static void setupRRPChests() { p = ResourceUtil.getBasePack(); - ResourceUtil.addSingleChestModels("entity/chest/normal", "chest", p); - ResourceUtil.addDoubleChestModels("entity/chest/normal_left", "entity/chest/normal_right","chest", p); - ResourceUtil.addSingleChestModels("entity/chest/trapped", "trapped_chest", p); - ResourceUtil.addDoubleChestModels("entity/chest/trapped_left", "entity/chest/trapped_right","trapped_chest", p); - ResourceUtil.addSingleChestModels("entity/chest/christmas", "christmas_chest", p); - ResourceUtil.addDoubleChestModels("entity/chest/christmas_left", "entity/chest/christmas_right","christmas_chest", p); - ResourceUtil.addSingleChestModels("entity/chest/ender", "ender_chest", p); + ResourceUtil.addSingleChestModels("normal", "chest", p); + ResourceUtil.addDoubleChestModels("normal_left", "normal_right","chest", p); + ResourceUtil.addSingleChestModels("trapped", "trapped_chest", p); + ResourceUtil.addDoubleChestModels("trapped_left", "trapped_right","trapped_chest", p); + ResourceUtil.addSingleChestModels("christmas", "christmas_chest", p); + ResourceUtil.addDoubleChestModels("christmas_left", "christmas_right","christmas_chest", p); + ResourceUtil.addSingleChestModels("ender", "ender_chest", p); - p.addResource(ResourceType.CLIENT_RESOURCES, new Identifier("models/item/chest.json"), - ResourceUtil.createChestItemModelResource("chest_center").getBytes()); - p.addResource(ResourceType.CLIENT_RESOURCES, new Identifier("models/item/trapped_chest.json"), - ResourceUtil.createChestItemModelResource("trapped_chest_center").getBytes()); - p.addModel(JModel.model("block/ender_chest_center"), new Identifier("item/ender_chest")); + ResourceUtil.addChestItemModel(new Identifier("models/item/chest.json"), "chest_center", p); + ResourceUtil.addChestItemModel(new Identifier("models/item/trapped_chest.json"), "trapped_chest_center", p); + ResourceUtil.addParentModel("block/ender_chest_center", new Identifier("item/ender_chest"), p); p.addDirBlockSprites("entity/chest", "entity/chest/"); } @@ -138,7 +133,7 @@ public static void setupRRPShulkerBoxes() { var id = color != null ? color.getName()+"_shulker_box" : "shulker_box"; ResourceUtil.addShulkerBoxBlockStates(color, pCompat); ResourceUtil.addShulkerBoxModels(color, p); - p.addModel(JModel.model("block/"+id), new Identifier("item/"+id)); + ResourceUtil.addParentModel("block/"+id, new Identifier("item/"+id), p); } p.addDirBlockSprites("entity/shulker", "entity/shulker/"); @@ -149,7 +144,7 @@ public static void setupRRPDecoratedPots() { EBEPack pCompat = ResourceUtil.getPackForCompat(); ResourceUtil.addDecoratedPotBlockState(pCompat); - for (RegistryKey patternKey : Registries.DECORATED_POT_PATTERN.getKeys()) { + for (var patternKey : Registries.DECORATED_POT_PATTERN.getKeys()) { ResourceUtil.addDecoratedPotPatternModels(patternKey, p); } @@ -157,7 +152,7 @@ public static void setupRRPDecoratedPots() { } public static void setupResourceProviders() { - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "chest_center"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -170,7 +165,7 @@ public static void setupResourceProviders() { DynamicModelEffects.CHEST ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "chest_left"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -184,7 +179,7 @@ public static void setupResourceProviders() { ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "chest_right"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -197,7 +192,7 @@ public static void setupResourceProviders() { DynamicModelEffects.CHEST ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "trapped_chest_center"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -210,7 +205,7 @@ public static void setupResourceProviders() { DynamicModelEffects.CHEST ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "trapped_chest_left"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -223,7 +218,7 @@ public static void setupResourceProviders() { DynamicModelEffects.CHEST ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "trapped_chest_right"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -236,7 +231,7 @@ public static void setupResourceProviders() { DynamicModelEffects.CHEST ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "ender_chest_center"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -248,7 +243,7 @@ public static void setupResourceProviders() { ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "bell_between_walls"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -259,7 +254,7 @@ public static void setupResourceProviders() { DynamicModelEffects.BELL ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "bell_ceiling"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -270,7 +265,7 @@ public static void setupResourceProviders() { DynamicModelEffects.BELL ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "bell_floor"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -281,7 +276,7 @@ public static void setupResourceProviders() { DynamicModelEffects.BELL ) )); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "bell_wall"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -293,7 +288,7 @@ public static void setupResourceProviders() { ) )); for (DyeColor color : EBEUtil.DEFAULTED_DYE_COLORS) { - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", color != null ? color.getName()+"_shulker_box" : "shulker_box"), () -> new DynamicUnbakedModel( new Identifier[] { @@ -307,7 +302,7 @@ public static void setupResourceProviders() { } DecoratedPotModelSelector decoratedPotSelector = new DecoratedPotModelSelector(); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new DynamicModelProvider( + ModelLoadingPlugin.register(new DynamicModelProvidingPlugin( new Identifier("builtin", "decorated_pot"), () -> new DynamicUnbakedModel( decoratedPotSelector.createModelIDs(), @@ -329,7 +324,7 @@ public static void setupChests() { }; EnhancedBlockEntityRegistry.register(Blocks.CHEST, BlockEntityType.CHEST, BlockEntityRenderCondition.CHEST, new ChestBlockEntityRendererOverride(() -> { - BakedModelManagerAccess manager = (BakedModelManagerAccess) MinecraftClient.getInstance().getBakedModelManager(); + FabricBakedModelManager manager = MinecraftClient.getInstance().getBakedModelManager(); return new BakedModel[] { manager.getModel(ModelIdentifiers.CHEST_CENTER_LID), manager.getModel(ModelIdentifiers.CHEST_LEFT_LID), @@ -342,7 +337,7 @@ public static void setupChests() { ); EnhancedBlockEntityRegistry.register(Blocks.TRAPPED_CHEST, BlockEntityType.TRAPPED_CHEST, BlockEntityRenderCondition.CHEST, new ChestBlockEntityRendererOverride(() -> { - BakedModelManagerAccess manager = (BakedModelManagerAccess)MinecraftClient.getInstance().getBakedModelManager(); + FabricBakedModelManager manager = MinecraftClient.getInstance().getBakedModelManager(); return new BakedModel[] { manager.getModel(ModelIdentifiers.TRAPPED_CHEST_CENTER_LID), manager.getModel(ModelIdentifiers.TRAPPED_CHEST_LEFT_LID), @@ -355,7 +350,7 @@ public static void setupChests() { ); EnhancedBlockEntityRegistry.register(Blocks.ENDER_CHEST, BlockEntityType.ENDER_CHEST, BlockEntityRenderCondition.CHEST, new ChestBlockEntityRendererOverride(() -> { - BakedModelManagerAccess manager = (BakedModelManagerAccess)MinecraftClient.getInstance().getBakedModelManager(); + FabricBakedModelManager manager = MinecraftClient.getInstance().getBakedModelManager(); return new BakedModel[] { manager.getModel(ModelIdentifiers.ENDER_CHEST_CENTER_LID) }; }, entity -> 0) ); @@ -431,7 +426,7 @@ public static void setupShulkerBoxes() { BlockRenderLayerMap.INSTANCE.putBlock(block, RenderLayer.getCutoutMipped()); EnhancedBlockEntityRegistry.register(block, BlockEntityType.SHULKER_BOX, BlockEntityRenderCondition.SHULKER_BOX, new ShulkerBoxBlockEntityRendererOverride((map) -> { - var models = (BakedModelManagerAccess) MinecraftClient.getInstance().getBakedModelManager(); + var models = MinecraftClient.getInstance().getBakedModelManager(); for (DyeColor dc : EBEUtil.DEFAULTED_DYE_COLORS) { map.put(dc, models.getModel(ModelIdentifiers.SHULKER_BOX_LIDS.get(dc))); } diff --git a/src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntities.java b/src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntities.java index 937f62bf..c3f67eca 100644 --- a/src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntities.java +++ b/src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntities.java @@ -2,12 +2,16 @@ import foundationgames.enhancedblockentities.client.model.ModelIdentifiers; import foundationgames.enhancedblockentities.client.render.SignRenderManager; +import foundationgames.enhancedblockentities.client.resource.template.TemplateLoader; import foundationgames.enhancedblockentities.config.EBEConfig; import foundationgames.enhancedblockentities.util.DateUtil; import foundationgames.enhancedblockentities.util.EBEUtil; import foundationgames.enhancedblockentities.util.ResourceUtil; +import foundationgames.enhancedblockentities.util.WorldUtil; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.item.ModelPredicateProviderRegistry; import org.apache.logging.log4j.LogManager; @@ -19,9 +23,20 @@ public final class EnhancedBlockEntities implements ClientModInitializer { public static final Logger LOG = LogManager.getLogger("Enhanced Block Entities"); public static final EBEConfig CONFIG = new EBEConfig(); + public static final TemplateLoader TEMPLATE_LOADER = new TemplateLoader(); + @Override public void onInitializeClient() { + FabricLoader.getInstance().getModContainer(ID).ifPresent(mod -> { + var roots = mod.getRootPaths(); + + if (roots.size() > 0) { + TEMPLATE_LOADER.setRoot(roots.get(0).resolve("templates")); + } + }); + WorldRenderEvents.END.register(SignRenderManager::endFrame); + ClientTickEvents.END_WORLD_TICK.register(WorldUtil.EVENT_LISTENER); ModelIdentifiers.init(); EBESetup.setupResourceProviders(); @@ -46,32 +61,32 @@ public static void load() { ResourceUtil.resetBasePack(); ResourceUtil.resetTopLevelPack(); - if(CONFIG.renderEnhancedChests) { + if (CONFIG.renderEnhancedChests) { EBESetup.setupChests(); EBESetup.setupRRPChests(); } - if(CONFIG.renderEnhancedSigns) { + if (CONFIG.renderEnhancedSigns) { EBESetup.setupSigns(); EBESetup.setupRRPSigns(); } - if(CONFIG.renderEnhancedBells) { + if (CONFIG.renderEnhancedBells) { EBESetup.setupBells(); EBESetup.setupRRPBells(); } - if(CONFIG.renderEnhancedBeds) { + if (CONFIG.renderEnhancedBeds) { EBESetup.setupBeds(); EBESetup.setupRRPBeds(); } - if(CONFIG.renderEnhancedShulkerBoxes) { + if (CONFIG.renderEnhancedShulkerBoxes) { EBESetup.setupShulkerBoxes(); EBESetup.setupRRPShulkerBoxes(); } - if(CONFIG.renderEnhancedDecoratedPots) { + if (CONFIG.renderEnhancedDecoratedPots) { EBESetup.setupDecoratedPots(); EBESetup.setupRRPDecoratedPots(); } diff --git a/src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvider.java b/src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvider.java deleted file mode 100644 index 373578f2..00000000 --- a/src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -package foundationgames.enhancedblockentities.client.model; - -import net.fabricmc.fabric.api.client.model.ModelProviderContext; -import net.fabricmc.fabric.api.client.model.ModelResourceProvider; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; - -public class DynamicModelProvider implements ModelResourceProvider { - private final Supplier model; - private final Identifier id; - - public DynamicModelProvider(Identifier id, Supplier model) { - this.model = model; - this.id = id; - } - - @Override - public @Nullable UnbakedModel loadModelResource(Identifier identifier, ModelProviderContext modelProviderContext) { - if(identifier.equals(this.id)) return model.get(); - return null; - } -} diff --git a/src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvidingPlugin.java b/src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvidingPlugin.java new file mode 100644 index 00000000..51c29e01 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvidingPlugin.java @@ -0,0 +1,30 @@ +package foundationgames.enhancedblockentities.client.model; + +import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; +import net.fabricmc.fabric.api.client.model.loading.v1.ModelResolver; +import net.minecraft.client.render.model.UnbakedModel; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public class DynamicModelProvidingPlugin implements ModelLoadingPlugin, ModelResolver { + private final Supplier model; + private final Identifier id; + + public DynamicModelProvidingPlugin(Identifier id, Supplier model) { + this.model = model; + this.id = id; + } + + @Override + public void onInitializeModelLoader(ModelLoadingPlugin.Context ctx) { + ctx.resolveModel().register(this); + } + + @Override + public @Nullable UnbakedModel resolveModel(ModelResolver.Context ctx) { + if (ctx.id().equals(this.id)) return this.model.get(); + return null; + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/client/model/ModelIdentifiers.java b/src/main/java/foundationgames/enhancedblockentities/client/model/ModelIdentifiers.java index 754be9ba..7cdac235 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/model/ModelIdentifiers.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/model/ModelIdentifiers.java @@ -3,7 +3,7 @@ import foundationgames.enhancedblockentities.EnhancedBlockEntities; import foundationgames.enhancedblockentities.config.EBEConfig; import foundationgames.enhancedblockentities.util.EBEUtil; -import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; +import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryKey; import net.minecraft.util.DyeColor; @@ -11,10 +11,14 @@ import net.minecraft.util.math.Direction; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.function.Predicate; -public final class ModelIdentifiers { +public final class ModelIdentifiers implements ModelLoadingPlugin { + private static final Map, Set> modelLoaders = new HashMap<>(); + public static final Predicate CHEST_PREDICATE = c -> c.renderEnhancedChests; public static final Predicate BELL_PREDICATE = c -> c.renderEnhancedBells; public static final Predicate SHULKER_BOX_PREDICATE = c -> c.renderEnhancedShulkerBoxes; @@ -84,6 +88,7 @@ public final class ModelIdentifiers { } public static void init() { + ModelLoadingPlugin.register(new ModelIdentifiers()); } public static void refreshPotteryPatterns() { @@ -92,7 +97,7 @@ public static void refreshPotteryPatterns() { // The order decorated pots store patterns per face Direction[] orderedHorizontalDirs = new Direction[] {Direction.NORTH, Direction.WEST, Direction.EAST, Direction.SOUTH}; - for (RegistryKey patternKey : Registries.DECORATED_POT_PATTERN.getKeys()) { + for (var patternKey : Registries.DECORATED_POT_PATTERN.getKeys()) { var pattern = patternKey.getValue().getPath(); var ids = new Identifier[orderedHorizontalDirs.length];; @@ -107,9 +112,18 @@ public static void refreshPotteryPatterns() { private static Identifier of(String id, Predicate condition) { Identifier idf = new Identifier(id); - ModelLoadingRegistry.INSTANCE.registerModelProvider((resourceManager, consumer) -> { - if(condition.test(EnhancedBlockEntities.CONFIG)) consumer.accept(idf); - }); + modelLoaders.computeIfAbsent(condition, k -> new HashSet<>()).add(idf); return idf; } + + @Override + public void onInitializeModelLoader(Context ctx) { + var config = EnhancedBlockEntities.CONFIG; + + for (var entry : modelLoaders.entrySet()) { + if (entry.getKey().test(config)) { + ctx.addModels(entry.getValue()); + } + } + } } diff --git a/src/main/java/foundationgames/enhancedblockentities/client/model/ModelSelector.java b/src/main/java/foundationgames/enhancedblockentities/client/model/ModelSelector.java index 84f8b253..328e6107 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/model/ModelSelector.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/model/ModelSelector.java @@ -1,7 +1,7 @@ package foundationgames.enhancedblockentities.client.model; import foundationgames.enhancedblockentities.util.DateUtil; -import foundationgames.enhancedblockentities.util.duck.ModelStateHolder; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; @@ -19,7 +19,7 @@ public abstract class ModelSelector { public static final ModelSelector STATE_HOLDER_SELECTOR = new ModelSelector() { @Override public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier rand, @Nullable RenderContext ctx, int[] indices) { - if(view.getBlockEntity(pos) instanceof ModelStateHolder stateHolder) { + if (view.getBlockEntity(pos) instanceof AppearanceStateHolder stateHolder) { indices[0] = stateHolder.getModelState(); return; } @@ -37,7 +37,7 @@ public int getParticleModelIndex() { @Override public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier rand, @Nullable RenderContext ctx, int[] indices) { - if(view.getBlockEntity(pos) instanceof ModelStateHolder stateHolder) { + if (view.getBlockEntity(pos) instanceof AppearanceStateHolder stateHolder) { indices[0] = stateHolder.getModelState() + this.getParticleModelIndex(); return; } diff --git a/src/main/java/foundationgames/enhancedblockentities/client/model/misc/DecoratedPotModelSelector.java b/src/main/java/foundationgames/enhancedblockentities/client/model/misc/DecoratedPotModelSelector.java index c753bb78..e4f85981 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/model/misc/DecoratedPotModelSelector.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/model/misc/DecoratedPotModelSelector.java @@ -2,6 +2,7 @@ import foundationgames.enhancedblockentities.client.model.ModelIdentifiers; import foundationgames.enhancedblockentities.client.model.ModelSelector; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.minecraft.block.BlockState; import net.minecraft.block.DecoratedPotPatterns; @@ -17,10 +18,16 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.function.Supplier; public class DecoratedPotModelSelector extends ModelSelector { + public static final int BUILTIN_MODEL_COUNT = 1; + + public static final int IDX_BASE_POT = 0; + private final List> potteryPatterns; public DecoratedPotModelSelector() { @@ -32,10 +39,10 @@ public DecoratedPotModelSelector() { public Identifier[] createModelIDs() { ModelIdentifiers.refreshPotteryPatterns(); - var ids = new Identifier[1 + potteryPatterns.size() * 4]; - ids[0] = ModelIdentifiers.DECORATED_POT_BASE; + var ids = new Identifier[BUILTIN_MODEL_COUNT + potteryPatterns.size() * 4]; + ids[IDX_BASE_POT] = ModelIdentifiers.DECORATED_POT_BASE; - int idIndex = 1; + int idIndex = BUILTIN_MODEL_COUNT; for (int dirIndex = 0; dirIndex < 4; dirIndex++) { for (var pattern : this.potteryPatterns) { ids[idIndex] = ModelIdentifiers.POTTERY_PATTERNS.get(pattern)[dirIndex]; @@ -51,24 +58,29 @@ public Identifier[] createModelIDs() { public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier rand, @Nullable RenderContext ctx, int[] indices) { final int patternCount = potteryPatterns.size(); - indices[0] = 0; + indices[0] = IDX_BASE_POT; if (view.getBlockEntity(pos) instanceof DecoratedPotBlockEntity pot) { + if (pot instanceof AppearanceStateHolder ms && ms.getModelState() > 0) { + Arrays.fill(indices, IDX_BASE_POT); + return; + } + var sherds = pot.getSherds(); - indices[1] = 1 + getPatternIndex(sherds.back(), patternCount); - indices[2] = 1 + getPatternIndex(sherds.left(), patternCount) + patternCount; - indices[3] = 1 + getPatternIndex(sherds.right(), patternCount) + patternCount * 2; - indices[4] = 1 + getPatternIndex(sherds.front(), patternCount) + patternCount * 3; + indices[1] = BUILTIN_MODEL_COUNT + getPatternIndex(Optional.ofNullable(sherds.back()), patternCount); + indices[2] = BUILTIN_MODEL_COUNT + getPatternIndex(Optional.ofNullable(sherds.left()), patternCount) + patternCount; + indices[3] = BUILTIN_MODEL_COUNT + getPatternIndex(Optional.ofNullable(sherds.right()), patternCount) + patternCount * 2; + indices[4] = BUILTIN_MODEL_COUNT + getPatternIndex(Optional.ofNullable(sherds.front()), patternCount) + patternCount * 3; return; } for (int i = 0; i < 4; i++) { - indices[1 + i] = 1 + patternCount * i; + indices[1 + i] = BUILTIN_MODEL_COUNT + patternCount * i; } } - private int getPatternIndex(Item sherd, int max) { - return MathHelper.clamp(this.potteryPatterns.indexOf(DecoratedPotPatterns.fromSherd(sherd)), 0, max - 1); + private int getPatternIndex(Optional sherd, int max) { + return MathHelper.clamp(this.potteryPatterns.indexOf(sherd.map(DecoratedPotPatterns::fromSherd).orElse(DecoratedPotPatterns.DECORATED_POT_SIDE_KEY)), 0, max - 1); } } diff --git a/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRenderCondition.java b/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRenderCondition.java index 4f8f55b5..82a273f2 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRenderCondition.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRenderCondition.java @@ -3,25 +3,25 @@ import foundationgames.enhancedblockentities.EnhancedBlockEntities; import foundationgames.enhancedblockentities.config.EBEConfig; import foundationgames.enhancedblockentities.mixin.SignBlockEntityRenderAccessor; -import foundationgames.enhancedblockentities.util.duck.ModelStateHolder; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.util.math.Vec3d; @FunctionalInterface public interface BlockEntityRenderCondition { - BlockEntityRenderCondition STATE_GREATER_THAN_1 = entity -> { - if(entity instanceof ModelStateHolder stateHolder) { - return stateHolder.getModelState() > 0; + BlockEntityRenderCondition NON_ZERO_STATE = entity -> { + if (entity instanceof AppearanceStateHolder stateHolder) { + return stateHolder.getRenderState() > 0; } return false; }; - BlockEntityRenderCondition CHEST = STATE_GREATER_THAN_1; + BlockEntityRenderCondition CHEST = NON_ZERO_STATE; - BlockEntityRenderCondition BELL = STATE_GREATER_THAN_1; + BlockEntityRenderCondition BELL = NON_ZERO_STATE; - BlockEntityRenderCondition SHULKER_BOX = STATE_GREATER_THAN_1; + BlockEntityRenderCondition SHULKER_BOX = NON_ZERO_STATE; BlockEntityRenderCondition SIGN = entity -> { EBEConfig config = EnhancedBlockEntities.CONFIG; diff --git a/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRendererOverride.java b/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRendererOverride.java index 2c5d2379..cbb5bfa6 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRendererOverride.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRendererOverride.java @@ -13,7 +13,7 @@ public void render(BlockEntityRenderer renderer, BlockEntity blockE }; public BlockEntityRendererOverride() { - EBEEvents.RELOAD_MODELS.register((loader, manager, profiler) -> this.onModelsReload()); + EBEEvents.RESOURCE_RELOAD.register(this::onModelsReload); } public abstract void render(BlockEntityRenderer renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay); diff --git a/src/main/java/foundationgames/enhancedblockentities/client/render/entity/BellBlockEntityRendererOverride.java b/src/main/java/foundationgames/enhancedblockentities/client/render/entity/BellBlockEntityRendererOverride.java index df65129e..af2bbb02 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/render/entity/BellBlockEntityRendererOverride.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/render/entity/BellBlockEntityRendererOverride.java @@ -3,7 +3,6 @@ import foundationgames.enhancedblockentities.client.model.ModelIdentifiers; import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride; import foundationgames.enhancedblockentities.util.EBEUtil; -import foundationgames.enhancedblockentities.util.duck.BakedModelManagerAccess; import net.minecraft.block.entity.BellBlockEntity; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; @@ -49,8 +48,7 @@ public void render(BlockEntityRenderer renderer, BlockEntity blockE } private BakedModel getBellModel() { - BakedModelManagerAccess manager = (BakedModelManagerAccess)MinecraftClient.getInstance().getBakedModelManager(); - return manager.getModel(ModelIdentifiers.BELL_BODY); + return MinecraftClient.getInstance().getBakedModelManager().getModel(ModelIdentifiers.BELL_BODY); } @Override diff --git a/src/main/java/foundationgames/enhancedblockentities/client/render/entity/ChestBlockEntityRendererOverride.java b/src/main/java/foundationgames/enhancedblockentities/client/render/entity/ChestBlockEntityRendererOverride.java index 055afa4b..4ba7a4fe 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/render/entity/ChestBlockEntityRendererOverride.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/render/entity/ChestBlockEntityRendererOverride.java @@ -34,7 +34,7 @@ public void render(BlockEntityRenderer renderer, BlockEntity blockE if (blockEntity instanceof LidOpenable) { matrices.push(); - LidOpenable chest = getAnimationProgress(blockEntity, tickDelta); + LidOpenable chest = getLidAnimationHolder(blockEntity, tickDelta); matrices.translate(0.5f, 0, 0.5f); Direction dir = blockEntity.getCachedState().get(ChestBlock.FACING); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - dir.asRotation())); @@ -53,7 +53,7 @@ public void render(BlockEntityRenderer renderer, BlockEntity blockE } } - public static LidOpenable getAnimationProgress(BlockEntity blockEntity, float tickDelta) { + public static LidOpenable getLidAnimationHolder(BlockEntity blockEntity, float tickDelta) { LidOpenable chest = (LidOpenable)blockEntity; BlockState state = blockEntity.getCachedState(); diff --git a/src/main/java/foundationgames/enhancedblockentities/client/resource/EBEPack.java b/src/main/java/foundationgames/enhancedblockentities/client/resource/EBEPack.java index b9f723ad..ac2135f9 100644 --- a/src/main/java/foundationgames/enhancedblockentities/client/resource/EBEPack.java +++ b/src/main/java/foundationgames/enhancedblockentities/client/resource/EBEPack.java @@ -1,56 +1,59 @@ package foundationgames.enhancedblockentities.client.resource; -import net.devtech.arrp.api.RuntimeResourcePack; -import net.devtech.arrp.json.animation.JAnimation; -import net.devtech.arrp.json.blockstate.JState; -import net.devtech.arrp.json.lang.JLang; -import net.devtech.arrp.json.loot.JLootTable; -import net.devtech.arrp.json.models.JModel; -import net.devtech.arrp.json.recipe.JRecipe; -import net.devtech.arrp.json.tags.JTag; -import net.devtech.arrp.util.CallableFunction; +import com.google.gson.JsonObject; +import foundationgames.enhancedblockentities.client.resource.template.TemplateLoader; +import foundationgames.enhancedblockentities.client.resource.template.TemplateProvider; +import net.minecraft.SharedConstants; import net.minecraft.client.texture.atlas.AtlasSource; import net.minecraft.client.texture.atlas.DirectoryAtlasSource; import net.minecraft.client.texture.atlas.SingleAtlasSource; import net.minecraft.resource.InputSupplier; +import net.minecraft.resource.ResourcePack; import net.minecraft.resource.ResourceType; import net.minecraft.resource.metadata.ResourceMetadataReader; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; -import java.awt.image.BufferedImage; -import java.io.File; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Optional; +import java.util.Properties; import java.util.Set; -import java.util.concurrent.Future; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.IntUnaryOperator; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -public class EBEPack implements RuntimeResourcePack { + +public class EBEPack implements ResourcePack { public static final Identifier BLOCK_ATLAS = new Identifier("blocks"); - private final RuntimeResourcePack resourcePack; private final Map atlases = new HashMap<>(); + private final Map> resources = new HashMap<>(); + private final Set namespaces = new HashSet<>(); + + private final TemplateLoader templates; + + private final JsonObject packMeta; + private final String name; + + public EBEPack(Identifier id, TemplateLoader templates) { + this.templates = templates; + + this.packMeta = new JsonObject(); + this.packMeta.addProperty("pack_format", SharedConstants.getGameVersion().getResourceVersion(ResourceType.CLIENT_RESOURCES)); + this.packMeta.addProperty("description", "Enhanced Block Entities Resources"); - public EBEPack(Identifier id) { - this.resourcePack = RuntimeResourcePack.create(id); + this.name = id.toString(); } public void addAtlasSprite(Identifier atlas, AtlasSource source) { var resource = this.atlases.computeIfAbsent(atlas, id -> new AtlasResourceBuilder()); resource.put(source); - this.addLazyResource(ResourceType.CLIENT_RESOURCES, - new Identifier(atlas.getNamespace(), "atlases/" + atlas.getPath() + ".json"), - (pack, id) -> resource.toBytes()); + this.addResource(new Identifier(atlas.getNamespace(), "atlases/" + atlas.getPath() + ".json"), resource::toBytes); } public void addSingleBlockSprite(Identifier path) { @@ -61,166 +64,137 @@ public void addDirBlockSprites(String dir, String prefix) { this.addAtlasSprite(BLOCK_ATLAS, new DirectoryAtlasSource(dir, prefix)); } - @Override - public void addRecoloredImage(Identifier identifier, InputStream target, IntUnaryOperator pixel) { - this.resourcePack.addRecoloredImage(identifier, target, pixel); + public void addResource(Identifier id, InputSupplier resource) { + this.namespaces.add(id.getNamespace()); + this.resources.put(id, new LazyBufferedResource(resource)); } - @Override - public byte[] addLang(Identifier identifier, JLang lang) { - return this.resourcePack.addLang(identifier, lang); + public void addResource(Identifier id, byte[] resource) { + this.namespaces.add(id.getNamespace()); + this.resources.put(id, () -> new ByteArrayInputStream(resource)); } - @Override - public void mergeLang(Identifier identifier, JLang lang) { - this.resourcePack.mergeLang(identifier, lang); + public void addPlainTextResource(Identifier id, String plainText) { + this.addResource(id, plainText.getBytes(StandardCharsets.UTF_8)); } - @Override - public byte[] addLootTable(Identifier identifier, JLootTable table) { - return this.resourcePack.addLootTable(identifier, table); + public void addTemplateResource(Identifier id, TemplateProvider.TemplateApplyingFunction template) { + this.addResource(id, () -> template.getAndApplyTemplate(new TemplateProvider(this.templates)).getBytes(StandardCharsets.UTF_8)); } - @Override - public Future addAsyncResource(ResourceType type, Identifier identifier, CallableFunction data) { - return this.resourcePack.addAsyncResource(type, identifier, data); + public void addTemplateResource(Identifier id, String templatePath) { + this.addTemplateResource(id, t -> t.load(templatePath, d -> {})); } + @Nullable @Override - public void addLazyResource(ResourceType type, Identifier path, BiFunction data) { - this.resourcePack.addLazyResource(type, path, data); + public InputSupplier openRoot(String... segments) { + return null; // Provide no root resources } + @Nullable @Override - public byte[] addResource(ResourceType type, Identifier path, byte[] data) { - return this.resourcePack.addResource(type, path, data); - } + public InputSupplier open(ResourceType type, Identifier id) { + if (type != ResourceType.CLIENT_RESOURCES) return null; - @Override - public Future addAsyncRootResource(String path, CallableFunction data) { - return this.resourcePack.addAsyncRootResource(path, data); + return this.resources.get(id); } @Override - public void addLazyRootResource(String path, BiFunction data) { - this.resourcePack.addLazyRootResource(path, data); - } + public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer consumer) { + if (type != ResourceType.CLIENT_RESOURCES) return; - @Override - public byte[] addRootResource(String path, byte[] data) { - return this.resourcePack.addRootResource(path, data); - } + for (var entry : this.resources.entrySet()) { + var id = entry.getKey(); - @Override - public byte[] addAsset(Identifier path, byte[] data) { - return this.resourcePack.addAsset(path, data); + if (id.getNamespace().startsWith(namespace) && id.getPath().startsWith(prefix)) { + consumer.accept(id, entry.getValue()); + } + } } @Override - public byte[] addData(Identifier path, byte[] data) { - return this.resourcePack.addData(path, data); - } + public Set getNamespaces(ResourceType type) { + if (type != ResourceType.CLIENT_RESOURCES) return Set.of(); - @Override - public byte[] addModel(JModel model, Identifier path) { - return this.resourcePack.addModel(model, path); + return this.namespaces; } + @Nullable @Override - public byte[] addBlockState(JState state, Identifier path) { - return this.resourcePack.addBlockState(state, path); - } + public T parseMetadata(ResourceMetadataReader meta) throws IOException { + if ("pack".equals(meta.getKey())) { + return meta.fromJson(this.packMeta); + } - @Override - public byte[] addTexture(Identifier id, BufferedImage image) { - return this.resourcePack.addTexture(id, image); + return null; } @Override - public byte[] addAnimation(Identifier id, JAnimation animation) { - return this.resourcePack.addAnimation(id, animation); + public String getName() { + return this.name; } @Override - public byte[] addTag(Identifier id, JTag tag) { - return this.resourcePack.addTag(id, tag); + public void close() { } - @Override - public byte[] addRecipe(Identifier id, JRecipe recipe) { - return this.resourcePack.addRecipe(id, recipe); - } + public void dump(Path dir) throws IOException { + dir = dir.resolve("assets"); - @Override - public Future async(Consumer action) { - return this.resourcePack.async(action); - } + for (var entry : this.resources.entrySet()) { + var id = entry.getKey(); + var file = dir.resolve(id.getNamespace()).resolve(id.getPath()); - @Override - public void dumpDirect(Path path) { - this.resourcePack.dumpDirect(path); - } + Files.createDirectories(file.getParent()); - @Override - public void load(Path path) throws IOException { - this.resourcePack.load(path); - } + try (var out = Files.newOutputStream(file)) { + var in = entry.getValue().get(); - @Override - public void dump(File file) { - this.resourcePack.dump(file); + int i; + while ((i = in.read()) >= 0) { + out.write(i); + } + } + } } - @Override - public void dump(ZipOutputStream stream) throws IOException { - this.resourcePack.dump(stream); - } + public static class PropertyBuilder { + private Properties properties = new Properties(); - @Override - public void load(ZipInputStream stream) throws IOException { - this.resourcePack.load(stream); - } + private PropertyBuilder() {} - @Override - public Identifier getId() { - return this.resourcePack.getId(); - } + public PropertyBuilder def(String k, String v) { + if (this.properties != null) { + this.properties.setProperty(k, v); + } - @Nullable - @Override - public InputSupplier openRoot(String... segments) { - return this.resourcePack.openRoot(segments); - } + return this; + } - @Nullable - @Override - public InputSupplier open(ResourceType type, Identifier id) { - return this.resourcePack.open(type, id); - } + private Properties build() { + var properties = this.properties; + this.properties = null; - @Override - public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer consumer) { - this.resourcePack.findResources(type, namespace, prefix, consumer); + return properties; + } } - @Override - public Set getNamespaces(ResourceType type) { - return this.resourcePack.getNamespaces(type); - } + public static class LazyBufferedResource implements InputSupplier { + private final InputSupplier backing; + private byte[] buffer = null; - @Nullable - @Override - public T parseMetadata(ResourceMetadataReader metaReader) throws IOException { - return this.resourcePack.parseMetadata(metaReader); - } + public LazyBufferedResource(InputSupplier backing) { + this.backing = backing; + } - @Override - public String getName() { - return this.resourcePack.getName(); - } + @Override + public InputStream get() throws IOException { + if (buffer == null) { + buffer = backing.get(); + } - @Override - public void close() { - this.resourcePack.close(); + return new ByteArrayInputStream(buffer); + } } } diff --git a/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateDefinitions.java b/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateDefinitions.java new file mode 100644 index 00000000..1af64867 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateDefinitions.java @@ -0,0 +1,45 @@ +package foundationgames.enhancedblockentities.client.resource.template; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public interface TemplateDefinitions { + default TemplateDefinitions def(String k, Object v) { + return this.def(k, templates -> String.valueOf(v)); + } + + TemplateDefinitions def(String k, TemplateProvider.TemplateApplyingFunction v); + + class Impl implements TemplateDefinitions, Iterable> { + private final Deque> stack = new ArrayDeque<>(); + + public void push() { + this.stack.addLast(new HashMap<>()); + } + + public void pop() { + this.stack.removeLast(); + } + + public TemplateDefinitions def(String k, String v) { + return this.def(k, templates -> v); + } + + public TemplateDefinitions def(String k, TemplateProvider.TemplateApplyingFunction v) { + this.stack.getLast().put(k, v); + + return this; + } + + @NotNull + @Override + public Iterator> iterator() { + return this.stack.getLast().entrySet().iterator(); + } + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateLoader.java b/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateLoader.java new file mode 100644 index 00000000..b3fc5e23 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateLoader.java @@ -0,0 +1,39 @@ +package foundationgames.enhancedblockentities.client.resource.template; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +public class TemplateLoader { + private Path rootPath; + + private final Map loadedTemplates = new HashMap<>(); + + public TemplateLoader() { + } + + public void setRoot(Path path) { + this.rootPath = path; + } + + public String getOrLoadRaw(String path) throws IOException { + if (this.rootPath == null) { + return ""; + } + + if (this.loadedTemplates.containsKey(path)) { + return this.loadedTemplates.get(path); + } + + var file = rootPath.resolve(path); + try (var in = Files.newInputStream(file)) { + var templateRaw = new String(in.readAllBytes(), StandardCharsets.UTF_8); + this.loadedTemplates.put(path, templateRaw); + + return templateRaw; + } + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateProvider.java b/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateProvider.java new file mode 100644 index 00000000..0545af29 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateProvider.java @@ -0,0 +1,51 @@ +package foundationgames.enhancedblockentities.client.resource.template; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.function.Consumer; +import java.util.regex.Pattern; + +public class TemplateProvider { + private final TemplateLoader loader; + private final TemplateDefinitions.Impl definitions = new TemplateDefinitions.Impl(); + private final Deque loaded = new ArrayDeque<>(); + + public TemplateProvider(TemplateLoader loader) { + this.loader = loader; + } + + public String load(String templatePath, Consumer definitions) throws IOException { + this.definitions.push(); + definitions.accept(this.definitions); + + try { + var substitutions = new HashMap(); + for (var entry : this.definitions) { + substitutions.put(entry.getKey(), entry.getValue().getAndApplyTemplate(this)); + } + + var templateRaw = this.loader.getOrLoadRaw(templatePath); + var matcher = Pattern.compile("!\\[(" + String.join("|", substitutions.keySet()) + ")]") + .matcher(templateRaw); + + var result = new StringBuilder(); + while (matcher.find()) { + matcher.appendReplacement(result, substitutions.get(matcher.group(1))); + } + matcher.appendTail(result); + + this.definitions.pop(); + return result.toString(); + } catch (IOException ex) { + this.definitions.pop(); + throw ex; + } + } + + @FunctionalInterface + public interface TemplateApplyingFunction { + String getAndApplyTemplate(TemplateProvider templates) throws IOException; + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/compat/dashloader/DashDynamicBakedModel.java b/src/main/java/foundationgames/enhancedblockentities/compat/dashloader/DashDynamicBakedModel.java deleted file mode 100644 index 70c6f356..00000000 --- a/src/main/java/foundationgames/enhancedblockentities/compat/dashloader/DashDynamicBakedModel.java +++ /dev/null @@ -1,43 +0,0 @@ -package foundationgames.enhancedblockentities.compat.dashloader; - -import dev.notalpha.dashloader.api.DashObject; -import dev.notalpha.dashloader.api.registry.RegistryReader; -import dev.notalpha.dashloader.api.registry.RegistryWriter; -import foundationgames.enhancedblockentities.client.model.DynamicBakedModel; -import foundationgames.enhancedblockentities.client.model.DynamicModelEffects; -import foundationgames.enhancedblockentities.client.model.ModelSelector; -import net.minecraft.client.render.model.BakedModel; - -public class DashDynamicBakedModel implements DashObject { - public final int[] models; - public final int selectorId; - public final int effectsId; - - public DashDynamicBakedModel(int[] models, int selectorId, int effectsId) { - this.models = models; - this.selectorId = selectorId; - this.effectsId = effectsId; - } - - public DashDynamicBakedModel(DynamicBakedModel model, RegistryWriter writer) { - BakedModel[] models = model.getModels(); - int[] dModels = new int[models.length]; - for (int i = 0; i < models.length; i++) { - dModels[i] = writer.add(models[i]); - } - - this.models = dModels; - this.selectorId = model.getSelector().id; - this.effectsId = model.getEffects().id; - } - - @Override - public DynamicBakedModel export(RegistryReader reader) { - BakedModel[] out = new BakedModel[models.length]; - for (int i = 0; i < models.length; i++) { - out[i] = reader.get(models[i]); - } - - return new DynamicBakedModel(out, ModelSelector.fromId(selectorId), DynamicModelEffects.fromId(effectsId)); - } -} diff --git a/src/main/java/foundationgames/enhancedblockentities/compat/dashloader/EBEDashLoader.java b/src/main/java/foundationgames/enhancedblockentities/compat/dashloader/EBEDashLoader.java deleted file mode 100644 index 9041f696..00000000 --- a/src/main/java/foundationgames/enhancedblockentities/compat/dashloader/EBEDashLoader.java +++ /dev/null @@ -1,11 +0,0 @@ -package foundationgames.enhancedblockentities.compat.dashloader; - -import dev.notalpha.dashloader.api.cache.CacheFactory; -import dev.notalpha.dashloader.api.DashEntrypoint; - -public class EBEDashLoader implements DashEntrypoint { - @Override - public void onDashLoaderInit(CacheFactory factory) { - factory.addDashObject(DashDynamicBakedModel.class); - } -} diff --git a/src/main/java/foundationgames/enhancedblockentities/config/EBEConfig.java b/src/main/java/foundationgames/enhancedblockentities/config/EBEConfig.java index d420aedb..4ac26f73 100644 --- a/src/main/java/foundationgames/enhancedblockentities/config/EBEConfig.java +++ b/src/main/java/foundationgames/enhancedblockentities/config/EBEConfig.java @@ -77,14 +77,14 @@ public void readFrom(Properties properties) { this.renderEnhancedShulkerBoxes = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_SHULKER_BOXES_KEY), true); this.renderEnhancedDecoratedPots = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_DECORATED_POTS_KEY), true); String pCC = properties.getProperty(CHRISTMAS_CHESTS_KEY); - if(pCC != null && (pCC.equals("allowed") || pCC.equals("forced") || pCC.equals("disabled"))) { + if (pCC != null && (pCC.equals("allowed") || pCC.equals("forced") || pCC.equals("disabled"))) { this.christmasChests = pCC; } else { EnhancedBlockEntities.LOG.warn("Configuration option 'christmas_chests' must be one of: 'allowed', 'forced', 'disabled'"); this.christmasChests = "allowed"; } String sST = properties.getProperty(SIGN_TEXT_RENDERING_KEY); - if(sST != null && (sST.equals("smart") || sST.equals("all") || sST.equals("most") || sST.equals("some") || sST.equals("few"))) { + if (sST != null && (sST.equals("smart") || sST.equals("all") || sST.equals("most") || sST.equals("some") || sST.equals("few"))) { this.signTextRendering = sST; } else { EnhancedBlockEntities.LOG.warn("Configuration option 'sign_text_rendering' must be one of: 'smart', 'all', 'most', 'some', 'few'"); @@ -106,7 +106,7 @@ public void save() { Properties properties = new Properties(); writeTo(properties); Path configPath = FabricLoader.getInstance().getConfigDir().resolve("enhanced_bes.properties"); - if(!Files.exists(configPath)) { + if (!Files.exists(configPath)) { try { Files.createFile(configPath); } catch (IOException e) { @@ -126,7 +126,7 @@ public void save() { public void load() { Properties properties = new Properties(); Path configPath = FabricLoader.getInstance().getConfigDir().resolve("enhanced_bes.properties"); - if(!Files.exists(configPath)) { + if (!Files.exists(configPath)) { try { Files.createFile(configPath); save(); diff --git a/src/main/java/foundationgames/enhancedblockentities/config/gui/option/EBEOption.java b/src/main/java/foundationgames/enhancedblockentities/config/gui/option/EBEOption.java index 34a67527..f2cadca1 100644 --- a/src/main/java/foundationgames/enhancedblockentities/config/gui/option/EBEOption.java +++ b/src/main/java/foundationgames/enhancedblockentities/config/gui/option/EBEOption.java @@ -2,8 +2,8 @@ import foundationgames.enhancedblockentities.ReloadType; import foundationgames.enhancedblockentities.util.GuiUtil; +import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.resource.language.I18n; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; @@ -24,7 +24,7 @@ public final class EBEOption { private final int defaultValue; private int selected; - private MutableText tooltip = null; + private Tooltip tooltip = null; private Text text = null; public EBEOption(String key, List values, int defaultValue, boolean hasValueComments, TextPalette palette, ReloadType reloadType) { @@ -60,10 +60,10 @@ public Text getText() { return text; } - public MutableText getTooltip() { + public Tooltip getTooltip() { if (tooltip == null) { - if (hasValueComments) tooltip = Text.translatable(String.format("option.ebe.%s.valueComment.%s", key, getValue())).append(NEWLINE).append(comment.copyContentOnly()); - else tooltip = comment.copyContentOnly(); + if (hasValueComments) tooltip = Tooltip.of(Text.translatable(String.format("option.ebe.%s.valueComment.%s", key, getValue())).append(NEWLINE).append(comment.copyContentOnly())); + else tooltip = Tooltip.of(comment.copyContentOnly()); } return tooltip; } diff --git a/src/main/java/foundationgames/enhancedblockentities/config/gui/screen/EBEConfigScreen.java b/src/main/java/foundationgames/enhancedblockentities/config/gui/screen/EBEConfigScreen.java index 4e9ee1ae..fd8b9fab 100644 --- a/src/main/java/foundationgames/enhancedblockentities/config/gui/screen/EBEConfigScreen.java +++ b/src/main/java/foundationgames/enhancedblockentities/config/gui/screen/EBEConfigScreen.java @@ -1,29 +1,20 @@ package foundationgames.enhancedblockentities.config.gui.screen; import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.systems.RenderSystem; -import dev.lambdaurora.spruceui.Position; -import dev.lambdaurora.spruceui.background.DirtTexturedBackground; -import dev.lambdaurora.spruceui.option.SpruceCyclingOption; -import dev.lambdaurora.spruceui.option.SpruceOption; -import dev.lambdaurora.spruceui.option.SpruceSeparatorOption; -import dev.lambdaurora.spruceui.screen.SpruceScreen; -import dev.lambdaurora.spruceui.util.RenderUtil; -import dev.lambdaurora.spruceui.widget.SpruceButtonWidget; -import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget; import foundationgames.enhancedblockentities.EnhancedBlockEntities; import foundationgames.enhancedblockentities.ReloadType; import foundationgames.enhancedblockentities.config.EBEConfig; import foundationgames.enhancedblockentities.config.gui.option.EBEOption; import foundationgames.enhancedblockentities.config.gui.option.TextPalette; +import foundationgames.enhancedblockentities.config.gui.widget.SectionTextWidget; +import foundationgames.enhancedblockentities.config.gui.widget.WidgetRowListWidget; import foundationgames.enhancedblockentities.util.EBEUtil; import foundationgames.enhancedblockentities.util.GuiUtil; - import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.RotatingCubeMapRenderer; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.GridWidget; import net.minecraft.client.resource.language.I18n; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Text; @@ -35,28 +26,27 @@ import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; -public class EBEConfigScreen extends SpruceScreen { - private SpruceOptionListWidget optionsWidget; - private List options = new ArrayList<>(); +public class EBEConfigScreen extends Screen { + private WidgetRowListWidget optionsWidget; + private final List options = new ArrayList<>(); private final Screen parent; private static final ImmutableList BOOLEAN_OPTIONS = ImmutableList.of("true", "false"); private static final ImmutableList ALLOWED_FORCED_DISABLED = ImmutableList.of("allowed", "forced", "disabled"); private static final ImmutableList SIGN_TEXT_OPTIONS = ImmutableList.of("smart", "all", "most", "some", "few"); - private static final Text HOLD_SHIFT = Text.translatable("text.ebe.descriptions").formatted(Formatting.DARK_GRAY, Formatting.ITALIC); - private static final String CHEST_OPTIONS_TITLE = "text.ebe.chest_options"; - private static final String SIGN_OPTIONS_TITLE = "text.ebe.sign_options"; - private static final String BELL_OPTIONS_TITLE = "text.ebe.bell_options"; - private static final String BED_OPTIONS_TITLE = "text.ebe.bed_options"; - private static final String SHULKER_BOX_OPTIONS_TITLE = "text.ebe.shulker_box_options"; - private static final String DECORATED_POT_OPTIONS_TITLE = "text.ebe.decorated_pot_options"; - private static final String ADVANCED_TITLE = "text.ebe.advanced"; + private static final Text HOLD_SHIFT = Text.translatable("text.ebe.descriptions").formatted(Formatting.GRAY, Formatting.ITALIC); + private static final Text CHEST_OPTIONS_TITLE = Text.translatable("text.ebe.chest_options"); + private static final Text SIGN_OPTIONS_TITLE = Text.translatable("text.ebe.sign_options"); + private static final Text BELL_OPTIONS_TITLE = Text.translatable("text.ebe.bell_options"); + private static final Text BED_OPTIONS_TITLE = Text.translatable("text.ebe.bed_options"); + private static final Text SHULKER_BOX_OPTIONS_TITLE = Text.translatable("text.ebe.shulker_box_options"); + private static final Text DECORATED_POT_OPTIONS_TITLE = Text.translatable("text.ebe.decorated_pot_options"); + private static final Text ADVANCED_TITLE = Text.translatable("text.ebe.advanced"); private static final Text DUMP_LABEL = Text.translatable("option.ebe.dump"); private final Text dumpTooltip = GuiUtil.shorten(I18n.translate("option.ebe.dump.comment"), 20); - private final RotatingCubeMapRenderer background = new RotatingCubeMapRenderer(TitleScreen.PANORAMA_CUBE_MAP); public EBEConfigScreen(Screen screen) { super(Text.translatable("screen.ebe.config")); @@ -66,37 +56,45 @@ public EBEConfigScreen(Screen screen) { @Override protected void init() { super.init(); - int bottomCenter = this.width / 2 - 50; - this.optionsWidget = new SpruceOptionListWidget(Position.of(0, 34), this.width, this.height - 69); + this.optionsWidget = new WidgetRowListWidget(this.client, this.width, this.height, 34, this.height - 34, 316, 20); this.options.clear(); - this.optionsWidget.setBackground(new DirtTexturedBackground(32, 32, 32, 0)); + addOptions(); this.addDrawableChild(optionsWidget); - this.addDrawableChild(new SpruceButtonWidget(Position.of(bottomCenter - 104, this.height - 27), 100, 20, ScreenTexts.CANCEL, button -> this.close())); - this.addDrawableChild(new SpruceButtonWidget(Position.of(bottomCenter, this.height - 27), 100, 20, Text.translatable("text.ebe.apply"), button -> this.applyChanges())); - this.addDrawableChild(new SpruceButtonWidget(Position.of(bottomCenter + 104, this.height - 27), 100, 20, ScreenTexts.DONE, button -> { - applyChanges(); - close(); - })); + var menuButtons = new GridWidget(); + menuButtons.setColumnSpacing(4); + + var menuButtonAdder = menuButtons.createAdder(3); + + menuButtonAdder.add(ButtonWidget.builder(ScreenTexts.CANCEL, button -> this.close()) + .size(100, 20).build()); + menuButtonAdder.add(ButtonWidget.builder(Text.translatable("text.ebe.apply"), button -> this.applyChanges()) + .size(100, 20).build()); + menuButtonAdder.add(ButtonWidget.builder(ScreenTexts.DONE, + button -> { + applyChanges(); + close(); + }) + .size(100, 20).build()); + + menuButtons.refreshPositions(); + menuButtons.setPosition((this.width - menuButtons.getWidth()) / 2, this.height - 27); + menuButtons.forEachChild((child) -> { + child.setNavigationOrder(1); + this.addDrawableChild(child); + }); } - @Override - public void renderBackgroundTexture(DrawContext context) { - } +// @Override +// protected void renderDarkening(DrawContext context) { +// renderDarkening(context, 0, 0, this.width, 34); +// renderDarkening(context, 0, this.height - 35, this.width, 35); +// } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - if (this.client.world == null) { - this.background.render(delta, 1); - RenderSystem.setShader(GameRenderer::getPositionTexProgram); - } - - context.fillGradient(0, 0, width, height, 0x4F141414, 0x4F141414); - RenderUtil.renderBackgroundTexture(0, 0, this.width, 34, 0); - RenderUtil.renderBackgroundTexture(0, this.height - 35, this.width, 35, 0); - super.render(context, mouseX, mouseY, delta); context.drawCenteredTextWithShadow(this.textRenderer, this.title, (int)(this.width * 0.5), 8, 0xFFFFFF); @@ -127,81 +125,88 @@ public void addOptions() { Properties config = new Properties(); EnhancedBlockEntities.CONFIG.writeTo(config); - optionsWidget.addSingleOptionEntry(new SpruceSeparatorOption(CHEST_OPTIONS_TITLE, true, null)); - optionsWidget.addSingleOptionEntry(option( + final var textRenderer = this.client.textRenderer; + + optionsWidget.add(new SectionTextWidget(CHEST_OPTIONS_TITLE, textRenderer)); + optionsWidget.add(option( new EBEOption(EBEConfig.RENDER_ENHANCED_CHESTS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.RENDER_ENHANCED_CHESTS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.CHEST_AO_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.CHEST_AO_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.EXPERIMENTAL_CHESTS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.EXPERIMENTAL_CHESTS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) ), option( new EBEOption(EBEConfig.CHRISTMAS_CHESTS_KEY, ALLOWED_FORCED_DISABLED, ALLOWED_FORCED_DISABLED.indexOf(config.getProperty(EBEConfig.CHRISTMAS_CHESTS_KEY)), true, TextPalette.rainbow(0.35f), ReloadType.WORLD) )); - optionsWidget.addSingleOptionEntry(new SpruceSeparatorOption(SIGN_OPTIONS_TITLE, true, null)); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(new SectionTextWidget(SIGN_OPTIONS_TITLE, textRenderer)); + optionsWidget.add(option( new EBEOption(EBEConfig.RENDER_ENHANCED_SIGNS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.RENDER_ENHANCED_SIGNS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.SIGN_TEXT_RENDERING_KEY, SIGN_TEXT_OPTIONS, SIGN_TEXT_OPTIONS.indexOf(config.getProperty(EBEConfig.SIGN_TEXT_RENDERING_KEY)), true, TextPalette.rainbow(0.45f), ReloadType.NONE) )); - optionsWidget.addOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.EXPERIMENTAL_SIGNS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.EXPERIMENTAL_SIGNS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) ), option( new EBEOption(EBEConfig.SIGN_AO_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.SIGN_AO_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(new SpruceSeparatorOption(BELL_OPTIONS_TITLE, true, null)); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(new SectionTextWidget(BELL_OPTIONS_TITLE, textRenderer)); + optionsWidget.add(option( new EBEOption(EBEConfig.RENDER_ENHANCED_BELLS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.RENDER_ENHANCED_BELLS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.BELL_AO_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.BELL_AO_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(new SpruceSeparatorOption(BED_OPTIONS_TITLE, true, null)); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(new SectionTextWidget(BED_OPTIONS_TITLE, textRenderer)); + optionsWidget.add(option( new EBEOption(EBEConfig.RENDER_ENHANCED_BEDS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.RENDER_ENHANCED_BEDS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.EXPERIMENTAL_BEDS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.EXPERIMENTAL_BEDS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) ), option( new EBEOption(EBEConfig.BED_AO_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.BED_AO_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(new SpruceSeparatorOption(SHULKER_BOX_OPTIONS_TITLE, true, null)); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(new SectionTextWidget(SHULKER_BOX_OPTIONS_TITLE, textRenderer)); + optionsWidget.add(option( new EBEOption(EBEConfig.RENDER_ENHANCED_SHULKER_BOXES_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.RENDER_ENHANCED_SHULKER_BOXES_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.SHULKER_BOX_AO_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.SHULKER_BOX_AO_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(new SpruceSeparatorOption(DECORATED_POT_OPTIONS_TITLE, true, null)); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(new SectionTextWidget(DECORATED_POT_OPTIONS_TITLE, textRenderer)); + optionsWidget.add(option( new EBEOption(EBEConfig.RENDER_ENHANCED_DECORATED_POTS_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.RENDER_ENHANCED_DECORATED_POTS_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(option( new EBEOption(EBEConfig.DECORATED_POT_AO_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.DECORATED_POT_AO_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(new SpruceSeparatorOption(ADVANCED_TITLE, true, null)); - optionsWidget.addSingleOptionEntry(option( + optionsWidget.add(new SectionTextWidget(ADVANCED_TITLE, textRenderer)); + optionsWidget.add(option( new EBEOption(EBEConfig.FORCE_RESOURCE_PACK_COMPAT_KEY, BOOLEAN_OPTIONS, BOOLEAN_OPTIONS.indexOf(config.getProperty(EBEConfig.FORCE_RESOURCE_PACK_COMPAT_KEY)), false, TextPalette.ON_OFF, ReloadType.RESOURCES) )); - optionsWidget.addSingleOptionEntry(new SpruceCyclingOption("option.ebe.dump", i -> { + optionsWidget.add(ButtonWidget.builder(DUMP_LABEL, b -> { try { EBEUtil.dumpResources(); } catch (IOException e) { EnhancedBlockEntities.LOG.error(e); } - }, o -> DUMP_LABEL, dumpTooltip)); + }).tooltip(Tooltip.of(dumpTooltip)).build()); } - private SpruceOption option(EBEOption option) { + private ButtonWidget option(EBEOption option) { options.add(option); - return new SpruceCyclingOption(option.getOptionKey(), i -> option.next(), o -> option.getText(), option.getTooltip()); + + return ButtonWidget.builder(option.getText(), b -> { + option.next(); + b.setMessage(option.getText()); + b.setTooltip(option.getTooltip()); + }).tooltip(option.getTooltip()).build(); } } diff --git a/src/main/java/foundationgames/enhancedblockentities/config/gui/widget/SectionTextWidget.java b/src/main/java/foundationgames/enhancedblockentities/config/gui/widget/SectionTextWidget.java new file mode 100644 index 00000000..7acc1d1d --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/config/gui/widget/SectionTextWidget.java @@ -0,0 +1,44 @@ +package foundationgames.enhancedblockentities.config.gui.widget; + +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.AbstractTextWidget; +import net.minecraft.text.Text; + +public class SectionTextWidget extends AbstractTextWidget { + public SectionTextWidget(Text message, TextRenderer textRenderer) { + this(0, 0, 200, 20, message, textRenderer); + } + + public SectionTextWidget(int x, int y, int width, int height, Text message, TextRenderer textRenderer) { + super(x, y, width, height, message, textRenderer); + this.active = false; + } + + @Override + public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) { + final int white = 0xFFFFFFFF; + var font = this.getTextRenderer(); + var msg = this.getMessage(); + + int l = this.getX(); + int w = this.getWidth(); + int r = l + w; + int y = (this.getY() + this.getHeight()) - 6; + + int tx = l + (w / 2); + int ty = y - (font.fontHeight / 2); + int tw = font.getWidth(msg); + + int ml = l + ((w - tw) / 2) - 5; + int mr = ml + tw + 10; + + l += 1; + r -= 1; + + context.fill(l, y, ml, y + 2, white); + context.fill(mr, y, r, y + 2, white); + + context.drawCenteredTextWithShadow(font, msg, tx, ty, 0xFFFFFF); + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/config/gui/widget/WidgetRowListWidget.java b/src/main/java/foundationgames/enhancedblockentities/config/gui/widget/WidgetRowListWidget.java new file mode 100644 index 00000000..60044550 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/config/gui/widget/WidgetRowListWidget.java @@ -0,0 +1,88 @@ +package foundationgames.enhancedblockentities.config.gui.widget; + +import foundationgames.enhancedblockentities.mixin.ClickableWidgetAccessor; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.Selectable; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.gui.widget.GridWidget; + +import java.util.ArrayList; +import java.util.List; + +public class WidgetRowListWidget extends ElementListWidget { + public static final int SPACING = 3; + + public final int rowWidth; + public final int rowHeight; + + public WidgetRowListWidget(MinecraftClient mc, int w, int h, int top, int bottom, int rowWidth, int rowHeight) { + super(mc, w, h, top, bottom, rowHeight + SPACING); + this.rowWidth = rowWidth; + this.rowHeight = rowHeight; + } + + public void add(ClickableWidget ... widgets) { + if (widgets.length == 0) return; + + var grid = new GridWidget(); + grid.setColumnSpacing(SPACING); + var adder = grid.createAdder(widgets.length); + + int width = (this.rowWidth - ((widgets.length - 1) * SPACING)) / widgets.length; + + for (var widget : widgets) { + widget.setWidth(width); + ((ClickableWidgetAccessor) widget).setHeight(this.rowHeight); + adder.add(widget); + } + + grid.refreshPositions(); + + this.addEntry(new Entry(grid)); + } + + @Override + public int getRowWidth() { + return rowWidth; + } + + @Override + protected int getScrollbarPositionX() { + return this.width - 6; + } + +// @Override +// protected void drawMenuListBackground(DrawContext context) { +// } + + public static class Entry extends ElementListWidget.Entry { + private final GridWidget widget; + private final List children = new ArrayList<>(); + + public Entry(GridWidget widget) { + this.widget = widget; + widget.forEachChild(children::add); + } + + @Override + public List children() { + return this.children; + } + + @Override + public List selectableChildren() { + return this.children; + } + + @Override + public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + this.widget.setPosition(x - 3, y); + this.widget.refreshPositions(); + + this.widget.forEachChild(c -> c.render(context, mouseX, mouseY, tickDelta)); + } + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/event/EBEEvents.java b/src/main/java/foundationgames/enhancedblockentities/event/EBEEvents.java index 62b07070..0c8918fc 100644 --- a/src/main/java/foundationgames/enhancedblockentities/event/EBEEvents.java +++ b/src/main/java/foundationgames/enhancedblockentities/event/EBEEvents.java @@ -7,13 +7,9 @@ import net.minecraft.util.profiler.Profiler; public enum EBEEvents {; - public static final Event RELOAD_MODELS = EventFactory.createArrayBacked(Reload.class, (callbacks) -> (loader, manager, profiler) -> { - for(Reload event : callbacks) { - event.onReload(loader, manager, profiler); + public static final Event RESOURCE_RELOAD = EventFactory.createArrayBacked(Runnable.class, (callbacks) -> () -> { + for (var event : callbacks) { + event.run(); } }); - - public interface Reload { - void onReload(ModelLoader loader, ResourceManager manager, Profiler profiler); - } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/AbstractBlockStateMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/AbstractBlockStateMixin.java index c454355f..f473ea76 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/AbstractBlockStateMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/AbstractBlockStateMixin.java @@ -17,7 +17,7 @@ public abstract class AbstractBlockStateMixin { @Inject(method = "getRenderType", at = @At("HEAD"), cancellable = true) public void enhanced_bes$overrideRenderType(CallbackInfoReturnable cir) { Block block = this.getBlock(); - if(EnhancedBlockEntityRegistry.BLOCKS.contains(block)) { + if (EnhancedBlockEntityRegistry.BLOCKS.contains(block)) { cir.setReturnValue(BlockRenderType.MODEL); } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/BakedModelManagerMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/BakedModelManagerMixin.java deleted file mode 100644 index 02660de0..00000000 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/BakedModelManagerMixin.java +++ /dev/null @@ -1,40 +0,0 @@ -package foundationgames.enhancedblockentities.mixin; - -import foundationgames.enhancedblockentities.event.EBEEvents; -import foundationgames.enhancedblockentities.util.duck.BakedModelManagerAccess; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BakedModelManager; -import net.minecraft.resource.ResourceManager; -import net.minecraft.resource.ResourceReloader; -import net.minecraft.util.Identifier; -import net.minecraft.util.profiler.Profiler; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; - -@Mixin(BakedModelManager.class) -public class BakedModelManagerMixin implements BakedModelManagerAccess { - @Shadow private Map models; - - @Override - public BakedModel getModel(Identifier id) { - return this.models.get(id); - } - - // Should invoke the EBE event after the model manager's block model cache is filled during a resource reload - @Inject(method = "reload", at = @At("TAIL")) - public void enhanced_bes$invokeReloadEvent(ResourceReloader.Synchronizer synchronizer, ResourceManager manager, - Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, - Executor applyExecutor, CallbackInfoReturnable> cir) { - cir.getReturnValue().thenAccept(obj -> { - var result = (BakedModelManager.BakingResult)(Object)obj; - EBEEvents.RELOAD_MODELS.invoker().onReload(result.modelLoader(), manager, applyProfiler); - }); - } -} diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/BellBlockEntityMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/BellBlockEntityMixin.java index 3059d081..c34954f4 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/BellBlockEntityMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/BellBlockEntityMixin.java @@ -1,7 +1,7 @@ package foundationgames.enhancedblockentities.mixin; import foundationgames.enhancedblockentities.EnhancedBlockEntities; -import foundationgames.enhancedblockentities.util.duck.ModelStateHolder; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BellBlockEntity; import net.minecraft.block.entity.BlockEntity; @@ -14,8 +14,9 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable; @Mixin(BellBlockEntity.class) -public class BellBlockEntityMixin extends BlockEntity implements ModelStateHolder { +public class BellBlockEntityMixin extends BlockEntity implements AppearanceStateHolder { @Unique private int enhanced_bes$modelState = 0; + @Unique private int enhanced_bes$renderState = 0; public BellBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -28,8 +29,8 @@ public BellBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState st ), index = 3) private static BellBlockEntity enhanced_bes$listenForStopRinging(BellBlockEntity blockEntity) { int mState = blockEntity.ringTicks > 0 ? 1 : 0; - if (EnhancedBlockEntities.CONFIG.renderEnhancedBells && ((ModelStateHolder)blockEntity).getModelState() != mState) { - ((ModelStateHolder)blockEntity).setModelState(mState, blockEntity.getWorld(), blockEntity.getPos()); + if (EnhancedBlockEntities.CONFIG.renderEnhancedBells && ((AppearanceStateHolder)blockEntity).getModelState() != mState) { + ((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, blockEntity.getWorld(), blockEntity.getPos()); } return blockEntity; } @@ -40,7 +41,17 @@ public int getModelState() { } @Override - public void applyModelState(int state) { + public void setModelState(int state) { this.enhanced_bes$modelState = state; } + + @Override + public int getRenderState() { + return enhanced_bes$renderState; + } + + @Override + public void setRenderState(int state) { + this.enhanced_bes$renderState = state; + } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/BlockEntityRenderDispatcherMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/BlockEntityRenderDispatcherMixin.java index 25f14e27..609d2ea9 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/BlockEntityRenderDispatcherMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/BlockEntityRenderDispatcherMixin.java @@ -24,9 +24,9 @@ public class BlockEntityRenderDispatcherMixin { cancellable = true ) private static void enhanced_bes$renderOverrides(BlockEntityRenderer renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { - if(EnhancedBlockEntityRegistry.ENTITIES.containsKey(blockEntity.getType()) && EnhancedBlockEntityRegistry.BLOCKS.contains(blockEntity.getCachedState().getBlock())) { + if (EnhancedBlockEntityRegistry.ENTITIES.containsKey(blockEntity.getType()) && EnhancedBlockEntityRegistry.BLOCKS.contains(blockEntity.getCachedState().getBlock())) { Pair entry = EnhancedBlockEntityRegistry.ENTITIES.get(blockEntity.getType()); - if(entry.getLeft().shouldRender(blockEntity)) { + if (entry.getLeft().shouldRender(blockEntity)) { entry.getRight().render(renderer, blockEntity, tickDelta, matrices, vertexConsumers, WorldRenderer.getLightmapCoordinates(blockEntity.getWorld(), blockEntity.getPos()), OverlayTexture.DEFAULT_UV); } ci.cancel(); diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/BuiltChunkMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/BuiltChunkMixin.java new file mode 100644 index 00000000..910d50e1 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/BuiltChunkMixin.java @@ -0,0 +1,23 @@ +package foundationgames.enhancedblockentities.mixin; + +import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess; +import net.minecraft.client.render.chunk.ChunkBuilder; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ChunkBuilder.BuiltChunk.class) +public class BuiltChunkMixin implements ChunkRebuildTaskAccess { + private @Unique + @Nullable Runnable enhanced_bes$taskAfterRebuild = null; + + @Override + public Runnable enhanced_bes$getTaskAfterRebuild() { + return enhanced_bes$taskAfterRebuild; + } + + @Override + public void enhanced_bes$setTaskAfterRebuild(Runnable task) { + enhanced_bes$taskAfterRebuild = task; + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/ChestBlockEntityMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/ChestBlockEntityMixin.java index b5066f1b..8a5fecc0 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/ChestBlockEntityMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/ChestBlockEntityMixin.java @@ -2,7 +2,7 @@ import foundationgames.enhancedblockentities.EnhancedBlockEntities; import foundationgames.enhancedblockentities.client.render.entity.ChestBlockEntityRendererOverride; -import foundationgames.enhancedblockentities.util.duck.ModelStateHolder; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -16,8 +16,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ChestBlockEntity.class) -public abstract class ChestBlockEntityMixin extends BlockEntity implements ModelStateHolder { +public abstract class ChestBlockEntityMixin extends BlockEntity implements AppearanceStateHolder { @Unique private int enhanced_bes$modelState = 0; + @Unique private int enhanced_bes$renderState = 0; private ChestBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -25,10 +26,11 @@ private ChestBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState @Inject(method = "clientTick", at = @At(value = "TAIL")) private static void enhanced_bes$listenForOpenClose(World world, BlockPos pos, BlockState state, ChestBlockEntity blockEntity, CallbackInfo ci) { - int mState = ChestBlockEntityRendererOverride.getAnimationProgress(blockEntity, 0) - .getAnimationProgress(0) > 0 ? 1 : 0; - if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((ModelStateHolder)blockEntity).getModelState() != mState) { - ((ModelStateHolder)blockEntity).setModelState(mState, world, pos); + var lid = ChestBlockEntityRendererOverride.getLidAnimationHolder(blockEntity, 0.5f); + int mState = lid.getAnimationProgress(0.5f) > 0 ? 1 : 0; + + if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((AppearanceStateHolder)blockEntity).getModelState() != mState) { + ((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, world, pos); } } @@ -38,7 +40,17 @@ public int getModelState() { } @Override - public void applyModelState(int state) { + public void setModelState(int state) { this.enhanced_bes$modelState = state; } + + @Override + public int getRenderState() { + return enhanced_bes$renderState; + } + + @Override + public void setRenderState(int state) { + this.enhanced_bes$renderState = state; + } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/ClickableWidgetAccessor.java b/src/main/java/foundationgames/enhancedblockentities/mixin/ClickableWidgetAccessor.java new file mode 100644 index 00000000..3c37793f --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/ClickableWidgetAccessor.java @@ -0,0 +1,12 @@ +package foundationgames.enhancedblockentities.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.gui.widget.ClickableWidget; + +@Mixin(ClickableWidget.class) +public interface ClickableWidgetAccessor { + @Accessor + void setHeight(int value); +} diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/DecoratedPotBlockEntityMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/DecoratedPotBlockEntityMixin.java index 3bee64a7..abc1d7f1 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/DecoratedPotBlockEntityMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/DecoratedPotBlockEntityMixin.java @@ -1,21 +1,46 @@ package foundationgames.enhancedblockentities.mixin; import foundationgames.enhancedblockentities.util.WorldUtil; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.minecraft.block.entity.DecoratedPotBlockEntity; import net.minecraft.nbt.NbtCompound; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(DecoratedPotBlockEntity.class) -public class DecoratedPotBlockEntityMixin { +public class DecoratedPotBlockEntityMixin implements AppearanceStateHolder { + @Unique private int enhanced_bes$modelState = 0; + @Unique private int enhanced_bes$renderState = 0; + @Inject(method = "readNbt", at = @At("TAIL")) private void enhanced_bes$updateChunkOnPatternsLoaded(NbtCompound nbt, CallbackInfo ci) { var self = (DecoratedPotBlockEntity)(Object)this; if (self.getWorld() != null && self.getWorld().isClient()) { - WorldUtil.rebuildChunkSynchronously(self.getWorld(), self.getPos(), false); + WorldUtil.rebuildChunk(self.getWorld(), self.getPos()); } } + + @Override + public int getModelState() { + return enhanced_bes$modelState; + } + + @Override + public void setModelState(int state) { + this.enhanced_bes$modelState = state; + } + + @Override + public int getRenderState() { + return enhanced_bes$renderState; + } + + @Override + public void setRenderState(int state) { + this.enhanced_bes$renderState = state; + } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/EnderChestBlockEntityMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/EnderChestBlockEntityMixin.java index 6b8db544..b24c90e9 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/EnderChestBlockEntityMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/EnderChestBlockEntityMixin.java @@ -1,7 +1,8 @@ package foundationgames.enhancedblockentities.mixin; import foundationgames.enhancedblockentities.EnhancedBlockEntities; -import foundationgames.enhancedblockentities.util.duck.ModelStateHolder; +import foundationgames.enhancedblockentities.client.render.entity.ChestBlockEntityRendererOverride; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -15,8 +16,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EnderChestBlockEntity.class) -public abstract class EnderChestBlockEntityMixin extends BlockEntity implements ModelStateHolder { +public abstract class EnderChestBlockEntityMixin extends BlockEntity implements AppearanceStateHolder { @Unique private int enhanced_bes$modelState = 0; + @Unique private int enhanced_bes$renderState = 0; private EnderChestBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -24,9 +26,11 @@ private EnderChestBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockS @Inject(method = "clientTick", at = @At(value = "TAIL")) private static void enhanced_bes$listenForOpenClose(World world, BlockPos pos, BlockState state, EnderChestBlockEntity blockEntity, CallbackInfo ci) { - int mState = blockEntity.getAnimationProgress(0) > 0 ? 1 : 0; - if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((ModelStateHolder)blockEntity).getModelState() != mState) { - ((ModelStateHolder)blockEntity).setModelState(mState, world, pos); + var lid = ChestBlockEntityRendererOverride.getLidAnimationHolder(blockEntity, 0.5f); + int mState = lid.getAnimationProgress(0.5f) > 0 ? 1 : 0; + + if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((AppearanceStateHolder)blockEntity).getModelState() != mState) { + ((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, world, pos); } } @@ -36,7 +40,17 @@ public int getModelState() { } @Override - public void applyModelState(int state) { + public void setModelState(int state) { this.enhanced_bes$modelState = state; } + + @Override + public int getRenderState() { + return enhanced_bes$renderState; + } + + @Override + public void setRenderState(int state) { + this.enhanced_bes$renderState = state; + } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/MinecraftClientMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/MinecraftClientMixin.java new file mode 100644 index 00000000..99ab3c43 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/MinecraftClientMixin.java @@ -0,0 +1,19 @@ +package foundationgames.enhancedblockentities.mixin; + +import foundationgames.enhancedblockentities.event.EBEEvents; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.concurrent.CompletableFuture; + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + @Inject(method = "reloadResources()Ljava/util/concurrent/CompletableFuture;", + at = @At("RETURN")) + private void enhanced_bes$fireReloadEvent(CallbackInfoReturnable> cir) { + cir.getReturnValue().thenAccept(v -> EBEEvents.RESOURCE_RELOAD.invoker().run()); + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/ShulkerBoxBlockEntityMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/ShulkerBoxBlockEntityMixin.java index 8dbfb0b0..472076fe 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/ShulkerBoxBlockEntityMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/ShulkerBoxBlockEntityMixin.java @@ -1,6 +1,6 @@ package foundationgames.enhancedblockentities.mixin; -import foundationgames.enhancedblockentities.util.duck.ModelStateHolder; +import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -15,10 +15,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ShulkerBoxBlockEntity.class) -public abstract class ShulkerBoxBlockEntityMixin extends BlockEntity implements ModelStateHolder { +public abstract class ShulkerBoxBlockEntityMixin extends BlockEntity implements AppearanceStateHolder { @Shadow public abstract float getAnimationProgress(float delta); @Unique private int enhanced_bes$modelState = 0; + @Unique private int enhanced_bes$renderState = 0; public ShulkerBoxBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -27,7 +28,7 @@ public ShulkerBoxBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockSt @Inject(method = "updateAnimation", at = @At("TAIL")) private void enhanced_bes$updateModelState(World world, BlockPos pos, BlockState state, CallbackInfo ci) { int mState = this.getAnimationProgress(0) > 0 ? 1 : 0; - if (mState != enhanced_bes$modelState) setModelState(mState, world, pos); + if (mState != enhanced_bes$modelState) updateAppearanceState(mState, world, pos); } @Override @@ -36,7 +37,17 @@ public int getModelState() { } @Override - public void applyModelState(int state) { + public void setModelState(int state) { this.enhanced_bes$modelState = state; } + + @Override + public int getRenderState() { + return enhanced_bes$renderState; + } + + @Override + public void setRenderState(int state) { + this.enhanced_bes$renderState = state; + } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/SignBlockEntityRenderAccessor.java b/src/main/java/foundationgames/enhancedblockentities/mixin/SignBlockEntityRenderAccessor.java index 3ce12b71..6e4b2bcd 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/SignBlockEntityRenderAccessor.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/SignBlockEntityRenderAccessor.java @@ -6,7 +6,6 @@ import net.minecraft.client.render.block.entity.SignBlockEntityRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.BlockPos; - import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/VideoOptionsScreenMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/VideoOptionsScreenMixin.java index c3785d7c..3edfe38b 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/VideoOptionsScreenMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/VideoOptionsScreenMixin.java @@ -15,12 +15,6 @@ protected VideoOptionsScreenMixin(Text title) { super(title); } - /* X----------------------------------init()------------------------------------X - | this.list.addSingleOptionEntry(this.gameOptions.getBiomeBlendRadius()); | - |---> HERE <--- | - | this.list.addAll(getOptions(this.gameOptions)); | - | this.addSelectableChild(this.list); | - X----------------------------[END: 5 LINES DOWN]-----------------------------X */ @ModifyArg( method = "init", at = @At( diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/WorldRendererMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/WorldRendererMixin.java index d775dc5b..c2eb6875 100644 --- a/src/main/java/foundationgames/enhancedblockentities/mixin/WorldRendererMixin.java +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/WorldRendererMixin.java @@ -1,26 +1,37 @@ package foundationgames.enhancedblockentities.mixin; import foundationgames.enhancedblockentities.util.WorldUtil; +import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess; import net.minecraft.client.render.WorldRenderer; -import org.objectweb.asm.Opcodes; +import net.minecraft.client.render.chunk.ChunkBuilder; +import net.minecraft.util.math.ChunkSectionPos; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(WorldRenderer.class) public class WorldRendererMixin { - /* X------------------------updateChunks(Camera camera)-------------------------X - |---> HERE <--- | - | if (bl) { | - | this.client.getProfiler().push("build_near_sync"); | - | this.chunkBuilder.rebuild(builtChunk, chunkRendererRegionBuilder); | - X----------------------------[END: 5 LINES DOWN]-----------------------------X */ - @ModifyVariable(method = "updateChunks", at = @At(value = "JUMP", shift = At.Shift.BEFORE, opcode = Opcodes.IFEQ, ordinal = 4), index = 10) - private boolean enhanced_bes$forceSynchronousChunkRebuild(boolean old) { - if (WorldUtil.FORCE_SYNCHRONOUS_CHUNK_REBUILD) { - WorldUtil.FORCE_SYNCHRONOUS_CHUNK_REBUILD = false; - return true; + + @ModifyVariable(method = "updateChunks", + at = @At(value = "INVOKE", shift = At.Shift.BEFORE, ordinal = 0, target = "Lnet/minecraft/client/option/SimpleOption;getValue()Ljava/lang/Object;"), + index = 8) + private ChunkBuilder.BuiltChunk enhanced_bes$addPostRebuildTask(ChunkBuilder.BuiltChunk chunk) { + if (WorldUtil.CHUNK_UPDATE_TASKS.size() > 0) { + var pos = ChunkSectionPos.from(chunk.getOrigin()); + + if (WorldUtil.CHUNK_UPDATE_TASKS.containsKey(pos)) { + var task = WorldUtil.CHUNK_UPDATE_TASKS.remove(pos); + ((ChunkRebuildTaskAccess) chunk).enhanced_bes$setTaskAfterRebuild(task); + } } - return old; + + return chunk; + } + + @Inject(method = "addBuiltChunk", at = @At("HEAD")) + private void enhanced_bes$runPostRebuildTask(ChunkBuilder.BuiltChunk chunk, CallbackInfo ci) { + ((ChunkRebuildTaskAccess) chunk).enhanced_bes$runAfterRebuildTask(); } } diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionManagerMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionManagerMixin.java new file mode 100644 index 00000000..f481ee85 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionManagerMixin.java @@ -0,0 +1,46 @@ +package foundationgames.enhancedblockentities.mixin.compat.sodium; + +import foundationgames.enhancedblockentities.util.WorldUtil; +import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess; +import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; +import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; +import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; +import net.minecraft.util.math.ChunkSectionPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +/** + *

Adapted from {@link foundationgames.enhancedblockentities.mixin.WorldRendererMixin}

+ */ +@Pseudo +@Mixin(value = RenderSectionManager.class, remap = false) +public class RenderSectionManagerMixin { + @ModifyVariable(method = "submitRebuildTasks", + at = @At(value = "INVOKE", shift = At.Shift.BEFORE, ordinal = 0, target = "Lme/jellysquid/mods/sodium/client/render/chunk/RenderSection;isDisposed()Z"), + index = 4, require = 0 + ) + private RenderSection enhanced_bes$compat_sodium$cacheUpdatingChunk(RenderSection section) { + if (WorldUtil.CHUNK_UPDATE_TASKS.size() > 0) { + var pos = ChunkSectionPos.from(section.getChunkX(), section.getChunkY(), section.getChunkZ()); + + if (WorldUtil.CHUNK_UPDATE_TASKS.containsKey(pos)) { + var task = WorldUtil.CHUNK_UPDATE_TASKS.remove(pos); + ((ChunkRebuildTaskAccess) section).enhanced_bes$setTaskAfterRebuild(task); + } + } + + return section; + } + + @ModifyVariable(method = "processChunkBuildResults", + at = @At(value = "INVOKE_ASSIGN", shift = At.Shift.BEFORE, ordinal = 0, target = "Lme/jellysquid/mods/sodium/client/render/chunk/RenderSection;getBuildCancellationToken()Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;"), + index = 4, require = 0 + ) + private ChunkBuildOutput enhanced_bes$runPostRebuildTask(ChunkBuildOutput output) { + ((ChunkRebuildTaskAccess) output.render).enhanced_bes$runAfterRebuildTask(); + + return output; + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionMixin.java b/src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionMixin.java new file mode 100644 index 00000000..6fcb64d7 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionMixin.java @@ -0,0 +1,28 @@ +package foundationgames.enhancedblockentities.mixin.compat.sodium; + +import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess; +import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Unique; + + +/** + *

Adapted from {@link foundationgames.enhancedblockentities.mixin.BuiltChunkMixin}

+ */ +@Pseudo +@Mixin(value = RenderSection.class, remap = false) +public class RenderSectionMixin implements ChunkRebuildTaskAccess { + private @Unique @Nullable Runnable enhanced_bes$taskAfterRebuild = null; + + @Override + public Runnable enhanced_bes$getTaskAfterRebuild() { + return enhanced_bes$taskAfterRebuild; + } + + @Override + public void enhanced_bes$setTaskAfterRebuild(Runnable task) { + enhanced_bes$taskAfterRebuild = task; + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/util/ConvUtil.java b/src/main/java/foundationgames/enhancedblockentities/util/ConvUtil.java index b4127619..dadd94b9 100644 --- a/src/main/java/foundationgames/enhancedblockentities/util/ConvUtil.java +++ b/src/main/java/foundationgames/enhancedblockentities/util/ConvUtil.java @@ -2,7 +2,7 @@ public enum ConvUtil {; public static boolean bool(String bool) { - return bool != null && bool.toLowerCase().equals("true"); + return bool != null && bool.equalsIgnoreCase("true"); } public static boolean defaultedBool(String bool, boolean defaultVal) { diff --git a/src/main/java/foundationgames/enhancedblockentities/util/DateUtil.java b/src/main/java/foundationgames/enhancedblockentities/util/DateUtil.java index b609acb1..b3d28202 100644 --- a/src/main/java/foundationgames/enhancedblockentities/util/DateUtil.java +++ b/src/main/java/foundationgames/enhancedblockentities/util/DateUtil.java @@ -7,8 +7,8 @@ public enum DateUtil {; public static boolean isChristmas() { String config = EnhancedBlockEntities.CONFIG.christmasChests; - if(config.equals("disabled")) return false; - if(config.equals("forced")) return true; + if (config.equals("disabled")) return false; + if (config.equals("forced")) return true; Calendar calendar = Calendar.getInstance(); return (calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DATE) >= 24 && calendar.get(Calendar.DATE) <= 26); } diff --git a/src/main/java/foundationgames/enhancedblockentities/util/EBEUtil.java b/src/main/java/foundationgames/enhancedblockentities/util/EBEUtil.java index 268dd4af..0d161f83 100644 --- a/src/main/java/foundationgames/enhancedblockentities/util/EBEUtil.java +++ b/src/main/java/foundationgames/enhancedblockentities/util/EBEUtil.java @@ -39,7 +39,7 @@ public enum EBEUtil {; public static void renderBakedModel(VertexConsumerProvider vertexConsumers, BlockState state, MatrixStack matrices, BakedModel model, int light, int overlay) { VertexConsumer vertices = vertexConsumers.getBuffer(RenderLayers.getEntityBlockLayer(state, false)); for (int i = 0; i <= 6; i++) { - for(BakedQuad q : model.getQuads(null, ModelHelper.faceFromIndex(i), dummy)) { + for (BakedQuad q : model.getQuads(null, ModelHelper.faceFromIndex(i), dummy)) { vertices.quad(matrices.peek(), q, 1, 1, 1, light, overlay); } } diff --git a/src/main/java/foundationgames/enhancedblockentities/util/ExecutableRunnableHashSet.java b/src/main/java/foundationgames/enhancedblockentities/util/ExecutableRunnableHashSet.java new file mode 100644 index 00000000..bcaf81ae --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/util/ExecutableRunnableHashSet.java @@ -0,0 +1,10 @@ +package foundationgames.enhancedblockentities.util; + +import java.util.HashSet; + +public class ExecutableRunnableHashSet extends HashSet implements Runnable { + @Override + public void run() { + this.forEach(Runnable::run); + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/util/ResourceUtil.java b/src/main/java/foundationgames/enhancedblockentities/util/ResourceUtil.java index 8f35bd45..2d889466 100644 --- a/src/main/java/foundationgames/enhancedblockentities/util/ResourceUtil.java +++ b/src/main/java/foundationgames/enhancedblockentities/util/ResourceUtil.java @@ -2,13 +2,10 @@ import foundationgames.enhancedblockentities.EnhancedBlockEntities; import foundationgames.enhancedblockentities.client.resource.EBEPack; -import net.devtech.arrp.json.blockstate.JState; -import net.devtech.arrp.json.blockstate.JVariant; -import net.devtech.arrp.json.models.JModel; -import net.devtech.arrp.json.models.JTextures; +import foundationgames.enhancedblockentities.client.resource.template.TemplateProvider; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; -import net.minecraft.block.DecoratedPotPatterns; +import net.minecraft.client.render.TexturedRenderLayers; import net.minecraft.registry.RegistryKey; import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; @@ -28,111 +25,174 @@ public enum ResourceUtil {; private static EBEPack BASE_PACK; private static EBEPack TOP_LEVEL_PACK; - public static String createChestItemModelResource(String centerChest) { - return "{\"parent\":\"block/"+centerChest+"\",\"overrides\":[{\"predicate\":{\"ebe:is_christmas\":1},\"model\": \"item/christmas_chest\"}]}"; + public static void addChestItemModel(Identifier id, String centerChest, EBEPack pack) { + pack.addTemplateResource(id, t -> t.load("chest_item_model.json", d -> d.def("chest", centerChest))); } - private static JVariant variantRotation16(JVariant variant, String keyPrefix, String modelPrefix) { - return variant - .put(keyPrefix+"0", JState.model(modelPrefix+"_0").y(180)) - .put(keyPrefix+"1", JState.model(modelPrefix+"_67_5").y(270)) - .put(keyPrefix+"2", JState.model(modelPrefix+"_45").y(270)) - .put(keyPrefix+"3", JState.model(modelPrefix+"_22_5").y(270)) - .put(keyPrefix+"4", JState.model(modelPrefix+"_0").y(270)) - .put(keyPrefix+"5", JState.model(modelPrefix+"_67_5")) - .put(keyPrefix+"6", JState.model(modelPrefix+"_45")) - .put(keyPrefix+"7", JState.model(modelPrefix+"_22_5")) - .put(keyPrefix+"8", JState.model(modelPrefix+"_0")) - .put(keyPrefix+"9", JState.model(modelPrefix+"_67_5").y(90)) - .put(keyPrefix+"10", JState.model(modelPrefix+"_45").y(90)) - .put(keyPrefix+"11", JState.model(modelPrefix+"_22_5").y(90)) - .put(keyPrefix+"12", JState.model(modelPrefix+"_0").y(90)) - .put(keyPrefix+"13", JState.model(modelPrefix+"_67_5").y(180)) - .put(keyPrefix+"14", JState.model(modelPrefix+"_45").y(180)) - .put(keyPrefix+"15", JState.model(modelPrefix+"_22_5").y(180)); + private static String list(String ... els) { + return String.join(",", els); } - private static JVariant variantHFacing(JVariant variant, String keyPrefix, String model) { - return variant - .put(keyPrefix+"north", JState.model(model)) - .put(keyPrefix+"west", JState.model(model).y(270)) - .put(keyPrefix+"south", JState.model(model).y(180)) - .put(keyPrefix+"east", JState.model(model).y(90)); + private static String kv(String k, String v) { + return String.format("\""+k+"\":\""+v+"\""); } - public static void addSingleChestModels(String texture, String chestName, EBEPack pack) { - pack.addModel(JModel.model().parent("block/template_chest_center").textures(withChestParticle(JModel.textures().var("chest", texture), chestName)), new Identifier("block/" + chestName + "_center")); - pack.addModel(JModel.model().parent("block/template_chest_center_lid").textures(withChestParticle(JModel.textures().var("chest", texture), chestName)), new Identifier("block/" + chestName + "_center_lid")); - pack.addModel(JModel.model().parent("block/template_chest_center_trunk").textures(withChestParticle(JModel.textures().var("chest", texture), chestName)), new Identifier("block/" + chestName + "_center_trunk")); + private static String kv(String k, int v) { + return String.format("\""+k+"\":"+v+""); + } + + private static String variant(TemplateProvider t, String state, String model) throws IOException { + return t.load("blockstate/var.json", d -> d + .def("state", state) + .def("model", model) + .def("extra", "")); + } + + private static String variantY(TemplateProvider t, String state, String model, int y) throws IOException { + return t.load("blockstate/var.json", d -> d + .def("state", state) + .def("model", model) + .def("extra", kv("y", y) + ",")); + } + + private static String variantXY(TemplateProvider t, String state, String model, int x, int y) throws IOException { + return t.load("blockstate/var.json", d -> d + .def("state", state) + .def("model", model) + .def("extra", list( + kv("x", x), + kv("y", y) + ) + ",")); + } + + private static String variantRotation16(TemplateProvider t, String keyPrefix, String modelPrefix) throws IOException { + return list( + variantY(t, keyPrefix+"0", modelPrefix+"_0", 180), + variantY(t, keyPrefix+"1", modelPrefix+"_67_5", 270), + variantY(t, keyPrefix+"2", modelPrefix+"_45", 270), + variantY(t, keyPrefix+"3", modelPrefix+"_22_5", 270), + variantY(t, keyPrefix+"4", modelPrefix+"_0", 270), + variant(t, keyPrefix+"5", modelPrefix+"_67_5"), + variant(t, keyPrefix+"6", modelPrefix+"_45"), + variant(t, keyPrefix+"7", modelPrefix+"_22_5"), + variant(t, keyPrefix+"8", modelPrefix+"_0"), + variantY(t, keyPrefix+"9", modelPrefix+"_67_5", 90), + variantY(t, keyPrefix+"10", modelPrefix+"_45", 90), + variantY(t, keyPrefix+"11", modelPrefix+"_22_5", 90), + variantY(t, keyPrefix+"12", modelPrefix+"_0", 90), + variantY(t, keyPrefix+"13", modelPrefix+"_67_5", 180), + variantY(t, keyPrefix+"14", modelPrefix+"_45", 180), + variantY(t, keyPrefix+"15", modelPrefix+"_22_5", 180) + ); + } + + private static String variantHFacing(TemplateProvider t, String keyPrefix, String model) throws IOException { + return list( + variant(t, keyPrefix+"north", model), + variantY(t, keyPrefix+"west", model, 270), + variantY(t, keyPrefix+"south", model, 180), + variantY(t, keyPrefix+"east", model, 90) + ); + } + + private static void addChestLikeModel(String parent, String chestTex, String chestName, Identifier id, EBEPack pack) { + pack.addTemplateResource(new Identifier(id.getNamespace(), "models/" + id.getPath() + ".json"), + t -> t.load("model/chest_like.json", d -> d + .def("parent", parent) + .def("chest_tex", chestTex) + .def("particle", chestParticle(chestName)) + ) + ); + } + + public static void addSingleChestModels(String chestTex, String chestName, EBEPack pack) { + addChestLikeModel("template_chest_center", chestTex, chestName, new Identifier("block/" + chestName + "_center"), pack); + addChestLikeModel("template_chest_center_lid", chestTex, chestName, new Identifier("block/" + chestName + "_center_lid"), pack); + addChestLikeModel("template_chest_center_trunk", chestTex, chestName, new Identifier("block/" + chestName + "_center_trunk"), pack); } public static void addDoubleChestModels(String leftTex, String rightTex, String chestName, EBEPack pack) { - pack.addModel(JModel.model().parent("block/template_chest_left").textures(withChestParticle(JModel.textures().var("chest", leftTex), chestName)), new Identifier("block/" + chestName + "_left")); - pack.addModel(JModel.model().parent("block/template_chest_left_lid").textures(withChestParticle(JModel.textures().var("chest", leftTex), chestName)), new Identifier("block/" + chestName + "_left_lid")); - pack.addModel(JModel.model().parent("block/template_chest_left_trunk").textures(withChestParticle(JModel.textures().var("chest", leftTex), chestName)), new Identifier("block/" + chestName + "_left_trunk")); - pack.addModel(JModel.model().parent("block/template_chest_right").textures(withChestParticle(JModel.textures().var("chest", rightTex), chestName)), new Identifier("block/" + chestName + "_right")); - pack.addModel(JModel.model().parent("block/template_chest_right_lid").textures(withChestParticle(JModel.textures().var("chest", rightTex), chestName)), new Identifier("block/" + chestName + "_right_lid")); - pack.addModel(JModel.model().parent("block/template_chest_right_trunk").textures(withChestParticle(JModel.textures().var("chest", rightTex), chestName)), new Identifier("block/" + chestName + "_right_trunk")); + addChestLikeModel("template_chest_left", leftTex, chestName, new Identifier("block/" + chestName + "_left"), pack); + addChestLikeModel("template_chest_left_lid", leftTex, chestName, new Identifier("block/" + chestName + "_left_lid"), pack); + addChestLikeModel("template_chest_left_trunk", leftTex, chestName, new Identifier("block/" + chestName + "_left_trunk"), pack); + addChestLikeModel("template_chest_right", rightTex, chestName, new Identifier("block/" + chestName + "_right"), pack); + addChestLikeModel("template_chest_right_lid", rightTex, chestName, new Identifier("block/" + chestName + "_right_lid"), pack); + addChestLikeModel("template_chest_right_trunk", rightTex, chestName, new Identifier("block/" + chestName + "_right_trunk"), pack); } - private static JTextures withChestParticle(JTextures textures, String chestName) { - if (EnhancedBlockEntities.CONFIG.experimentalChests) textures.var("particle", "block/"+chestName+"_particle"); - return textures; + private static String chestParticle(String chestName) { + if (EnhancedBlockEntities.CONFIG.experimentalChests) return kv("particle", "block/"+chestName+"_particle") + ","; + return ""; } - private static JTextures withBedParticle(JTextures textures, String bedColor) { - if (EnhancedBlockEntities.CONFIG.experimentalBeds) textures.var("particle", "block/"+bedColor+"_bed_particle"); - return textures; + private static String bedParticle(String bedColor) { + if (EnhancedBlockEntities.CONFIG.experimentalBeds) return kv("particle", "block/"+bedColor+"_bed_particle") + ","; + return ""; } - private static JTextures withSignParticle(JTextures textures, String signName) { - if (EnhancedBlockEntities.CONFIG.experimentalSigns) textures.var("particle", "block/"+signName+"_particle"); - return textures; + private static String signParticle(String signName) { + if (EnhancedBlockEntities.CONFIG.experimentalSigns) return kv("particle", "block/"+signName+"_particle") + ","; + return ""; } - public static void addChestBlockStates(String chestName, EBEPack pack) { - var variant = JState.variant(); - variantHFacing(variant, "type=single,facing=", "builtin:"+chestName+"_center"); - variantHFacing(variant, "type=left,facing=", "builtin:"+chestName+"_left"); - variantHFacing(variant, "type=right,facing=", "builtin:"+chestName+"_right"); + private static void addBlockState(Identifier id, TemplateProvider.TemplateApplyingFunction vars, EBEPack pack) { + pack.addTemplateResource(new Identifier(id.getNamespace(), "blockstates/" + id.getPath() + ".json"), + t -> t.load("blockstate/base.json", d -> d.def("vars", vars))); + } - pack.addBlockState(JState.state(variant), new Identifier(chestName)); + public static void addChestBlockStates(String chestName, EBEPack pack) { + addBlockState(new Identifier(chestName), + t0 -> list( + variantHFacing(t0, "type=single,facing=", "builtin:"+chestName+"_center"), + variantHFacing(t0, "type=left,facing=", "builtin:"+chestName+"_left"), + variantHFacing(t0, "type=right,facing=", "builtin:"+chestName+"_right") + ), pack); } public static void addSingleChestOnlyBlockStates(String chestName, EBEPack pack) { - pack.addBlockState( - JState.state( - variantHFacing(JState.variant(), "facing=", "builtin:"+chestName+"_center") - ), new Identifier(chestName) - ); + addBlockState(new Identifier(chestName), + t0 -> list( + variantHFacing(t0, "facing=", "builtin:"+chestName+"_center") + ), pack); + } + + public static void addParentModel(String parent, Identifier id, EBEPack pack) { + pack.addTemplateResource(new Identifier(id.getNamespace(), "models/" + id.getPath() + ".json"), t -> + "{" + kv("parent", parent) + "}"); + } + + public static void addParentTexModel(String parent, String textures, Identifier id, EBEPack pack) { + pack.addTemplateResource(new Identifier(id.getNamespace(), "models/" + id.getPath() + ".json"), t -> + t.load("model/parent_and_tex.json", d -> d.def("parent", parent).def("textures", textures))); } public static void addSignTypeModels(String signType, EBEPack pack) { var signName = signType+"_sign"; var signTex = "entity/signs/"+signType; addRotation16Models( - withSignParticle(new JTextures().var("sign", signTex), signName), + signParticle(signName) + kv("sign", signTex), "block/template_sign", "block/"+signName, ResourceUtil::signAOSuffix, pack); - var hangingTexDef = new JTextures() - .var("sign", "entity/signs/hanging/"+signType) - .var("particle", "block/particle_hanging_sign_"+signType); + var hangingTexDef = list( + kv("sign", "entity/signs/hanging/"+signType), + kv("particle", "block/particle_hanging_sign_"+signType) + ); addRotation16Models(hangingTexDef, "block/template_hanging_sign", "block/"+signType+"_hanging_sign", ResourceUtil::signAOSuffix, pack); addRotation16Models(hangingTexDef, "block/template_hanging_sign_attached", "block/"+signType+"_hanging_sign_attached", ResourceUtil::signAOSuffix, pack); - pack.addModel(JModel.model().parent(signAOSuffix("block/template_wall_sign")) - .textures(withSignParticle(JModel.textures().var("sign", signTex), signName)), new Identifier("block/"+signType+"_wall_sign")); - pack.addModel(JModel.model().parent(signAOSuffix("block/template_wall_hanging_sign")) - .textures(hangingTexDef), new Identifier("block/"+signType+"_wall_hanging_sign")); + addParentTexModel(signAOSuffix("block/template_wall_sign"), + signParticle(signName) + kv("sign", signTex), new Identifier("block/"+signType+"_wall_sign"), pack); + addParentTexModel(signAOSuffix("block/template_wall_hanging_sign"), + hangingTexDef, new Identifier("block/"+signType+"_wall_hanging_sign"), pack); } - public static void addRotation16Models(JTextures textures, String templatePrefix, String modelPrefix, Function suffix, EBEPack pack) { - pack.addModel(JModel.model().parent(suffix.apply(templatePrefix+"_0")).textures(textures), new Identifier(modelPrefix + "_0")); - pack.addModel(JModel.model().parent(suffix.apply(templatePrefix+"_22_5")).textures(textures), new Identifier(modelPrefix + "_22_5")); - pack.addModel(JModel.model().parent(suffix.apply(templatePrefix+"_45")).textures(textures), new Identifier(modelPrefix + "_45")); - pack.addModel(JModel.model().parent(suffix.apply(templatePrefix+"_67_5")).textures(textures), new Identifier(modelPrefix + "_67_5")); + public static void addRotation16Models(String textures, String templatePrefix, String modelPrefix, Function suffix, EBEPack pack) { + addParentTexModel(suffix.apply(templatePrefix+"_0"), textures, new Identifier(modelPrefix + "_0"), pack); + addParentTexModel(suffix.apply(templatePrefix+"_22_5"), textures, new Identifier(modelPrefix + "_22_5"), pack); + addParentTexModel(suffix.apply(templatePrefix+"_45"), textures, new Identifier(modelPrefix + "_45"), pack); + addParentTexModel(suffix.apply(templatePrefix+"_67_5"), textures, new Identifier(modelPrefix + "_67_5"), pack); } private static String signAOSuffix(String model) { @@ -141,71 +201,63 @@ private static String signAOSuffix(String model) { } public static void addSignBlockStates(String signName, String wallSignName, EBEPack pack) { - pack.addBlockState( - JState.state( - variantRotation16(JState.variant(), "rotation=", "block/"+signName) - ), new Identifier(signName) - ); - pack.addBlockState( - JState.state( - variantHFacing(JState.variant(), "facing=", "block/"+wallSignName) - ), new Identifier(wallSignName) - ); + addBlockState(new Identifier(signName), + t -> variantRotation16(t, "rotation=", "block/"+signName), pack); + addBlockState(new Identifier(wallSignName), + t -> variantHFacing(t, "facing=", "block/"+wallSignName), pack); } public static void addHangingSignBlockStates(String signName, String wallSignName, EBEPack pack) { - var variant = JState.variant(); - variantRotation16(variant, "attached=false,rotation=", "block/"+signName); - variantRotation16(variant, "attached=true,rotation=", "block/"+signName+"_attached"); - - pack.addBlockState(JState.state(variant), new Identifier(signName)); - pack.addBlockState( - JState.state( - variantHFacing(JState.variant(), "facing=", "block/"+wallSignName) - ), new Identifier(wallSignName) - ); + addBlockState(new Identifier(signName), + t -> list( + variantRotation16(t, "attached=false,rotation=", "block/"+signName), + variantRotation16(t, "attached=true,rotation=", "block/"+signName+"_attached") + ), pack); + + addBlockState(new Identifier(wallSignName), + t -> variantHFacing(t, "facing=", "block/"+wallSignName), pack); } public static void addBellBlockState(EBEPack pack) { - JVariant variant = JState.variant(); - for (Direction dir : EBEUtil.HORIZONTAL_DIRECTIONS) { - int rot = (int)dir.asRotation() + 90; - variant - .put("attachment=double_wall,facing="+dir.getName(), JState.model("builtin:bell_between_walls").y(rot)) - .put("attachment=ceiling,facing="+dir.getName(), JState.model("builtin:bell_ceiling").y(rot + 90)) // adding 90 here and below to maintain Parity with vanilla's weird choice of rotations - .put("attachment=floor,facing="+dir.getName(), JState.model("builtin:bell_floor").y(rot + 90)) - .put("attachment=single_wall,facing="+dir.getName(), JState.model("builtin:bell_wall").y(rot)) - ; - } - pack.addBlockState(JState.state(variant), new Identifier("bell")); + addBlockState(new Identifier("bell"), + t -> { + var vars = new DelimitedAppender(","); + for (Direction dir : EBEUtil.HORIZONTAL_DIRECTIONS) { + int rot = (int)dir.asRotation() + 90; + vars + .append(variantY(t, "attachment=double_wall,facing="+dir.getName(), "builtin:bell_between_walls", rot)) + .append(variantY(t, "attachment=ceiling,facing="+dir.getName(), "builtin:bell_ceiling", rot + 90)) // adding 90 here and below to maintain Parity with vanilla's weird choice of rotations + .append(variantY(t, "attachment=floor,facing="+dir.getName(), "builtin:bell_floor", rot + 90)) + .append(variantY(t, "attachment=single_wall,facing="+dir.getName(), "builtin:bell_wall", rot)); + } + return vars.get(); + }, pack); } public static void addBedModels(DyeColor bedColor, EBEPack pack) { String color = bedColor.getName(); - pack.addModel( - JModel.model() - .parent(bedAOSuffix("block/template_bed_head")) - .textures(withBedParticle(JModel.textures().var("bed", "entity/bed/" + color), color)), - new Identifier("block/" + color + "_bed_head") - ); - pack.addModel( - JModel.model() - .parent(bedAOSuffix("block/template_bed_foot")) - .textures(withBedParticle(JModel.textures().var("bed", "entity/bed/" + color), color)), - new Identifier("block/" + color + "_bed_foot") - ); + + addParentTexModel(bedAOSuffix("block/template_bed_head"), + bedParticle(color) + kv("bed", "entity/bed/" + color), + new Identifier("block/" + color + "_bed_head"), pack); + addParentTexModel(bedAOSuffix("block/template_bed_foot"), + bedParticle(color) + kv("bed", "entity/bed/" + color), + new Identifier("block/" + color + "_bed_foot"), pack); } public static void addBedBlockState(DyeColor bedColor, EBEPack pack) { String color = bedColor.getName(); - JVariant variant = JState.variant(); - for (Direction dir : EBEUtil.HORIZONTAL_DIRECTIONS) { - int rot = (int)dir.asRotation() + 180; - variant - .put("part=head,facing="+dir.getName(), JState.model("block/" + bedColor + "_bed_head").y(rot)) - .put("part=foot,facing="+dir.getName(), JState.model("block/" + bedColor + "_bed_foot").y(rot)); - } - pack.addBlockState(JState.state(variant), new Identifier(color + "_bed")); + addBlockState(new Identifier(color + "_bed"), + t -> { + var vars = new DelimitedAppender(","); + for (Direction dir : EBEUtil.HORIZONTAL_DIRECTIONS) { + int rot = (int)dir.asRotation() + 180; + vars + .append(variantY(t, "part=head,facing="+dir.getName(), "block/" + bedColor + "_bed_head", rot)) + .append(variantY(t, "part=foot,facing="+dir.getName(), "block/" + bedColor + "_bed_foot", rot)); + } + return vars.get(); + }, pack); } private static String bedAOSuffix(String model) { @@ -217,45 +269,53 @@ public static void addShulkerBoxModels(@Nullable DyeColor color, EBEPack pack) { var texture = color != null ? "entity/shulker/shulker_"+color.getName() : "entity/shulker/shulker"; var shulkerBoxStr = color != null ? color.getName()+"_shulker_box" : "shulker_box"; var particle = "block/"+shulkerBoxStr; - pack.addModel(JModel.model().parent("block/template_shulker_box").textures(JModel.textures().var("shulker", texture).var("particle", particle)), new Identifier("block/"+shulkerBoxStr)); - pack.addModel(JModel.model().parent("block/template_shulker_box_bottom").textures(JModel.textures().var("shulker", texture).var("particle", particle)), new Identifier("block/"+shulkerBoxStr+"_bottom")); - pack.addModel(JModel.model().parent("block/template_shulker_box_lid").textures(JModel.textures().var("shulker", texture).var("particle", particle)), new Identifier("block/"+shulkerBoxStr+"_lid")); + addParentTexModel("block/template_shulker_box", + list(kv("shulker", texture), kv("particle", particle)), + new Identifier("block/"+shulkerBoxStr), pack); + addParentTexModel("block/template_shulker_box_bottom", + list(kv("shulker", texture), kv("particle", particle)), + new Identifier("block/"+shulkerBoxStr+"_bottom"), pack); + addParentTexModel("block/template_shulker_box_lid", + list(kv("shulker", texture), kv("particle", particle)), + new Identifier("block/"+shulkerBoxStr+"_lid"), pack); } public static void addShulkerBoxBlockStates(@Nullable DyeColor color, EBEPack pack) { var shulkerBoxStr = color != null ? color.getName()+"_shulker_box" : "shulker_box"; - var variant = JState.variant() - .put("facing=up", JState.model("builtin:"+shulkerBoxStr)) - .put("facing=down", JState.model("builtin:"+shulkerBoxStr).x(180)); - for (Direction dir : EBEUtil.HORIZONTAL_DIRECTIONS) { - int rot = (int)dir.asRotation() + 180; - variant.put("facing="+dir.getName(), JState.model("builtin:"+shulkerBoxStr).x(90).y(rot)); - } - pack.addBlockState(JState.state(variant), new Identifier(shulkerBoxStr)); + addBlockState(new Identifier(shulkerBoxStr), + t -> { + var vars = new DelimitedAppender(","); + vars + .append(variant(t, "facing=up", "builtin:"+shulkerBoxStr)) + .append(variantXY(t, "facing=down", "builtin:"+shulkerBoxStr, 180, 0)); + for (Direction dir : EBEUtil.HORIZONTAL_DIRECTIONS) { + int rot = (int)dir.asRotation() + 180; + vars.append(variantXY(t, "facing="+dir.getName(), "builtin:"+shulkerBoxStr, 90, rot)); + } + return vars.get(); + }, pack); } public static void addDecoratedPotBlockState(EBEPack pack) { - pack.addBlockState(JState.state(variantHFacing(JState.variant(), "facing=", "builtin:decorated_pot")), new Identifier("decorated_pot")); + addBlockState(new Identifier("decorated_pot"), + t -> variantHFacing(t, "facing=", "builtin:decorated_pot"), pack); } public static void addDecoratedPotPatternModels(RegistryKey patternKey, EBEPack pack) { for (Direction dir : EBEUtil.HORIZONTAL_DIRECTIONS) { - pack.addModel(JModel.model().parent("block/template_pottery_pattern_" + dir.getName()) - .textures( - JModel.textures() - .var("pattern", DecoratedPotPatterns.getTextureId(patternKey).toString()) - ), - new Identifier("block/" + patternKey.getValue().getPath() + "_" + dir.getName()) - ); + addParentTexModel("block/template_pottery_pattern_" + dir.getName(), + kv("pattern", TexturedRenderLayers.getDecoratedPotPatternTextureId(patternKey).getTextureId().toString()), + new Identifier("block/" + patternKey.getValue().getPath() + "_" + dir.getName()), + pack); } } public static void resetBasePack() { - BASE_PACK = new EBEPack(EBEUtil.id("base_resources")); + BASE_PACK = new EBEPack(EBEUtil.id("base_resources"), EnhancedBlockEntities.TEMPLATE_LOADER); } public static void resetTopLevelPack() { - TOP_LEVEL_PACK = new EBEPack(EBEUtil.id("top_level_resources")); + TOP_LEVEL_PACK = new EBEPack(EBEUtil.id("top_level_resources"), EnhancedBlockEntities.TEMPLATE_LOADER); } public static EBEPack getBasePack() { @@ -296,11 +356,31 @@ public static void dumpModAssets(Path dest) throws IOException { } public static void dumpAllPacks(Path dest) throws IOException { - getBasePack().dumpDirect(dest); - getTopLevelPack().dumpDirect(dest); + getBasePack().dump(dest); + getTopLevelPack().dump(dest); dumpModAssets(dest); } + private static class DelimitedAppender { + private final StringBuilder builder = new StringBuilder(); + private final CharSequence delimiter; + + private DelimitedAppender(CharSequence delimiter) { + this.delimiter = delimiter; + } + + public DelimitedAppender append(CharSequence seq) { + if (!this.builder.isEmpty()) this.builder.append(this.delimiter); + + this.builder.append(seq); + return this; + } + + public String get() { + return this.builder.toString(); + } + } + static { resetBasePack(); resetTopLevelPack(); diff --git a/src/main/java/foundationgames/enhancedblockentities/util/WorldUtil.java b/src/main/java/foundationgames/enhancedblockentities/util/WorldUtil.java index 62485674..6d3c4365 100644 --- a/src/main/java/foundationgames/enhancedblockentities/util/WorldUtil.java +++ b/src/main/java/foundationgames/enhancedblockentities/util/WorldUtil.java @@ -1,20 +1,51 @@ package foundationgames.enhancedblockentities.util; -import foundationgames.enhancedblockentities.EnhancedBlockEntities; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.registry.RegistryKey; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkSectionPos; import net.minecraft.world.World; -public enum WorldUtil {; - public static boolean FORCE_SYNCHRONOUS_CHUNK_REBUILD = false; +import java.util.HashMap; +import java.util.Map; - public static void rebuildChunkSynchronously(World world, BlockPos pos, boolean forceSync) { - var bState = world.getBlockState(pos); - try { - WorldUtil.FORCE_SYNCHRONOUS_CHUNK_REBUILD = forceSync; - MinecraftClient.getInstance().worldRenderer.updateBlock(world, pos, bState, bState, 8); - } catch (NullPointerException ignored) { - EnhancedBlockEntities.LOG.warn("Error rebuilding chunk at block pos "+pos); +public enum WorldUtil implements ClientTickEvents.EndWorldTick { + EVENT_LISTENER; + + public static final Map CHUNK_UPDATE_TASKS = new HashMap<>(); + private static final Map, Long2ObjectMap> TIMED_TASKS = new HashMap<>(); + + public static void rebuildChunk(World world, BlockPos pos) { + var state = world.getBlockState(pos); + MinecraftClient.getInstance().worldRenderer.updateBlock(world, pos, state, state, 8); + } + + public static void rebuildChunkAndThen(World world, BlockPos pos, Runnable action) { + CHUNK_UPDATE_TASKS.computeIfAbsent(ChunkSectionPos.from(pos), k -> new ExecutableRunnableHashSet()).add(action); + rebuildChunk(world, pos); + } + + public static void scheduleTimed(World world, long time, Runnable action) { + TIMED_TASKS.computeIfAbsent(world.getRegistryKey(), k -> new Long2ObjectOpenHashMap<>()).put(time, action); + } + + @Override + public void onEndTick(ClientWorld world) { + var key = world.getRegistryKey(); + + if (TIMED_TASKS.containsKey(key)) { + TIMED_TASKS.get(key).long2ObjectEntrySet().removeIf(entry -> { + if (world.getTime() >= entry.getLongKey()) { + entry.getValue().run(); + return true; + } + + return false; + }); } } } diff --git a/src/main/java/foundationgames/enhancedblockentities/util/duck/AppearanceStateHolder.java b/src/main/java/foundationgames/enhancedblockentities/util/duck/AppearanceStateHolder.java new file mode 100644 index 00000000..e0d8ddc2 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/util/duck/AppearanceStateHolder.java @@ -0,0 +1,24 @@ +package foundationgames.enhancedblockentities.util.duck; + +import foundationgames.enhancedblockentities.util.WorldUtil; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public interface AppearanceStateHolder { + int getModelState(); + + void setModelState(int state); + + int getRenderState(); + + void setRenderState(int state); + + default void updateAppearanceState(int state, World world, BlockPos pos) { + if (!world.isClient()) { + return; + } + + this.setModelState(state); + WorldUtil.rebuildChunkAndThen(world, pos, () -> this.setRenderState(state)); + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/util/duck/BakedModelManagerAccess.java b/src/main/java/foundationgames/enhancedblockentities/util/duck/BakedModelManagerAccess.java deleted file mode 100644 index 509312df..00000000 --- a/src/main/java/foundationgames/enhancedblockentities/util/duck/BakedModelManagerAccess.java +++ /dev/null @@ -1,8 +0,0 @@ -package foundationgames.enhancedblockentities.util.duck; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.util.Identifier; - -public interface BakedModelManagerAccess { - BakedModel getModel(Identifier id); -} diff --git a/src/main/java/foundationgames/enhancedblockentities/util/duck/ChunkRebuildTaskAccess.java b/src/main/java/foundationgames/enhancedblockentities/util/duck/ChunkRebuildTaskAccess.java new file mode 100644 index 00000000..e72114f3 --- /dev/null +++ b/src/main/java/foundationgames/enhancedblockentities/util/duck/ChunkRebuildTaskAccess.java @@ -0,0 +1,17 @@ +package foundationgames.enhancedblockentities.util.duck; + +public interface ChunkRebuildTaskAccess { + Runnable enhanced_bes$getTaskAfterRebuild(); + + void enhanced_bes$setTaskAfterRebuild(Runnable task); + + default void enhanced_bes$runAfterRebuildTask() { + var task = this.enhanced_bes$getTaskAfterRebuild(); + + if (task != null) { + task.run(); + + this.enhanced_bes$setTaskAfterRebuild(null); + } + } +} diff --git a/src/main/java/foundationgames/enhancedblockentities/util/duck/ModelStateHolder.java b/src/main/java/foundationgames/enhancedblockentities/util/duck/ModelStateHolder.java deleted file mode 100644 index 8dddf70d..00000000 --- a/src/main/java/foundationgames/enhancedblockentities/util/duck/ModelStateHolder.java +++ /dev/null @@ -1,20 +0,0 @@ -package foundationgames.enhancedblockentities.util.duck; - -import foundationgames.enhancedblockentities.util.WorldUtil; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public interface ModelStateHolder { - int getModelState(); - - void applyModelState(int state); - - default void setModelState(int state, World world, BlockPos pos) { - if (!world.isClient()) { - return; - } - - this.applyModelState(state); - WorldUtil.rebuildChunkSynchronously(world, pos, true); - } -} diff --git a/src/main/java/foundationgames/enhancedblockentities/util/hacks/ResourceHacks.java b/src/main/java/foundationgames/enhancedblockentities/util/hacks/ResourceHacks.java index fa303463..e866f36b 100644 --- a/src/main/java/foundationgames/enhancedblockentities/util/hacks/ResourceHacks.java +++ b/src/main/java/foundationgames/enhancedblockentities/util/hacks/ResourceHacks.java @@ -2,7 +2,6 @@ import foundationgames.enhancedblockentities.client.resource.EBEPack; import net.minecraft.resource.ResourceManager; -import net.minecraft.resource.ResourceType; import net.minecraft.util.Identifier; import java.io.IOException; @@ -19,7 +18,7 @@ private static void cropAndPutTexture(Identifier source, Identifier result, Reso } if (image == null) return; - TextureHacks.cropImage(image, u0, v0, u1, v1).ifPresent(imgBytes -> pack.addResource(ResourceType.CLIENT_RESOURCES, result, imgBytes)); + TextureHacks.cropImage(image, u0, v0, u1, v1).ifPresent(imgBytes -> pack.addResource(result, imgBytes)); image.close(); } diff --git a/src/main/resources/enhancedblockentities.accesswidener b/src/main/resources/enhancedblockentities.accesswidener index 8471e1df..38989dda 100644 --- a/src/main/resources/enhancedblockentities.accesswidener +++ b/src/main/resources/enhancedblockentities.accesswidener @@ -2,3 +2,5 @@ accessWidener v2 named accessible class net/minecraft/client/option/SimpleOption$Callbacks accessible class net/minecraft/client/render/model/BakedModelManager$BakingResult + +accessible field net/minecraft/block/DecoratedPotPatterns DECORATED_POT_SIDE_KEY Lnet/minecraft/registry/RegistryKey; diff --git a/src/main/resources/enhancedblockentities.mixins.json b/src/main/resources/enhancedblockentities.mixins.json index 3b91494a..e4b9215f 100644 --- a/src/main/resources/enhancedblockentities.mixins.json +++ b/src/main/resources/enhancedblockentities.mixins.json @@ -5,19 +5,23 @@ "compatibilityLevel": "JAVA_17", "client": [ "AbstractBlockStateMixin", - "BakedModelManagerMixin", "BellBlockEntityMixin", "BlockEntityRenderDispatcherMixin", + "BuiltChunkMixin", "BuiltinModelItemRendererMixin", "ChestBlockEntityMixin", + "ClickableWidgetAccessor", "DecoratedPotBlockEntityMixin", "EnderChestBlockEntityMixin", "LifecycledResourceManagerImplMixin", + "MinecraftClientMixin", "ShulkerBoxBlockEntityMixin", "SignBlockEntityRenderAccessor", "SignEditScreenMixin", "VideoOptionsScreenMixin", - "WorldRendererMixin" + "WorldRendererMixin", + "compat.sodium.RenderSectionManagerMixin", + "compat.sodium.RenderSectionMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 33e98359..b1769909 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -24,9 +24,6 @@ ], "modmenu": [ "foundationgames.enhancedblockentities.config.gui.EBEModMenuPlugin" - ], - "dashloader": [ - "foundationgames.enhancedblockentities.compat.dashloader.EBEDashLoader" ] }, "mixins": [ @@ -35,7 +32,7 @@ "depends": { "fabricloader": ">=0.7.4", - "fabric": "*", + "fabric-api": "*", "minecraft": ">=1.20" }, "breaks": { @@ -45,9 +42,6 @@ "accessWidener": "enhancedblockentities.accesswidener", "custom": { - "dashloader:dashobject": [ - "foundationgames.enhancedblockentities.compat.dashloader.DashDynamicBakedModel" - ], "modmenu": { "links": { "modmenu.discord": "https://discord.gg/7Aw3y4RtY9" diff --git a/src/main/resources/templates/blockstate/base.json b/src/main/resources/templates/blockstate/base.json new file mode 100644 index 00000000..db0e7b03 --- /dev/null +++ b/src/main/resources/templates/blockstate/base.json @@ -0,0 +1,5 @@ +{ + "variants": { + ![vars] + } +} \ No newline at end of file diff --git a/src/main/resources/templates/blockstate/var.json b/src/main/resources/templates/blockstate/var.json new file mode 100644 index 00000000..c58c587d --- /dev/null +++ b/src/main/resources/templates/blockstate/var.json @@ -0,0 +1 @@ +"![state]": {![extra]"model": "![model]"} \ No newline at end of file diff --git a/src/main/resources/templates/chest_item_model.json b/src/main/resources/templates/chest_item_model.json new file mode 100644 index 00000000..a4cc2f6c --- /dev/null +++ b/src/main/resources/templates/chest_item_model.json @@ -0,0 +1 @@ +{"parent":"block/![chest]","overrides":[{"predicate":{"ebe:is_christmas":1},"model": "item/christmas_chest"}]} \ No newline at end of file diff --git a/src/main/resources/templates/model/chest_like.json b/src/main/resources/templates/model/chest_like.json new file mode 100644 index 00000000..2826e974 --- /dev/null +++ b/src/main/resources/templates/model/chest_like.json @@ -0,0 +1,7 @@ +{ + "parent": "block/![parent]", + "textures": { + ![particle] + "chest": "entity/chest/![chest_tex]" + } +} \ No newline at end of file diff --git a/src/main/resources/templates/model/parent_and_tex.json b/src/main/resources/templates/model/parent_and_tex.json new file mode 100644 index 00000000..b24028b7 --- /dev/null +++ b/src/main/resources/templates/model/parent_and_tex.json @@ -0,0 +1,6 @@ +{ + "parent": "![parent]", + "textures": { + ![textures] + } +} \ No newline at end of file