Create a simple renderer api testmod (#1295)

* Create a simple renderer api testmod

* Update fabric-renderer-api-v1/src/testmod/java/net/fabricmc/fabric/test/renderer/simple/client/RendererClientTest.java

Co-authored-by: liach <7806504+liach@users.noreply.github.com>

Co-authored-by: liach <7806504+liach@users.noreply.github.com>
This commit is contained in:
i509VCB 2021-04-14 12:40:42 -05:00 committed by GitHub
parent 6d5e24549f
commit b0e4dde51b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 756 additions and 0 deletions

View file

@ -4,3 +4,11 @@ version = getSubprojectVersion(project, "0.4.1")
moduleDependencies(project, [
'fabric-api-base'
])
dependencies {
testmodCompile project(path: ':fabric-blockrenderlayer-v1', configuration: 'dev')
testmodCompile project(path: ':fabric-models-v0', configuration: 'dev')
testmodCompile project(path: ':fabric-networking-blockentity-v0', configuration: 'dev')
testmodCompile project(path: ':fabric-object-builder-api-v1', configuration: 'dev')
testmodCompile project(path: ':fabric-rendering-data-attachment-v1', configuration: 'dev')
}

View file

@ -0,0 +1,31 @@
/*
* 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.renderer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* Extension interface for a world to notify the world that a block needs to be re-rendered.
*/
public interface WorldRenderExtensions {
static void scheduleBlockRerender(World world, BlockPos pos) {
((WorldRenderExtensions) world).scheduleBlockRerender(pos);
}
void scheduleBlockRerender(BlockPos pos);
}

View file

@ -0,0 +1,38 @@
/*
* 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.renderer.mixin;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;
@Mixin(ClientWorld.class)
abstract class ClientWorldMixin extends WorldMixin {
@Shadow
@Final
private WorldRenderer worldRenderer;
@Override
public void scheduleBlockRerender(BlockPos pos) {
// Update the block at the position to trigger chunk re-render.
this.worldRenderer.updateBlock(null, pos, null, null, 0);
}
}

View file

@ -0,0 +1,32 @@
/*
* 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.renderer.mixin;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.fabricmc.fabric.test.renderer.WorldRenderExtensions;
@Mixin(World.class)
abstract class WorldMixin implements WorldRenderExtensions {
@Override
public void scheduleBlockRerender(BlockPos pos) {
// Do nothing, the client world will do things here
}
}

View file

@ -0,0 +1,26 @@
/*
* 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.
*/
/**
* The testmod for the Fabric Renderer API.
* Right now there is only one test here, but more tests may come to exist in the future.
* These tests are used to validate Indigo's implementation is correct, but these tests may also be useful for other implementations of the Fabric Renderer API.
*
* <p>Right now there is a simple test in the {@code simple} package which validates that simple meshes and quad emitters function.
* Future tests may look into testing things such as render materials or creating more advanced models.
*/
package net.fabricmc.fabric.test.renderer;

View file

@ -0,0 +1,92 @@
/*
* 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.renderer.simple;
import org.jetbrains.annotations.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
public final class FrameBlock extends Block implements BlockEntityProvider {
public FrameBlock(Settings settings) {
super(settings);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (world.isClient()) {
return ActionResult.PASS;
}
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof FrameBlockEntity) {
ItemStack stack = player.getStackInHand(hand);
Block handBlock = Block.getBlockFromItem(stack.getItem());
@Nullable
Block currentBlock = ((FrameBlockEntity) blockEntity).getBlock();
if (stack.isEmpty()) {
// Try to remove if the stack in hand is empty
if (currentBlock != null) {
player.inventory.offerOrDrop(world, new ItemStack(currentBlock));
((FrameBlockEntity) blockEntity).setBlock(null);
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
// getBlockFromItem will return air if we do not have a block item in hand
if (handBlock.is(Blocks.AIR)) {
return ActionResult.FAIL;
}
// Do not allow blocks that may have a block entity
if (handBlock.hasBlockEntity()) {
return ActionResult.FAIL;
}
if (currentBlock != null) {
player.inventory.offerOrDrop(world, new ItemStack(currentBlock));
}
((FrameBlockEntity) blockEntity).setBlock(handBlock);
return ActionResult.SUCCESS;
}
return ActionResult.FAIL;
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockView world) {
return new FrameBlockEntity();
}
}

View file

@ -0,0 +1,107 @@
/*
* 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.renderer.simple;
import org.jetbrains.annotations.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity;
import net.fabricmc.fabric.api.util.NbtType;
import net.fabricmc.fabric.test.renderer.WorldRenderExtensions;
public final class FrameBlockEntity extends BlockEntity implements RenderAttachmentBlockEntity, BlockEntityClientSerializable {
@Nullable
private Block block = null;
public FrameBlockEntity() {
super(RendererTest.FRAME_BLOCK_ENTITY);
}
@Override
public void fromTag(BlockState state, CompoundTag tag) {
super.fromTag(state, tag);
if (tag.contains("block", NbtType.STRING)) {
this.block = Registry.BLOCK.get(new Identifier(tag.getString("block")));
}
}
@Override
public CompoundTag toTag(CompoundTag tag) {
if (this.block != null) {
tag.putString("block", Registry.BLOCK.getId(this.block).toString());
}
return super.toTag(tag);
}
@Override
public void markDirty() {
super.markDirty();
if (this.hasWorld() && !this.getWorld().isClient()) {
this.sync();
}
}
@Nullable
public Block getBlock() {
return this.block;
}
public void setBlock(@Nullable Block block) {
this.block = block;
this.markDirty();
}
@Nullable
@Override
public Block getRenderAttachmentData() {
return this.block;
}
@Override
public void fromClientTag(CompoundTag tag) {
System.out.println("Recieved sync packet");
if (tag.contains("block", NbtType.STRING)) {
this.block = Registry.BLOCK.get(new Identifier(tag.getString("block")));
} else {
this.block = null;
}
if (this.getWorld() != null) {
WorldRenderExtensions.scheduleBlockRerender(this.getWorld(), this.getPos());
}
}
@Override
public CompoundTag toClientTag(CompoundTag tag) {
if (this.block != null) {
tag.putString("block", Registry.BLOCK.getId(this.block).toString());
}
return tag;
}
}

View file

@ -0,0 +1,44 @@
/*
* 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.renderer.simple;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
/**
* A simple testmod that renders a simple block rendered using the fabric renderer api.
* The block that is rendered is a simple frame that another block is rendered in.
* Blocks that provide a block entity cannot be placed inside the frame.
*
* <p>There are no fancy shaders or glow that is provided by this renderer test.
*/
public final class RendererTest implements ModInitializer {
public static final Block FRAME = new FrameBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).nonOpaque());
public static final BlockEntityType<FrameBlockEntity> FRAME_BLOCK_ENTITY = BlockEntityType.Builder.create(FrameBlockEntity::new, FRAME).build(null);
@Override
public void onInitialize() {
Registry.register(Registry.BLOCK, new Identifier("fabric-renderer-api-v1-testmod", "frame"), FRAME);
Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier("fabric-renderer-api-v1-testmod", "frame"), FRAME_BLOCK_ENTITY);
}
}

View file

@ -0,0 +1,138 @@
/*
* 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.renderer.simple.client;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
final class FrameBakedModel implements BakedModel, FabricBakedModel {
private final Mesh frameMesh;
private final Sprite frameSprite;
FrameBakedModel(Mesh frameMesh, Sprite frameSprite) {
this.frameMesh = frameMesh;
this.frameSprite = frameSprite;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
return Collections.emptyList(); // Renderer API makes this obsolete, so return no quads
}
@Override
public boolean useAmbientOcclusion() {
return true; // we want the block to have a shadow depending on the adjacent blocks
}
@Override
public boolean hasDepth() {
return false;
}
@Override
public boolean isSideLit() {
return false;
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public Sprite getSprite() {
return this.frameSprite;
}
@Override
public ModelTransformation getTransformation() {
return ModelTransformation.NONE;
}
@Override
public ModelOverrideList getOverrides() {
return ModelOverrideList.EMPTY;
}
@Override
public boolean isVanillaAdapter() {
return false;
}
@Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
// Emit our frame mesh
context.meshConsumer().accept(this.frameMesh);
RenderAttachedBlockView renderAttachedBlockView = (RenderAttachedBlockView) blockView;
// We cannot access the block entity from here. We should instead use the immutable render attachments provided by the block entity.
@Nullable
Block data = (Block) renderAttachedBlockView.getBlockEntityRenderAttachment(pos);
if (data == null) {
return; // No inner block to render
}
Sprite sprite = MinecraftClient.getInstance().getBlockRenderManager().getModels().getModelManager().getBlockModels().getSprite(data.getDefaultState());
QuadEmitter emitter = context.getEmitter();
// We can emit our quads outside of the mesh as the block being put in the frame is very much dynamic.
// Emit the quads for each face of the block inside the frame
for (Direction direction : Direction.values()) {
// Add a face, with an inset to give the appearance of the block being in a frame.
emitter.square(direction, 0.1F, 0.1F, 0.9F, 0.9F, 0.1F)
// Set the sprite of the fact, use whole texture via BAKE_LOCK_UV
.spriteBake(0, sprite, MutableQuadView.BAKE_LOCK_UV)
// Allow textures
// TODO: the magic values here are not documented at all and probably should be
.spriteColor(0, -1, -1, -1, -1)
// Emit the quad
.emit();
}
}
@Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
// TODO: Implement an item test.
// For now we will just leave this as I have not added a block item yet
}
}

View file

@ -0,0 +1,43 @@
/*
* 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.renderer.simple.client;
import org.jetbrains.annotations.Nullable;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.client.model.ModelProviderContext;
import net.fabricmc.fabric.api.client.model.ModelProviderException;
import net.fabricmc.fabric.api.client.model.ModelResourceProvider;
/**
* Provides the unbaked model for use with the frame block.
*/
final class FrameModelResourceProvider implements ModelResourceProvider {
private static final Identifier FRAME_MODEL_ID = new Identifier("fabric-renderer-api-v1-testmod", "block/frame");
@Nullable
@Override
public UnbakedModel loadModelResource(Identifier resourceId, ModelProviderContext context) throws ModelProviderException {
if (resourceId.equals(FRAME_MODEL_ID)) {
return new FrameUnbakedModel();
}
return null;
}
}

View file

@ -0,0 +1,123 @@
/*
* 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.renderer.simple.client;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import org.jetbrains.annotations.Nullable;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
final class FrameUnbakedModel implements UnbakedModel {
FrameUnbakedModel() {
}
@Override
public Collection<Identifier> getModelDependencies() {
return Collections.emptySet();
}
@Override
public Collection<SpriteIdentifier> getTextureDependencies(Function<Identifier, UnbakedModel> unbakedModelGetter, Set<Pair<String, String>> unresolvedTextureReferences) {
return Collections.emptySet(); // TODO: Also set the return value when we set a proper texture.
}
/*
* Bake the model.
* In this case we can prebake the frame into a mesh, but will render the contained block when we draw the quads.
*/
@Nullable
@Override
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
// The renderer api may not have an implementation.
// For this reason we will just null check the renderer impl
if (RendererAccess.INSTANCE.hasRenderer()) {
Renderer renderer = RendererAccess.INSTANCE.getRenderer();
MeshBuilder builder = renderer.meshBuilder();
QuadEmitter emitter = builder.getEmitter();
// TODO: Just some random texture to get a missing texture, we should get a proper texture soon
Sprite frameSprite = textureGetter.apply(new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier("foo:foo")));
for (Direction direction : Direction.values()) {
// Draw outer frame
emitter.square(direction, 0.0F, 0.9F, 0.9F, 1.0F, 0.0F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
emitter.square(direction, 0.0F, 0.0F, 0.1F, 0.9F, 0.0F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
emitter.square(direction, 0.9F, 0.1F, 1.0F, 1.0F, 0.0F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
emitter.square(direction, 0.1F, 0.0F, 1.0F, 0.1F, 0.0F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
// Draw inner frame - inset by 0.9 so the frame looks like an actual mesh
emitter.square(direction, 0.0F, 0.9F, 0.9F, 1.0F, 0.9F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
emitter.square(direction, 0.0F, 0.0F, 0.1F, 0.9F, 0.9F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
emitter.square(direction, 0.9F, 0.1F, 1.0F, 1.0F, 0.9F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
emitter.square(direction, 0.1F, 0.0F, 1.0F, 0.1F, 0.9F)
.spriteBake(0, frameSprite, MutableQuadView.BAKE_LOCK_UV)
.spriteColor(0, -1, -1, -1, -1)
.emit();
}
return new FrameBakedModel(builder.build(), frameSprite);
}
// No renderer implementation is present.
return null;
}
}

View file

@ -0,0 +1,32 @@
/*
* 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.renderer.simple.client;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.test.renderer.simple.RendererTest;
public final class RendererClientTest implements ClientModInitializer {
@Override
public void onInitializeClient() {
ModelLoadingRegistry.INSTANCE.registerResourceProvider(manager -> new FrameModelResourceProvider());
BlockRenderLayerMap.INSTANCE.putBlock(RendererTest.FRAME, RenderLayer.getCutoutMipped());
}
}

View file

@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "fabric-renderer-api-v1-testmod:block/frame" }
}
}

View file

@ -0,0 +1,14 @@
{
"required": true,
"package": "net.fabricmc.fabric.test.renderer.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"WorldMixin"
],
"client": [
"ClientWorldMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View file

@ -0,0 +1,23 @@
{
"schemaVersion": 1,
"id": "fabric-renderer-api-v1-testmod",
"name": "Fabric Renderer API (v1) Test Mod",
"version": "1.0.0",
"environment": "*",
"license": "Apache-2.0",
"depends": {
"fabric-renderer-api-v1":"*",
"fabric-resource-loader-v0": "*"
},
"entrypoints": {
"main": [
"net.fabricmc.fabric.test.renderer.simple.RendererTest"
],
"client": [
"net.fabricmc.fabric.test.renderer.simple.client.RendererClientTest"
]
},
"mixins": [
"fabric-renderer-api-v1-testmod.mixins.json"
]
}