diff --git a/build.gradle b/build.gradle index f048994..c16acd1 100755 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ if(rootProject.file("private.gradle").exists()) { //Publishing details archivesBaseName = "templates" group = "io.github.cottonmc" -version = "2.0.5+1.20.1" +version = "2.1.0+1.20.1" repositories { mavenCentral() diff --git a/src/main/java/io/github/cottonmc/templates/Templates.java b/src/main/java/io/github/cottonmc/templates/Templates.java index 593a806..f2f5265 100644 --- a/src/main/java/io/github/cottonmc/templates/Templates.java +++ b/src/main/java/io/github/cottonmc/templates/Templates.java @@ -17,6 +17,7 @@ import io.github.cottonmc.templates.block.TemplateSlabBlock; import io.github.cottonmc.templates.block.TemplateSlopeBlock; import io.github.cottonmc.templates.block.TemplateStairsBlock; import io.github.cottonmc.templates.block.TemplateTrapdoorBlock; +import io.github.cottonmc.templates.block.TemplateVerticalSlabBlock; import io.github.cottonmc.templates.block.TemplateWallBlock; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; @@ -53,6 +54,7 @@ public class Templates implements ModInitializer { return TemplateInteractionUtil.configureSettings(AbstractBlock.Settings.copy(base)); } + //vanilla, or at least vanilla-like, templates: public static final Block BUTTON = Registry.register(Registries.BLOCK, id("button") , new TemplateButtonBlock(cp(Blocks.OAK_BUTTON))); public static final Block CANDLE = Registry.register(Registries.BLOCK, id("candle") , new TemplateCandleBlock(TemplateCandleBlock.configureSettings(cp(Blocks.CANDLE)))); public static final Block CARPET = Registry.register(Registries.BLOCK, id("carpet") , new TemplateCarpetBlock(cp(Blocks.WHITE_CARPET))); @@ -69,20 +71,25 @@ public class Templates implements ModInitializer { public static final Block SLAB = Registry.register(Registries.BLOCK, id("slab") , new TemplateSlabBlock(cp(Blocks.OAK_SLAB))); public static final Block STAIRS = Registry.register(Registries.BLOCK, id("stairs") , new TemplateStairsBlock(cp(Blocks.OAK_STAIRS))); public static final Block TRAPDOOR = Registry.register(Registries.BLOCK, id("trapdoor") , new TemplateTrapdoorBlock(cp(Blocks.OAK_TRAPDOOR), BlockSetType.OAK)); + public static final Block VERTICAL_SLAB = Registry.register(Registries.BLOCK, id("vertical_slab") , new TemplateVerticalSlabBlock(cp(Blocks.OAK_SLAB))); public static final Block WALL = Registry.register(Registries.BLOCK, id("wall") , new TemplateWallBlock(TemplateInteractionUtil.makeSettings())); + + //oddball templates: public static final Block SLOPE = Registry.register(Registries.BLOCK, id("slope") , new TemplateSlopeBlock(TemplateInteractionUtil.makeSettings())); //30 degree slope (shallow/deep) //corner slopes //quarter slabs???? + //Very good public static final Block COOL_RIVULET = Registry.register(Registries.BLOCK, id("cool_rivulet"), new GlazedTerracottaBlock(AbstractBlock.Settings.create().hardness(0.2f)) { @Override public void appendTooltip(ItemStack stack, @Nullable BlockView world, List tooltip, TooltipContext eggbals) { tooltip.add(Text.translatable("block.templates.cool_rivulet").formatted(Formatting.GRAY)); } - }); //Very good + }); - //for addon devs: it's fine to make your own block entity type instead of gluing additional blocks to this one + //For addon devs: Just make your own BlockEntityType instead of trying to add more blocks to this one. + //You can even reuse the same TemplateEntity class. public static final BlockEntityType TEMPLATE_BLOCK_ENTITY = Registry.register( Registries.BLOCK_ENTITY_TYPE, id("slope"), FabricBlockEntityTypeBuilder.create(Templates::makeTemplateBlockEntity, @@ -102,6 +109,7 @@ public class Templates implements ModInitializer { SLAB, STAIRS, TRAPDOOR, + VERTICAL_SLAB, WALL, SLOPE ).build(null) @@ -137,6 +145,7 @@ public class Templates implements ModInitializer { Registry.register(Registries.ITEM, id("slab") , new BlockItem(SLAB, new Item.Settings())); Registry.register(Registries.ITEM, id("stairs") , new BlockItem(STAIRS, new Item.Settings())); Registry.register(Registries.ITEM, id("trapdoor") , new BlockItem(TRAPDOOR, new Item.Settings())); + Registry.register(Registries.ITEM, id("vertical_slab") , new BlockItem(VERTICAL_SLAB, new Item.Settings())); Registry.register(Registries.ITEM, id("wall") , new BlockItem(WALL, new Item.Settings())); Registry.register(Registries.ITEM, id("slope") , new BlockItem(SLOPE, new Item.Settings())); @@ -154,11 +163,13 @@ public class Templates implements ModInitializer { private void fillCreativeTab(ItemGroup.DisplayContext ctx, ItemGroup.Entries e) { //sorted by encounter order of the vanilla block in the "search" creative tab - //with the non-vanilla "post" inserted of course - //and i moved the lever next to the pressureplate and button cause theyre redstoney + //with the non-vanilla "post" and "vertical slab" inserted where they fit + //...and i moved the lever way up next to the pressureplate and button, cause theyre redstoney... + //hopefully this ordering makes sense lol e.add(CUBE); e.add(STAIRS); e.add(SLAB); + e.add(VERTICAL_SLAB); e.add(POST); e.add(FENCE); e.add(FENCE_GATE); @@ -174,8 +185,10 @@ public class Templates implements ModInitializer { e.add(PANE); e.add(CANDLE); + //Oddball that doesn't look anything like vanilla blocks e.add(SLOPE); - e.add(COOL_RIVULET); //Very good + //Very good + e.add(COOL_RIVULET); } } diff --git a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java index e0862f1..cf60aeb 100644 --- a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java +++ b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java @@ -72,6 +72,7 @@ public class TemplatesClient implements ClientModInitializer { Templates.SLAB, Templates.STAIRS, Templates.TRAPDOOR, + Templates.VERTICAL_SLAB, Templates.WALL, Templates.SLOPE ); @@ -122,6 +123,7 @@ public class TemplatesClient implements ClientModInitializer { provider.addTemplateModel(Templates.id("glass_pane_side_alt_special") , new UnbakedAutoRetexturedModel(Templates.id("block/glass_pane_side_alt"))); provider.addTemplateModel(Templates.id("wall_side_special") , new UnbakedJsonRetexturedModel(Templates.id("block/wall_side"))); provider.addTemplateModel(Templates.id("wall_side_tall_special") , new UnbakedJsonRetexturedModel(Templates.id("block/wall_side_tall"))); + provider.addTemplateModel(Templates.id("vertical_slab_special") , new UnbakedJsonRetexturedModel(Templates.id("block/vertical_slab"))); //mesh models provider.addTemplateModel(Templates.id("slope_special") , new UnbakedMeshRetexturedModel(Templates.id("block/slope_base"), SlopeBaseMesh::makeUpright)); @@ -145,6 +147,7 @@ public class TemplatesClient implements ClientModInitializer { provider.assignItemModel(Templates.id("slab_bottom_special") , Templates.SLAB); provider.assignItemModel(Templates.id("stairs_special") , Templates.STAIRS); provider.assignItemModel(Templates.id("trapdoor_bottom_special") , Templates.TRAPDOOR); + provider.assignItemModel(Templates.id("vertical_slab_special") , Templates.VERTICAL_SLAB); provider.assignItemModel(Templates.id("wall_inventory_special") , Templates.WALL); provider.assignItemModel(Templates.id("slope_special") , Templates.SLOPE); } diff --git a/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java b/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java index ae7b321..9d1bb12 100644 --- a/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java +++ b/src/main/java/io/github/cottonmc/templates/block/TemplateBlock.java @@ -29,6 +29,8 @@ public class TemplateBlock extends Block implements BlockEntityProvider { setDefaultState(TemplateInteractionUtil.setDefaultStates(getDefaultState())); } + //For addon devs: override this so your blocks don't end up trying to place my block entity, my BlockEntityType only handles blocks internal to the mod + //Just make your own BlockEntityType, it's fine, you can even use the same TemplateEntity class @Override public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) { return Templates.TEMPLATE_BLOCK_ENTITY.instantiate(pos, state); diff --git a/src/main/java/io/github/cottonmc/templates/block/TemplateVerticalSlabBlock.java b/src/main/java/io/github/cottonmc/templates/block/TemplateVerticalSlabBlock.java new file mode 100644 index 0000000..9c92c86 --- /dev/null +++ b/src/main/java/io/github/cottonmc/templates/block/TemplateVerticalSlabBlock.java @@ -0,0 +1,116 @@ +package io.github.cottonmc.templates.block; + +import io.github.cottonmc.templates.api.TemplateInteractionUtil; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; +import net.minecraft.block.enums.SlabType; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.EnumProperty; +import net.minecraft.util.StringIdentifiable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +import org.jetbrains.annotations.Nullable; + +//Extending SlabBlock from this is a little bit bold - let's see how this goes +public class TemplateVerticalSlabBlock extends TemplateSlabBlock { + public TemplateVerticalSlabBlock(Settings settings) { + super(settings); + setDefaultState(getDefaultState().with(AFFINITY, Affinity.X)); + } + + protected static final EnumProperty AFFINITY = EnumProperty.of("affinity", Affinity.class); + protected static final VoxelShape NORTH_SHAPE = createCuboidShape(0, 0, 0, 16, 16, 8); + protected static final VoxelShape EAST_SHAPE = createCuboidShape(8, 0, 0, 16, 16, 16); + protected static final VoxelShape SOUTH_SHAPE = createCuboidShape(0, 0, 8, 16, 16, 16); + protected static final VoxelShape WEST_SHAPE = createCuboidShape(0, 0, 0, 8, 16, 16); + + @Override + protected void appendProperties(StateManager.Builder builder) { + super.appendProperties(builder.add(AFFINITY)); + } + + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext ctx) { + SlabType type = state.get(TYPE); + if(type == SlabType.DOUBLE) return VoxelShapes.fullCube(); + + Affinity aff = state.get(AFFINITY); + if(type == SlabType.BOTTOM && aff == Affinity.X) return WEST_SHAPE; + if(type == SlabType.BOTTOM && aff == Affinity.Z) return NORTH_SHAPE; + if(type == SlabType.TOP && aff == Affinity.X) return EAST_SHAPE; + if(type == SlabType.TOP && aff == Affinity.Z) return SOUTH_SHAPE; + + return VoxelShapes.fullCube(); //unreachable + } + + @Override + public @Nullable BlockState getPlacementState(ItemPlacementContext ctx) { + BlockPos pos = ctx.getBlockPos(); + BlockState existingState = ctx.getWorld().getBlockState(pos); + if(existingState.isOf(this)) { + return TemplateInteractionUtil.modifyPlacementState(existingState.with(TYPE, SlabType.DOUBLE).with(WATERLOGGED, false), ctx); + } else { +// double dx = ctx.getHitPos().x - ctx.getBlockPos().getX(); +// double dz = ctx.getHitPos().z - ctx.getBlockPos().getZ(); +// +// Direction hmm = switch(ctx.getHorizontalPlayerFacing()) { +// case NORTH, SOUTH -> dx < 0.5 ? Direction.WEST : Direction.EAST; +// case EAST, WEST -> dz < 0.5 ? Direction.NORTH : Direction.SOUTH; +// default -> Direction.NORTH; //unreachable +// }; + + Direction hmm = ctx.getHorizontalPlayerFacing(); + + return TemplateInteractionUtil.modifyPlacementState(getDefaultState() + .with(WATERLOGGED, ctx.getWorld().getFluidState(pos).getFluid() == Fluids.WATER) + .with(TYPE, (hmm == Direction.NORTH || hmm == Direction.WEST) ? SlabType.BOTTOM : SlabType.TOP) + .with(AFFINITY, (hmm == Direction.NORTH || hmm == Direction.SOUTH) ? Affinity.Z : Affinity.X), ctx); + } + } + + @Override + public boolean canReplace(BlockState state, ItemPlacementContext ctx) { + SlabType type = state.get(TYPE); + if(type == SlabType.DOUBLE) return false; + + ItemStack stack = ctx.getStack(); + if(!stack.isOf(asItem())) return false; + + if(ctx.canReplaceExisting()) { + //Easy check -> clicking on the floor or ceiling should complete the slab. + //I don't think this check actually works lol, but vanilla has something like it + //If you click on the floor or ceiling of the next block, you get !canReplaceExisting + Direction dir = ctx.getSide(); + if(dir.getAxis().isVertical()) return true; + + //Hard check -> clicking the west face of a slab occupying the east half of the block should complete the slab. + Affinity aff = state.get(AFFINITY); + return (type == SlabType.BOTTOM && aff == Affinity.X && dir == Direction.EAST) || + (type == SlabType.BOTTOM && aff == Affinity.Z && dir == Direction.SOUTH) || + (type == SlabType.TOP && aff == Affinity.X && dir == Direction.WEST) || + (type == SlabType.TOP && aff == Affinity.Z && dir == Direction.NORTH); + } else { + //This looks wrong, right? if !ctx.canReplaceExisting, return "true"? + //I'll chalk this up to a bad Yarn name. This method seems to return false when the placement was "bumped" + //into this blockspace, like when you click the side of an end rod that's facing my block + return true; + } + } + + enum Affinity implements StringIdentifiable { + X, Z; + + @Override + public String asString() { + return this == X ? "x" : "z"; + } + } +} diff --git a/src/main/resources/assets/templates/blockstates/vertical_slab.json b/src/main/resources/assets/templates/blockstates/vertical_slab.json new file mode 100644 index 0000000..dca471a --- /dev/null +++ b/src/main/resources/assets/templates/blockstates/vertical_slab.json @@ -0,0 +1,25 @@ +{ + "variants": { + "type=bottom,affinity=x": { + "model": "templates:vertical_slab_special", + "y": 270 + }, + "type=double,affinity=x": { + "model": "templates:cube_special" + }, + "type=top,affinity=x": { + "model": "templates:vertical_slab_special", + "y": 90 + }, + "type=bottom,affinity=z": { + "model": "templates:vertical_slab_special" + }, + "type=double,affinity=z": { + "model": "templates:cube_special" + }, + "type=top,affinity=z": { + "model": "templates:vertical_slab_special", + "y": 180 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/templates/lang/en_us.json b/src/main/resources/assets/templates/lang/en_us.json index cd7f119..e8e8ab0 100644 --- a/src/main/resources/assets/templates/lang/en_us.json +++ b/src/main/resources/assets/templates/lang/en_us.json @@ -18,6 +18,7 @@ "block.templates.slab": "Slab Template", "block.templates.stairs": "Stairs Template", "block.templates.trapdoor": "Trapdoor Template", + "block.templates.vertical_slab": "Vertical Slab Template", "block.templates.wall": "Wall Template", "block.templates.cool_rivulet": "cool rivulet" diff --git a/src/main/resources/assets/templates/models/block/vertical_slab.json b/src/main/resources/assets/templates/models/block/vertical_slab.json new file mode 100644 index 0000000..176f83d --- /dev/null +++ b/src/main/resources/assets/templates/models/block/vertical_slab.json @@ -0,0 +1,75 @@ +{ + "parent": "minecraft:block/block", + "textures": { + "down": "templates:templates_special/down", + "up": "templates:templates_special/up", + "north": "templates:templates_special/north", + "south": "templates:templates_special/south", + "west": "templates:templates_special/west", + "east": "templates:templates_special/east" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 16, 8], + "faces": { + "down": { + "texture": "#down", + "cullface": "down" + }, + "up": { + "texture": "#up", + "cullface": "up" + }, + "north": { + "texture": "#north", + "cullface": "north" + }, + "south": { + "texture": "#south" + }, + "west": { + "texture": "#west", + "cullface": "west" + }, + "east": { + "texture": "#east", + "cullface": "east" + } + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, -135, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "thirdperson_lefthand": { + "rotation": [75, -135, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "firstperson_righthand": { + "rotation": [0, -145, 0], + "scale": [0.4, 0.4, 0.4] + }, + "firstperson_lefthand": { + "rotation": [0, 225, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, 45, 0], + "translation": [1.75, -1, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "rotation": [0, -90, 0], + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json index 83d36fc..1838bbe 100644 --- a/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json +++ b/src/main/resources/data/minecraft/tags/blocks/mineable/axe.json @@ -15,6 +15,7 @@ "templates:slab", "templates:stairs", "templates:trapdoor", + "templates:vertical_slab", "templates:wall", "templates:slope" ] diff --git a/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json b/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json index 6117b97..d8a199c 100644 --- a/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json +++ b/src/main/resources/data/minecraft/tags/blocks/wooden_slabs.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "templates:slab" + "templates:slab", + "templates:vertical_slab" ] } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/items/wooden_slabs.json b/src/main/resources/data/minecraft/tags/items/wooden_slabs.json index 6117b97..d8a199c 100644 --- a/src/main/resources/data/minecraft/tags/items/wooden_slabs.json +++ b/src/main/resources/data/minecraft/tags/items/wooden_slabs.json @@ -1,6 +1,7 @@ { "replace": false, "values": [ - "templates:slab" + "templates:slab", + "templates:vertical_slab" ] } \ No newline at end of file diff --git a/src/main/resources/data/templates/loot_tables/blocks/vertical_slab.json b/src/main/resources/data/templates/loot_tables/blocks/vertical_slab.json new file mode 100644 index 0000000..bfb9a02 --- /dev/null +++ b/src/main/resources/data/templates/loot_tables/blocks/vertical_slab.json @@ -0,0 +1,38 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "conditions": [ + { + "block": "templates:vertical_slab", + "condition": "minecraft:block_state_property", + "properties": { + "type": "double" + } + } + ], + "count": 2.0, + "function": "minecraft:set_count" + }, + { + "function": "minecraft:explosion_decay" + } + ], + "name": "templates:vertical_slab" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/templates/recipes/post.json b/src/main/resources/data/templates/recipes/post.json index 218de3e..d00af23 100644 --- a/src/main/resources/data/templates/recipes/post.json +++ b/src/main/resources/data/templates/recipes/post.json @@ -1,9 +1,9 @@ { "type": "minecraft:crafting_shaped", "pattern": [ - "I ", "I~", - "I " + "I ", + "I~" ], "key": { "I": { diff --git a/src/main/resources/data/templates/recipes/vertical_slab.json b/src/main/resources/data/templates/recipes/vertical_slab.json new file mode 100644 index 0000000..4029946 --- /dev/null +++ b/src/main/resources/data/templates/recipes/vertical_slab.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "I ", + "I~", + "I " + ], + "key": { + "I": { + "item": "minecraft:bamboo" + }, + "~": { + "item": "minecraft:string" + } + }, + "result": { + "item": "templates:vertical_slab", + "count": 6 + }, + "group": "templates" +} \ No newline at end of file