mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-26 17:46:25 -05:00
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:
parent
6d5e24549f
commit
b0e4dde51b
15 changed files with 756 additions and 0 deletions
|
@ -4,3 +4,11 @@ version = getSubprojectVersion(project, "0.4.1")
|
||||||
moduleDependencies(project, [
|
moduleDependencies(project, [
|
||||||
'fabric-api-base'
|
'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')
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": { "model": "fabric-renderer-api-v1-testmod:block/frame" }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"package": "net.fabricmc.fabric.test.renderer.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_8",
|
||||||
|
"mixins": [
|
||||||
|
"WorldMixin"
|
||||||
|
],
|
||||||
|
"client": [
|
||||||
|
"ClientWorldMixin"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
23
fabric-renderer-api-v1/src/testmod/resources/fabric.mod.json
Normal file
23
fabric-renderer-api-v1/src/testmod/resources/fabric.mod.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue