From e034fae532f809d1dd486b70109e442426f38939 Mon Sep 17 00:00:00 2001 From: quat1024 Date: Mon, 3 Jul 2023 21:55:32 -0400 Subject: [PATCH] Poke at stuff, documentation especially --- README.md | 30 +++++++++++++++++-- .../cottonmc/templates/TemplatesClient.java | 4 +-- .../templates/api/ThemeableBlockEntity.java | 7 +++-- .../block/entity/TemplateEntity.java | 8 +---- ...> RetexturedMeshTemplateUnbakedModel.java} | 4 +-- .../templates/model/SlopeBaseMesh.java | 10 +++---- .../templates/model/TemplateBakedModel.java | 2 +- 7 files changed, 43 insertions(+), 22 deletions(-) rename src/main/java/io/github/cottonmc/templates/model/{RetexturedMeshTemplateModel.java => RetexturedMeshTemplateUnbakedModel.java} (89%) diff --git a/README.md b/README.md index 66b8fe1..bf20544 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,35 @@ Template blocks can be placed in the world, then right-clicked with a full-size * Evaluate whether I need to keep the `Supplier` in TemplatesModelProvider, or whether I can reuse my `UnbakedModel`s indefinitely * `templates:block/slope_base` needs a suspicious amount of custom rotations. Maybe the model is pointing the wrong way. +* `uvlock` in a blockstate will not work for `RetexturedMeshTemplateUnbakedModel`s. Can it be fixed? * Upside-down slopes would be nice... * More templates !! -## Notes for addon developers +## For addon developers -To create your block, instantiate or extend `TemplateBlock`. Pass your `Block.Settings` through `TemplateBlock.configureSettings` to wire up the "click for glowstone" feature. Create an `ItemBlock` as normal, and create a `BlockEntityType` by instantiating or extending `TemplateEntity`. +You may create your block any way you like, just make sure it has a block entity that returns a `BlockState` object from `RenderAttachmentBlockEntity.getRenderAttachmentData` and implements `ThemeableBlockEntity`. If you don't already have a block, the stock implementations in `TemplateBlock` and `TemplateEntity` are considered public API - they also implement the light- and redstone-emission features, just remember to feed the `AbstractBlock.Settings` through `TemplateBlock.configureSettings`. -Next, wire up the custom model todo document this, it's easy \ No newline at end of file +(Really the important part is implementing `RenderAttachmentBlockEntity` with a `BlockState`; that's the only thing Templates's bakedmodels assume. `ThemeableBlockEntity` opts-in to a couple more things such as overriding the break/sprint/fall particles.) + +## `Mesh`-based models + +We will construct a `RetexturedMeshTemplateUnbakedModel`. You need two things - the ID of a parent model, and a `Supplier` to retexture. + +Fill in the parent model field with the ID of any model. Ideally, this model should have a parent of `block/block`, or at least define *some* non-default rotations (smokey the bear voice *Only You Can Prevent Weirdly Rotated First-Person Models*), set `"gui_light": "front"` (lest the item model look weird), and define a particle texture. + +When building the `Mesh`, if you want a face to be dynamically retextured, `.tag()` it with the `.ordinal() + 1` of the `Direction` it corresponds to and give the face U/V coordinates ranging from 0 to 1. (For example, if you tag a face with `3` (`Direction.NORTH.ordinal() + 1`), it will be retextured to the north side of the template's theme.) + +(TODO: implement a system for baking unchanging `Sprite`s onto the mesh, potentially by "registering" more tags; the problem is you don't have access to sprite uvs at mesh building time. Or just provide a way to get sprite UVs at mesh building time...?) + +That's all you need in order to construct a `RetexturedMeshTemplateUnbakedModel`, so to finish things off: + +* Come up with an ID for it +* Register it using `TemplatesClient.provider.addTemplateModel` (a thin wrapper around Fabric's `ModelResourceProvider`) +* Create a blockstate for your block, point it at your model's ID + * You may rotate the blockmodel with the `x` and `y` properties. + +You may create a regular item model (JSON or otherwise), or use ours by calling `TemplatesClient.provider.assignItemModel` (a thin wrapper around Fabric's `ModelVariantProvider`) passing the same model ID the block used. (This is a bit of a kludge. The reason you have to do this, instead of simply creating a regular item model and setting its `parent`, is that `JsonUnbakedModel`s can't have non-`JsonUnbakedModel`s as their `parent`, and even a trivial item model with only the `parent` field set counts as a `JsonUnbakedModel`. Blockstates are a layer of indirection before model loading, so it's not a problem for blocks.) + +## JSON models + +Soon:tm: \ No newline at end of file diff --git a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java index fa9f9b1..370f6ef 100644 --- a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java +++ b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java @@ -1,6 +1,6 @@ package io.github.cottonmc.templates; -import io.github.cottonmc.templates.model.RetexturedMeshTemplateModel; +import io.github.cottonmc.templates.model.RetexturedMeshTemplateUnbakedModel; import io.github.cottonmc.templates.model.SlopeBaseMesh; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; @@ -55,7 +55,7 @@ public class TemplatesClient implements ClientModInitializer { BlockRenderLayerMap.INSTANCE.putBlock(Templates.SLOPE, RenderLayer.getCutout()); - provider.addTemplateModel(Templates.id("slope_special"), () -> new RetexturedMeshTemplateModel(Templates.id("block/slope_base"), SlopeBaseMesh::make)); + provider.addTemplateModel(Templates.id("slope_special"), () -> new RetexturedMeshTemplateUnbakedModel(Templates.id("block/slope_base"), SlopeBaseMesh::make)); provider.assignItemModel(Templates.id("slope_special"), Templates.SLOPE); } } diff --git a/src/main/java/io/github/cottonmc/templates/api/ThemeableBlockEntity.java b/src/main/java/io/github/cottonmc/templates/api/ThemeableBlockEntity.java index 6bd228c..3aa31b0 100644 --- a/src/main/java/io/github/cottonmc/templates/api/ThemeableBlockEntity.java +++ b/src/main/java/io/github/cottonmc/templates/api/ThemeableBlockEntity.java @@ -1,7 +1,10 @@ package io.github.cottonmc.templates.api; +import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity; import net.minecraft.block.BlockState; -public interface ThemeableBlockEntity { - BlockState getThemeState(); +public interface ThemeableBlockEntity extends RenderAttachmentBlockEntity { + default BlockState getThemeState() { + return (BlockState) getRenderAttachmentData(); + } } diff --git a/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java b/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java index 39004c0..129565c 100644 --- a/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java +++ b/src/main/java/io/github/cottonmc/templates/block/entity/TemplateEntity.java @@ -2,7 +2,6 @@ package io.github.cottonmc.templates.block.entity; import io.github.cottonmc.templates.Templates; import io.github.cottonmc.templates.api.ThemeableBlockEntity; -import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; @@ -19,7 +18,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Objects; -public class TemplateEntity extends BlockEntity implements RenderAttachmentBlockEntity, ThemeableBlockEntity { +public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity { protected BlockState renderedState = Blocks.AIR.getDefaultState(); //Whether the player has manually spent a redstone/glowstone item to upgrade the template. @@ -75,11 +74,6 @@ public class TemplateEntity extends BlockEntity implements RenderAttachmentBlock return renderedState; } - @Override - public BlockState getThemeState() { - return renderedState; - } - public void setRenderedState(BlockState newState) { if(!Objects.equals(renderedState, newState)) { renderedState = newState; diff --git a/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateModel.java b/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateUnbakedModel.java similarity index 89% rename from src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateModel.java rename to src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateUnbakedModel.java index ca74b19..cc7bfd5 100644 --- a/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateModel.java +++ b/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateUnbakedModel.java @@ -16,8 +16,8 @@ import java.util.function.Function; import java.util.function.Supplier; @SuppressWarnings("ClassCanBeRecord") -public class RetexturedMeshTemplateModel implements UnbakedModel { - public RetexturedMeshTemplateModel(Identifier parent, Supplier baseMeshFactory) { +public class RetexturedMeshTemplateUnbakedModel implements UnbakedModel { + public RetexturedMeshTemplateUnbakedModel(Identifier parent, Supplier baseMeshFactory) { this.parent = parent; this.baseMeshFactory = baseMeshFactory; } diff --git a/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java b/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java index 16b7a16..3e60fc9 100644 --- a/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java +++ b/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java @@ -11,11 +11,11 @@ public class SlopeBaseMesh { /** * @see TemplateBakedModel.RetexturingTransformer for why these values were chosen */ - public static final int TAG_SLOPE = Direction.UP.ordinal(); - public static final int TAG_LEFT = Direction.EAST.ordinal(); - public static final int TAG_RIGHT = Direction.WEST.ordinal(); - public static final int TAG_BACK = Direction.SOUTH.ordinal(); - public static final int TAG_BOTTOM = Direction.DOWN.ordinal(); + public static final int TAG_SLOPE = Direction.UP.ordinal() + 1; + public static final int TAG_LEFT = Direction.EAST.ordinal() + 1; + public static final int TAG_RIGHT = Direction.WEST.ordinal() + 1; + public static final int TAG_BACK = Direction.SOUTH.ordinal() + 1; + public static final int TAG_BOTTOM = Direction.DOWN.ordinal() + 1; public static Mesh make() { Renderer renderer = TemplatesClient.getFabricRenderer(); diff --git a/src/main/java/io/github/cottonmc/templates/model/TemplateBakedModel.java b/src/main/java/io/github/cottonmc/templates/model/TemplateBakedModel.java index 64f62c4..9d55224 100644 --- a/src/main/java/io/github/cottonmc/templates/model/TemplateBakedModel.java +++ b/src/main/java/io/github/cottonmc/templates/model/TemplateBakedModel.java @@ -100,7 +100,7 @@ public final class TemplateBakedModel extends ForwardingBakedModel { quad.material(appearance.getRenderMaterial()); //The quad tag numbers were selected so this magic trick works: - Direction dir = facePermutation.get(DIRECTIONS[quad.tag()]); + Direction dir = facePermutation.get(DIRECTIONS[quad.tag() - 1]); //TODO: this newly-simplified direction passing to hasColor is almost certainly incorrect // I think hasColor was kinda incorrect in the first place tho