diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/BuiltInBlockModelsCallback.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/BuiltInBlockModelsCallback.java new file mode 100644 index 0000000000..165d454bd2 --- /dev/null +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/api/client/rendering/v1/BuiltInBlockModelsCallback.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.rendering.v1; + +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.renderer.block.BuiltInBlockModels; +import net.minecraft.client.renderer.block.model.BlockModel; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +/** + * Called when custom {@link BlockModel.Unbaked BlockModels} are registered in + * {@link BuiltInBlockModels#createBlockModels(BlockColors)}. + * + *

This allows for overriding block models which eventually end up being used in + * {@link net.minecraft.client.renderer.block.BlockModelResolver}. + */ +public interface BuiltInBlockModelsCallback { + Event EVENT = EventFactory.createArrayBacked( + BuiltInBlockModelsCallback.class, + listeners -> builder -> { + for (BuiltInBlockModelsCallback listener : listeners) { + listener.createBlockModels(builder); + } + }); + + /** + * @param builder the block models builder instance + */ + void createBlockModels(BuiltInBlockModels.Builder builder); +} diff --git a/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/BuiltInBlockModelsMixin.java b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/BuiltInBlockModelsMixin.java new file mode 100644 index 0000000000..77d9108390 --- /dev/null +++ b/fabric-rendering-v1/src/client/java/net/fabricmc/fabric/mixin/client/rendering/BuiltInBlockModelsMixin.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.client.rendering; + +import java.util.Map; + +import com.llamalad7.mixinextras.sugar.Local; +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 net.minecraft.client.renderer.block.BuiltInBlockModels; +import net.minecraft.client.renderer.block.model.BlockModel; +import net.minecraft.world.level.block.state.BlockState; + +import net.fabricmc.fabric.api.client.rendering.v1.BuiltInBlockModelsCallback; + +@Mixin(BuiltInBlockModels.class) +abstract class BuiltInBlockModelsMixin { + @Inject(method = "createBlockModels", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/block/BuiltInBlockModels$Builder;build()Ljava/util/Map;")) + private static void createBlockModels(CallbackInfoReturnable> callback, @Local BuiltInBlockModels.Builder builder) { + BuiltInBlockModelsCallback.EVENT.invoker().createBlockModels(builder); + } +} diff --git a/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json b/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json index fef8f1dd1f..b120569799 100644 --- a/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json +++ b/fabric-rendering-v1/src/client/resources/fabric-rendering-v1.mixins.json @@ -7,6 +7,7 @@ "AtlasManagerMixin", "BlockColorsMixin", "BlockEntityRenderersMixin", + "BuiltInBlockModelsMixin", "CapeLayerMixin", "ClientLevelMixin", "ClientTooltipComponentMixin", diff --git a/fabric-rendering-v1/src/testmod/resources/fabric.mod.json b/fabric-rendering-v1/src/testmod/resources/fabric.mod.json index 0af1e25ff7..b4bb40148d 100644 --- a/fabric-rendering-v1/src/testmod/resources/fabric.mod.json +++ b/fabric-rendering-v1/src/testmod/resources/fabric.mod.json @@ -16,6 +16,7 @@ "net.fabricmc.fabric.test.rendering.client.AdvancementRenderingTests", "net.fabricmc.fabric.test.rendering.client.AtlasTests", "net.fabricmc.fabric.test.rendering.client.ArmorRenderingTests", + "net.fabricmc.fabric.test.rendering.client.BuiltInBlockModelsTest", "net.fabricmc.fabric.test.rendering.client.CustomSpriteSourcesTest", "net.fabricmc.fabric.test.rendering.client.CustomColorResolverTest", "net.fabricmc.fabric.test.rendering.client.DebugOptionsTests", diff --git a/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/BuiltInBlockModelsTest.java b/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/BuiltInBlockModelsTest.java new file mode 100644 index 0000000000..b3f32e8ea5 --- /dev/null +++ b/fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client/BuiltInBlockModelsTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.rendering.client; + +import net.minecraft.client.renderer.block.BuiltInBlockModels; +import net.minecraft.world.level.block.Blocks; + +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.rendering.v1.BuiltInBlockModelsCallback; + +public class BuiltInBlockModelsTest implements ClientModInitializer { + @Override + public void onInitializeClient() { + BuiltInBlockModelsCallback.EVENT.register(builder -> { + // Overrides the yellow shulker box built-in block model with an empty one. + // This can be tested in-game e.g., by checking out a minecart with that block. + // summon minecraft:minecart ~ ~ ~ {DisplayState:{Name:"minecraft:yellow_shulker_box"}} + BuiltInBlockModels.createAir(builder, Blocks.DYED_SHULKER_BOX.yellow()); + }); + } +} diff --git a/fabric-transitive-access-wideners-v1/build.gradle b/fabric-transitive-access-wideners-v1/build.gradle index 76d5f1e57b..343c4e4103 100644 --- a/fabric-transitive-access-wideners-v1/build.gradle +++ b/fabric-transitive-access-wideners-v1/build.gradle @@ -49,6 +49,8 @@ tasks.register('generateClassTweaker') { FileSystems.newFileSystem(URI.create("jar:${clientJar.toUri()}"), [create: false]).withCloseable { fs -> generateRenderPipelinesFields(lines, fs) + lines.add("") + generateBuiltInBlockModelsMethods(lines, fs) } file('src/main/resources/fabric-transitive-access-wideners-v1.classtweaker').text = String.join('\n', lines) + '\n' @@ -191,12 +193,30 @@ def generateEnchantmentMethods(List lines, FileSystem fs) { } } } + lines.add('transitive-accessible class net/minecraft/world/item/enchantment/EnchantmentHelper$EnchantmentVisitor') lines.add('transitive-accessible class net/minecraft/world/item/enchantment/EnchantmentHelper$EnchantmentInSlotVisitor') lines.add('transitive-accessible class net/minecraft/world/item/enchantment/Enchantment$GenericAction') lines.add('transitive-accessible class net/minecraft/world/item/enchantment/Enchantment$FloatAction') } +def generateBuiltInBlockModelsMethods(List lines, FileSystem fs) { + lines.add("# Private methods of BuiltInBlockModels and BuiltInBlockModels\$Builder") + + for (def node : [ loadClass(fs.getPath("net/minecraft/client/renderer/block/BuiltInBlockModels.class")), loadClass(fs.getPath("net/minecraft/client/renderer/block/BuiltInBlockModels\$Builder.class")) ]) { + for (def method : node.methods) { + // Every method can be useful + if ((method.access & Opcodes.ACC_PRIVATE) != 0 && !method.name.startsWith("lambda\$")) { + lines.add("transitive-accessible method $node.name $method.name $method.desc") + } + } + } + + lines.add('transitive-accessible class net/minecraft/client/renderer/block/BuiltInBlockModels$Builder') + lines.add('transitive-accessible class net/minecraft/client/renderer/block/BuiltInBlockModels$ModelFactory') + lines.add('transitive-accessible class net/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory') +} + ClassNode loadClass(Path path) { def node = new ClassNode() diff --git a/fabric-transitive-access-wideners-v1/src/main/resources/fabric-transitive-access-wideners-v1.classtweaker b/fabric-transitive-access-wideners-v1/src/main/resources/fabric-transitive-access-wideners-v1.classtweaker index 1290ec1391..b63ac2fe36 100644 --- a/fabric-transitive-access-wideners-v1/src/main/resources/fabric-transitive-access-wideners-v1.classtweaker +++ b/fabric-transitive-access-wideners-v1/src/main/resources/fabric-transitive-access-wideners-v1.classtweaker @@ -413,3 +413,37 @@ transitive-accessible field net/minecraft/client/renderer/RenderPipelines GUI_TE transitive-accessible field net/minecraft/client/renderer/RenderPipelines GUI_TEXT_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet; transitive-accessible field net/minecraft/client/renderer/RenderPipelines OUTLINE_SNIPPET Lcom/mojang/blaze3d/pipeline/RenderPipeline$Snippet; transitive-accessible method net/minecraft/client/renderer/RenderPipelines register (Lcom/mojang/blaze3d/pipeline/RenderPipeline;)Lcom/mojang/blaze3d/pipeline/RenderPipeline; + +# Private methods of BuiltInBlockModels and BuiltInBlockModels$Builder +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels addDefaults (Lnet/minecraft/client/renderer/block/BuiltInBlockModels$Builder;)V +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createAir (Lnet/minecraft/client/renderer/block/BuiltInBlockModels$Builder;Lnet/minecraft/world/level/block/Block;)V +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels special (Lnet/minecraft/client/renderer/special/SpecialModelRenderer$Unbaked;)Lnet/minecraft/client/renderer/block/model/BlockModel$Unbaked; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels special (Lnet/minecraft/client/renderer/special/SpecialModelRenderer$Unbaked;Lcom/mojang/math/Transformation;)Lnet/minecraft/client/renderer/block/model/BlockModel$Unbaked; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createMobHead (Lnet/minecraft/world/level/block/SkullBlock$Types;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createMobWallHead (Lnet/minecraft/world/level/block/SkullBlock$Types;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createMobHeads (Lnet/minecraft/client/renderer/block/BuiltInBlockModels$Builder;Lnet/minecraft/world/level/block/SkullBlock$Types;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/level/block/Block;)V +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createPlayerHead ()Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createPlayerWallHead ()Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createBanner (Lnet/minecraft/world/item/DyeColor;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createWallBanner (Lnet/minecraft/world/item/DyeColor;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createShulkerBox ()Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createDyedShulkerBox (Lnet/minecraft/world/item/DyeColor;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createChest (Lnet/minecraft/resources/Identifier;Lnet/minecraft/world/level/block/state/properties/ChestType;Lnet/minecraft/core/Direction;)Lnet/minecraft/client/renderer/block/model/BlockModel$Unbaked; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createSingletonChest (Lnet/minecraft/resources/Identifier;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createChest (Lnet/minecraft/client/renderer/MultiblockChestResources;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createXmasChest (Lnet/minecraft/client/renderer/MultiblockChestResources;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createCopperGolem (Lnet/minecraft/world/level/block/WeatheringCopper$WeatherState;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createDecoratedPot ()Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createBlockStateModelWrapper (Lnet/minecraft/client/color/block/BlockColors;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/BlockStateModelWrapper$Unbaked; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels combineSpecialAndBlockModels (Lnet/minecraft/client/renderer/block/model/BlockModel$Unbaked;Lnet/minecraft/client/color/block/BlockColors;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/model/CompositeBlockModel$Unbaked; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createFlowerBedModel (Lnet/minecraft/client/color/block/BlockColors;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/client/renderer/block/SelectBlockModel$Unbaked; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels createEnchantingTable ()Lnet/minecraft/client/renderer/block/model/BlockModel$Unbaked; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels specialModelWithPropertyDispatch (Lnet/minecraft/world/level/block/state/properties/Property;Ljava/util/function/Function;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels specialModelWithPropertyDispatch (Lnet/minecraft/world/level/block/state/properties/Property;Lnet/minecraft/world/level/block/state/properties/Property;Ljava/util/function/BiFunction;)Lnet/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory; +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels$Builder (Lnet/minecraft/client/color/block/BlockColors;)V +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels$Builder put (Lnet/minecraft/client/renderer/block/BuiltInBlockModels$ModelFactory;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/level/block/Block;)V +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels$Builder put (Lnet/minecraft/client/renderer/block/model/BlockModel$Unbaked;Lnet/minecraft/world/level/block/Block;)V +transitive-accessible method net/minecraft/client/renderer/block/BuiltInBlockModels$Builder put (Lnet/minecraft/client/renderer/block/BuiltInBlockModels$ModelFactory;Lnet/minecraft/world/level/block/Block;)V +transitive-accessible class net/minecraft/client/renderer/block/BuiltInBlockModels$Builder +transitive-accessible class net/minecraft/client/renderer/block/BuiltInBlockModels$ModelFactory +transitive-accessible class net/minecraft/client/renderer/block/BuiltInBlockModels$SpecialModelFactory