Poke at stuff, documentation especially

This commit is contained in:
quat1024 2023-07-03 21:55:32 -04:00
parent 80910e38f5
commit e034fae532
7 changed files with 43 additions and 22 deletions

View File

@ -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
(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<Mesh>` 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:

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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<Mesh> baseMeshFactory) {
public class RetexturedMeshTemplateUnbakedModel implements UnbakedModel {
public RetexturedMeshTemplateUnbakedModel(Identifier parent, Supplier<Mesh> baseMeshFactory) {
this.parent = parent;
this.baseMeshFactory = baseMeshFactory;
}

View File

@ -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();

View File

@ -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