diff --git a/NOTICE b/NOTICE index 2d85d7f..ebbedae 100644 --- a/NOTICE +++ b/NOTICE @@ -14,6 +14,8 @@ The Writing Desk item texture is copied from Legacy's assets/mystcraft/textures/items/writingdesk.png under the same license. The Writing Desk block texture is copied from Legacy's assets/mystcraft/textures/entity/desk.png under the same license. +The Writing Desk GUI atlas is copied from Legacy's assets/mystcraft/gui/writingdesk.png +under the same license; desk wood and inlay textures are cropped from desk.png. The initial build layout is derived from the official NeoForge 1.21.1 ModDevGradle MDK: https://github.com/NeoForgeMDKs/MDK-1.21.1-ModDevGradle diff --git a/README.md b/README.md index b38667e..632e486 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ The spent vial returns a glass bottle. Server owners can adjust the symbol-copy and link-panel costs in the `writing` section of `rivencraft-server.toml`. The Writing Desk can copy a selected written page from its collection tabs. The Writing Desk is now craftable from planks, a glass bottle, and a feather. +It occupies two adjacent blocks, with one shared inventory; loaded paper and +the selected page appear on its Legacy-inspired model. +Desks placed before 0.3.6.1 keep their old one-block footprint until broken +and placed again; leave an adjacent space when replacing one. Its four collection tabs, paper input, ink vial input, empty glass-bottle return, 16-unit ink meter, and inventory persist through world saves; breaking it drops stored contents. The desk screen is a diff --git a/docs/ASSET_PROVENANCE.md b/docs/ASSET_PROVENANCE.md index 5ca85d7..47fa911 100644 --- a/docs/ASSET_PROVENANCE.md +++ b/docs/ASSET_PROVENANCE.md @@ -9,7 +9,9 @@ project's GNU LGPL v3 license. Rivencraft itself uses the same license. | `assets/rivencraft/textures/item/page.png` | `assets/mystcraft/textures/items/page_background.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Namespace/path rename only | | `assets/rivencraft/textures/gui/notebook_pages.png` | `assets/mystcraft/gui/bookui_pagel.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Namespace/path rename only; Notebook draws the native 30×40 page at atlas coordinates `(156, 0)` | | `assets/rivencraft/textures/item/writing_desk.png` | `assets/mystcraft/textures/items/writingdesk.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Namespace/path rename only | -| `assets/rivencraft/textures/block/writing_desk.png` | `assets/mystcraft/textures/entity/desk.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Namespace/path rename only; single-block model adapts the desk geometry and UV regions from `ModelWritingDesk` | +| `assets/rivencraft/textures/block/writing_desk.png` | `assets/mystcraft/textures/entity/desk.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Namespace/path rename only | +| `assets/rivencraft/textures/block/writing_desk_wood.png` and `writing_desk_inlay.png` | `assets/mystcraft/textures/entity/desk.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Cropped opaque wood and red inlay regions for the two-block model | +| `assets/rivencraft/textures/gui/writing_desk_legacy.png` | `assets/mystcraft/gui/writingdesk.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Namespace/path rename only; solid GUI backing sampled from Legacy atlas | | `assets/rivencraft/textures/item/linking_book_unwritten.png` | `assets/mystcraft/textures/items/unlinked.png` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Namespace/path rename only | | `assets/rivencraft/textures/item/page_link_panel.png` | `page_background.png` and `PageBuilder.BasicPageSprite` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Reproduces the legacy 160 px scale, black panel at `(25,30)`–`(135,75)`, and 128 px resample | | `assets/rivencraft/textures/item/page_symbol*.png` and `page_unresolved.png` | `page_background.png`, `textures/symbolcomponents.png`, `WordData`, `ModSymbols`, and `PageBuilder.PageSprite` | `9bc8ddc061845df0cd5ea47f4fdef773cff786ae` | Static 1.21.1 renditions of the legacy runtime-composed four-word symbol pages; `normal_time` uses the legacy Full Length poem | diff --git a/gradle.properties b/gradle.properties index e380cad..c79688c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -35,7 +35,7 @@ mod_name=Rivencraft # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=LGPL-3.0-or-later # The mod version. Rivencraft uses the x.y.z.b policy documented in README.md. -mod_version=0.3.6.0 +mod_version=0.3.6.1 immersive_portals_version=6.0.7 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. diff --git a/src/main/java/net/dnorberg/rivencraft/block/WritingDeskBlock.java b/src/main/java/net/dnorberg/rivencraft/block/WritingDeskBlock.java index 76d74ca..79224c6 100644 --- a/src/main/java/net/dnorberg/rivencraft/block/WritingDeskBlock.java +++ b/src/main/java/net/dnorberg/rivencraft/block/WritingDeskBlock.java @@ -5,6 +5,7 @@ import net.dnorberg.rivencraft.block.entity.WritingDeskBlockEntity; import net.dnorberg.rivencraft.menu.WritingDeskMenu; import net.dnorberg.rivencraft.writing.WritingDeskCatalog; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Containers; @@ -19,48 +20,72 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.entity.LivingEntity; +import org.jetbrains.annotations.Nullable; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.BlockHitResult; public final class WritingDeskBlock extends BaseEntityBlock { public static final MapCodec CODEC = simpleCodec(WritingDeskBlock::new); public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final BooleanProperty EXTENSION = BooleanProperty.create("extension"); public WritingDeskBlock(Properties properties) { super(properties); - registerDefaultState(stateDefinition.any().setValue(FACING, net.minecraft.core.Direction.NORTH)); + registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(EXTENSION, false)); } @Override public MapCodec codec() { return CODEC; } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(FACING); + builder.add(FACING, EXTENSION); } @Override public BlockState getStateForPlacement(BlockPlaceContext context) { - return defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()); + Direction facing = context.getHorizontalDirection().getOpposite(); + BlockPos extension = context.getClickedPos().relative(facing.getClockWise()); + return context.getLevel().getBlockState(extension).canBeReplaced(context) + ? defaultBlockState().setValue(FACING, facing) : null; + } + @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, + @Nullable LivingEntity placer, ItemStack stack) { + super.setPlacedBy(level, pos, state, placer, stack); + level.setBlock(pos.relative(state.getValue(FACING).getClockWise()), + state.setValue(EXTENSION, true), 3); } @Override protected RenderShape getRenderShape(BlockState state) { return RenderShape.MODEL; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { - return new WritingDeskBlockEntity(pos, state); + return state.getValue(EXTENSION) ? null : new WritingDeskBlockEntity(pos, state); } @Override protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) { + BlockPos controller = state.getValue(EXTENSION) + ? pos.relative(state.getValue(FACING).getCounterClockWise()) : pos; if (!level.isClientSide && player instanceof ServerPlayer serverPlayer - && level.getBlockEntity(pos) instanceof WritingDeskBlockEntity desk) { + && level.getBlockEntity(controller) instanceof WritingDeskBlockEntity desk) { serverPlayer.openMenu(new SimpleMenuProvider( (id, inventory, ignored) -> new WritingDeskMenu(id, inventory, desk), Component.translatable("container.rivencraft.writing_desk")), buffer -> { - buffer.writeBlockPos(pos); + buffer.writeBlockPos(controller); WritingDeskCatalog.write(buffer, WritingDeskCatalog.available(desk)); }); } return InteractionResult.sidedSuccess(level.isClientSide); } @Override protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState replacement, boolean moving) { - if (!state.is(replacement.getBlock()) && !level.isClientSide - && level.getBlockEntity(pos) instanceof WritingDeskBlockEntity desk) { - Containers.dropContents(level, pos, desk); - level.updateNeighbourForOutputSignal(pos, this); + if (!state.is(replacement.getBlock())) { + if (!level.isClientSide && !state.getValue(EXTENSION) + && level.getBlockEntity(pos) instanceof WritingDeskBlockEntity desk) { + Containers.dropContents(level, pos, desk); + level.updateNeighbourForOutputSignal(pos, this); + } + BlockPos other = pos.relative(state.getValue(FACING).getClockWise(), + state.getValue(EXTENSION) ? -1 : 1); + BlockState otherState = level.getBlockState(other); + if (otherState.is(this) && otherState.getValue(EXTENSION) != state.getValue(EXTENSION)) { + level.setBlock(other, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), 35); + } } super.onRemove(state, level, pos, replacement, moving); } diff --git a/src/main/java/net/dnorberg/rivencraft/block/entity/WritingDeskBlockEntity.java b/src/main/java/net/dnorberg/rivencraft/block/entity/WritingDeskBlockEntity.java index d817a95..906c7d3 100644 --- a/src/main/java/net/dnorberg/rivencraft/block/entity/WritingDeskBlockEntity.java +++ b/src/main/java/net/dnorberg/rivencraft/block/entity/WritingDeskBlockEntity.java @@ -8,6 +8,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; import net.minecraft.world.entity.player.Player; @@ -28,6 +31,7 @@ public final class WritingDeskBlockEntity extends BlockEntity implements Contain private NonNullList items = NonNullList.withSize(SIZE, ItemStack.EMPTY); private int activeCollection; private int inkRemaining; + private ItemStack displayPage = ItemStack.EMPTY; public WritingDeskBlockEntity(BlockPos pos, BlockState state) { super(ModBlockEntities.WRITING_DESK.get(), pos, state); @@ -35,6 +39,14 @@ public final class WritingDeskBlockEntity extends BlockEntity implements Contain public int activeCollection() { return activeCollection; } public int inkRemaining() { return inkRemaining; } + public ItemStack displayPage() { return displayPage; } + public void setDisplayPage(ItemStack page) { + ItemStack next = page.isEmpty() ? ItemStack.EMPTY : page.copyWithCount(1); + if (!ItemStack.matches(displayPage, next)) { + displayPage = next; + setChanged(); + } + } public void setActiveCollection(int index) { if (index >= 0 && index < COLLECTIONS && activeCollection != index) { activeCollection = index; @@ -47,13 +59,17 @@ public final class WritingDeskBlockEntity extends BlockEntity implements Contain @Override public ItemStack getItem(int slot) { return items.get(slot); } @Override public ItemStack removeItem(int slot, int amount) { ItemStack removed = ContainerHelper.removeItem(items, slot, amount); - if (!removed.isEmpty()) setChanged(); + if (!removed.isEmpty()) { + if (slot < COLLECTIONS) displayPage = ItemStack.EMPTY; + setChanged(); + } return removed; } @Override public ItemStack removeItemNoUpdate(int slot) { return ContainerHelper.takeItem(items, slot); } @Override public void setItem(int slot, ItemStack stack) { items.set(slot, stack); if (stack.getCount() > getMaxStackSize()) stack.setCount(getMaxStackSize()); + if (slot < COLLECTIONS) displayPage = ItemStack.EMPTY; setChanged(); } @Override public boolean stillValid(Player player) { @@ -107,6 +123,7 @@ public final class WritingDeskBlockEntity extends BlockEntity implements Contain items.clear(); items = NonNullList.withSize(SIZE, ItemStack.EMPTY); inkRemaining = 0; + displayPage = ItemStack.EMPTY; setChanged(); } @Override protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { @@ -115,11 +132,27 @@ public final class WritingDeskBlockEntity extends BlockEntity implements Contain ContainerHelper.loadAllItems(tag, items, registries); activeCollection = Math.clamp(tag.getInt("ActiveCollection"), 0, COLLECTIONS - 1); inkRemaining = Math.clamp(tag.getInt("InkRemaining"), 0, InkVialItem.CAPACITY); + displayPage = tag.contains("DisplayPage", CompoundTag.TAG_COMPOUND) + ? ItemStack.parse(registries, tag.getCompound("DisplayPage")).orElse(ItemStack.EMPTY) + : ItemStack.EMPTY; } @Override protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { super.saveAdditional(tag, registries); ContainerHelper.saveAllItems(tag, items, registries); tag.putInt("ActiveCollection", activeCollection); tag.putInt("InkRemaining", inkRemaining); + if (!displayPage.isEmpty()) tag.put("DisplayPage", displayPage.save(registries)); + } + @Override public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + @Override public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + return saveWithoutMetadata(registries); + } + @Override public void setChanged() { + super.setChanged(); + if (level != null && !level.isClientSide) { + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2); + } } } diff --git a/src/main/java/net/dnorberg/rivencraft/client/ClientEvents.java b/src/main/java/net/dnorberg/rivencraft/client/ClientEvents.java index 32f4b92..2d580d5 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/ClientEvents.java +++ b/src/main/java/net/dnorberg/rivencraft/client/ClientEvents.java @@ -25,6 +25,7 @@ public final class ClientEvents { @SubscribeEvent public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) { event.registerBlockEntityRenderer(ModBlockEntities.BOOK_STAND.get(), BookStandRenderer::new); + event.registerBlockEntityRenderer(ModBlockEntities.WRITING_DESK.get(), WritingDeskRenderer::new); } @SubscribeEvent diff --git a/src/main/java/net/dnorberg/rivencraft/client/WritingDeskRenderer.java b/src/main/java/net/dnorberg/rivencraft/client/WritingDeskRenderer.java new file mode 100644 index 0000000..0eb0761 --- /dev/null +++ b/src/main/java/net/dnorberg/rivencraft/client/WritingDeskRenderer.java @@ -0,0 +1,55 @@ +package net.dnorberg.rivencraft.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import net.dnorberg.rivencraft.block.WritingDeskBlock; +import net.dnorberg.rivencraft.block.entity.WritingDeskBlockEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +/** Visible selected page and loaded paper, as on the Legacy desk. */ +public final class WritingDeskRenderer implements BlockEntityRenderer { + public WritingDeskRenderer(BlockEntityRendererProvider.Context context) {} + + @Override public void render(WritingDeskBlockEntity desk, float partialTick, PoseStack pose, + MultiBufferSource buffers, int light, int overlay) { + int paper = desk.getItem(WritingDeskBlockEntity.PAPER).getCount(); + ItemStack page = desk.displayPage(); + if (paper == 0 && page.isEmpty()) return; + pose.pushPose(); + pose.translate(0.5, 0, 0.5); + pose.mulPose(Axis.YP.rotationDegrees( + 180.0F - desk.getBlockState().getValue(WritingDeskBlock.FACING).toYRot())); + if (paper > 0) { + ItemStack sheet = new ItemStack(Items.PAPER); + int layers = Math.min(4, 1 + paper / 16); + for (int i = 0; i < layers; i++) { + drawFlat(desk, sheet, pose, buffers, light, overlay, 1.22, 0.27 + i * 0.008, -0.14, 0.55F); + } + } + if (!page.isEmpty()) { + drawFlat(desk, page, pose, buffers, light, overlay, 1.0, 0.572, 0.0, 0.8F); + } + pose.popPose(); + } + + private static void drawFlat(WritingDeskBlockEntity desk, ItemStack stack, PoseStack pose, + MultiBufferSource buffers, int light, int overlay, + double x, double y, double z, float scale) { + pose.pushPose(); + pose.translate(x, y, z); + pose.mulPose(Axis.XP.rotationDegrees(90)); + pose.scale(scale, scale, scale); + Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemDisplayContext.FIXED, + light, overlay, pose, buffers, desk.getLevel(), 0); + pose.popPose(); + } + + @Override public boolean shouldRenderOffScreen(WritingDeskBlockEntity blockEntity) { return true; } + @Override public int getViewDistance() { return 64; } +} diff --git a/src/main/java/net/dnorberg/rivencraft/client/screen/WritingDeskScreen.java b/src/main/java/net/dnorberg/rivencraft/client/screen/WritingDeskScreen.java index 314744f..c0fd52c 100644 --- a/src/main/java/net/dnorberg/rivencraft/client/screen/WritingDeskScreen.java +++ b/src/main/java/net/dnorberg/rivencraft/client/screen/WritingDeskScreen.java @@ -23,6 +23,8 @@ import net.minecraft.world.item.ItemStack; public final class WritingDeskScreen extends AbstractContainerScreen { private static final ResourceLocation PAGE_ATLAS = ResourceLocation.fromNamespaceAndPath( Rivencraft.MOD_ID, "textures/gui/notebook_pages.png"); + private static final ResourceLocation LEGACY_DESK = ResourceLocation.fromNamespaceAndPath( + Rivencraft.MOD_ID, "textures/gui/writing_desk_legacy.png"); private int lastCollection = -1; private int selectedPage; private int scrollRows; @@ -80,19 +82,21 @@ public final class WritingDeskScreen extends AbstractContainerScreen e.getItem().is(block.asItem())) + .mapToInt(e -> e.getItem().getCount()).sum(); + int paper = drops.stream().filter(e -> e.getItem().is(Items.PAPER)) + .mapToInt(e -> e.getItem().getCount()).sum(); + helper.assertValueEqual(desks, 1, "Breaking either half must drop one desk"); + helper.assertValueEqual(paper, 7, "Breaking either half must drop stored paper once"); + helper.succeed(); + } + + @GameTest(template = "empty") + public static void breakingControllerRemovesExtensionWithoutDuplicateDesk(GameTestHelper helper) { + BlockPos pos = helper.absolutePos(new BlockPos(1, 1, 1)); + var block = ModBlocks.WRITING_DESK.get(); + var state = block.defaultBlockState().setValue(WritingDeskBlock.FACING, Direction.NORTH); + helper.getLevel().setBlock(pos, state, 3); + block.setPlacedBy(helper.getLevel(), pos, state, null, new ItemStack(block)); + BlockPos extension = pos.relative(Direction.EAST); + helper.getLevel().destroyBlock(pos, true); + helper.assertTrue(helper.getLevel().getBlockState(extension).isAir(), + "Breaking the controller must remove the extension"); + var drops = helper.getLevel().getEntitiesOfClass(ItemEntity.class, new AABB(pos).inflate(3)); + int desks = drops.stream().filter(e -> e.getItem().is(block.asItem())) + .mapToInt(e -> e.getItem().getCount()).sum(); + helper.assertValueEqual(desks, 1, "Controller break must drop exactly one desk"); + helper.succeed(); + } + + @GameTest(template = "empty") + public static void openDeskDoesNotOccludeTerrain(GameTestHelper helper) { + helper.assertFalse(ModBlocks.WRITING_DESK.get().defaultBlockState().canOcclude(), + "Open shelves must not cull terrain behind the desk"); + helper.succeed(); + } } diff --git a/src/main/java/net/dnorberg/rivencraft/menu/WritingDeskMenu.java b/src/main/java/net/dnorberg/rivencraft/menu/WritingDeskMenu.java index 172b6f4..34a9942 100644 --- a/src/main/java/net/dnorberg/rivencraft/menu/WritingDeskMenu.java +++ b/src/main/java/net/dnorberg/rivencraft/menu/WritingDeskMenu.java @@ -181,6 +181,7 @@ public final class WritingDeskMenu extends AbstractContainerMenu { private void refreshOutput() { if (clientSide) return; + if (blockEntity != null) blockEntity.setDisplayPage(selectedSource()); ItemStack preview = canCopy() ? selectedSource().copyWithCount(1) : ItemStack.EMPTY; if (!ItemStack.matches(result.getItem(0), preview)) result.setItem(0, preview); } diff --git a/src/main/java/net/dnorberg/rivencraft/registry/ModBlocks.java b/src/main/java/net/dnorberg/rivencraft/registry/ModBlocks.java index 248f520..5ecd3f5 100644 --- a/src/main/java/net/dnorberg/rivencraft/registry/ModBlocks.java +++ b/src/main/java/net/dnorberg/rivencraft/registry/ModBlocks.java @@ -19,7 +19,7 @@ public final class ModBlocks { ); public static final DeferredBlock WRITING_DESK = BLOCKS.registerBlock( "writing_desk", WritingDeskBlock::new, - BlockBehaviour.Properties.ofFullCopy(Blocks.CRAFTING_TABLE) + BlockBehaviour.Properties.ofFullCopy(Blocks.CRAFTING_TABLE).noOcclusion() ); private ModBlocks() { diff --git a/src/main/resources/assets/rivencraft/blockstates/writing_desk.json b/src/main/resources/assets/rivencraft/blockstates/writing_desk.json index b860a13..b8e2086 100644 --- a/src/main/resources/assets/rivencraft/blockstates/writing_desk.json +++ b/src/main/resources/assets/rivencraft/blockstates/writing_desk.json @@ -1,8 +1,12 @@ { "variants": { - "facing=north": { "model": "rivencraft:block/writing_desk" }, - "facing=east": { "model": "rivencraft:block/writing_desk", "y": 90 }, - "facing=south": { "model": "rivencraft:block/writing_desk", "y": 180 }, - "facing=west": { "model": "rivencraft:block/writing_desk", "y": 270 } + "facing=north,extension=false": {"model":"rivencraft:block/writing_desk"}, + "facing=east,extension=false": {"model":"rivencraft:block/writing_desk","y":90}, + "facing=south,extension=false": {"model":"rivencraft:block/writing_desk","y":180}, + "facing=west,extension=false": {"model":"rivencraft:block/writing_desk","y":270}, + "facing=north,extension=true": {"model":"rivencraft:block/writing_desk_extension"}, + "facing=east,extension=true": {"model":"rivencraft:block/writing_desk_extension","y":90}, + "facing=south,extension=true": {"model":"rivencraft:block/writing_desk_extension","y":180}, + "facing=west,extension=true": {"model":"rivencraft:block/writing_desk_extension","y":270} } } diff --git a/src/main/resources/assets/rivencraft/models/block/writing_desk.json b/src/main/resources/assets/rivencraft/models/block/writing_desk.json index 84ad793..f095c27 100644 --- a/src/main/resources/assets/rivencraft/models/block/writing_desk.json +++ b/src/main/resources/assets/rivencraft/models/block/writing_desk.json @@ -1,69 +1,11 @@ { "parent": "minecraft:block/block", - "ambientocclusion": false, - "textures": { - "particle": "rivencraft:block/writing_desk", - "desk": "rivencraft:block/writing_desk" - }, + "textures": {"wood":"rivencraft:block/writing_desk_wood","inlay":"rivencraft:block/writing_desk_inlay","particle":"rivencraft:block/writing_desk_wood"}, "elements": [ - { - "from": [0, 8, 0], "to": [16, 9, 16], - "faces": { - "up": {"uv": [1, 0, 3, 2], "texture": "#desk"}, - "down": {"uv": [1, 2, 3, 4], "texture": "#desk"}, - "north": {"uv": [1, 0, 3, 0.125], "texture": "#desk"}, - "south": {"uv": [1, 0, 3, 0.125], "texture": "#desk"}, - "east": {"uv": [1, 0, 3, 0.125], "texture": "#desk"}, - "west": {"uv": [1, 0, 3, 0.125], "texture": "#desk"} - } - }, - { - "from": [0, 0, 1], "to": [2, 8, 15], - "faces": { - "north": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"}, - "south": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"}, - "east": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"}, - "west": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"} - } - }, - { - "from": [14, 0, 1], "to": [16, 8, 15], - "faces": { - "north": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"}, - "south": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"}, - "east": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"}, - "west": {"uv": [5.625, 0.125, 5.875, 2], "texture": "#desk"} - } - }, - { - "from": [1, 3, 2], "to": [15, 4, 14], - "faces": { - "up": {"uv": [0, 4.25, 3.75, 6.125], "texture": "#desk"}, - "down": {"uv": [0, 4.25, 3.75, 6.125], "texture": "#desk"}, - "north": {"uv": [0, 4.25, 3.75, 4.5], "texture": "#desk"}, - "south": {"uv": [0, 4.25, 3.75, 4.5], "texture": "#desk"}, - "east": {"uv": [0, 4.25, 3.75, 4.5], "texture": "#desk"}, - "west": {"uv": [0, 4.25, 3.75, 4.5], "texture": "#desk"} - } - }, - { - "from": [1, 9, 14], "to": [15, 15, 16], - "faces": { - "north": {"uv": [8, 0, 11.75, 2], "texture": "#desk"}, - "south": {"uv": [8, 0, 11.75, 2], "texture": "#desk"}, - "east": {"uv": [8, 0, 8.25, 2], "texture": "#desk"}, - "west": {"uv": [8, 0, 8.25, 2], "texture": "#desk"}, - "up": {"uv": [8, 0, 11.75, 0.25], "texture": "#desk"} - } - }, - { - "from": [1, 12, 9], "to": [15, 13, 15], - "faces": { - "up": {"uv": [8, 3.625, 11.75, 4.375], "texture": "#desk"}, - "down": {"uv": [8, 3.625, 11.75, 4.375], "texture": "#desk"}, - "north": {"uv": [8, 3.625, 11.75, 3.75], "texture": "#desk"}, - "south": {"uv": [8, 3.625, 11.75, 3.75], "texture": "#desk"} - } - } + {"from":[0,0,1],"to":[16,1,15],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[0,8,0],"to":[16,9,16],"faces":{"up":{"texture":"#inlay"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[0,0,1],"to":[1,8,15],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[1,3,1],"to":[16,4,15],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[0,9,15],"to":[16,15,16],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}} ] } diff --git a/src/main/resources/assets/rivencraft/models/block/writing_desk_extension.json b/src/main/resources/assets/rivencraft/models/block/writing_desk_extension.json new file mode 100644 index 0000000..12685bf --- /dev/null +++ b/src/main/resources/assets/rivencraft/models/block/writing_desk_extension.json @@ -0,0 +1,11 @@ +{ + "parent": "minecraft:block/block", + "textures": {"wood":"rivencraft:block/writing_desk_wood","inlay":"rivencraft:block/writing_desk_inlay","particle":"rivencraft:block/writing_desk_wood"}, + "elements": [ + {"from":[0,0,1],"to":[16,1,15],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[0,8,0],"to":[16,9,16],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[15,0,1],"to":[16,8,15],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[0,3,1],"to":[15,4,15],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}}, + {"from":[0,9,15],"to":[16,15,16],"faces":{"up":{"texture":"#wood"},"down":{"texture":"#wood"},"north":{"texture":"#wood"},"south":{"texture":"#wood"},"east":{"texture":"#wood"},"west":{"texture":"#wood"}}} + ] +} diff --git a/src/main/resources/assets/rivencraft/models/item/writing_desk.json b/src/main/resources/assets/rivencraft/models/item/writing_desk.json index 7d99ef8..9dc2eda 100644 --- a/src/main/resources/assets/rivencraft/models/item/writing_desk.json +++ b/src/main/resources/assets/rivencraft/models/item/writing_desk.json @@ -1,3 +1,4 @@ { - "parent": "rivencraft:block/writing_desk" + "parent": "minecraft:item/generated", + "textures": {"layer0": "rivencraft:item/writing_desk"} } diff --git a/src/main/resources/assets/rivencraft/textures/block/writing_desk_inlay.png b/src/main/resources/assets/rivencraft/textures/block/writing_desk_inlay.png new file mode 100644 index 0000000..205f1a8 Binary files /dev/null and b/src/main/resources/assets/rivencraft/textures/block/writing_desk_inlay.png differ diff --git a/src/main/resources/assets/rivencraft/textures/block/writing_desk_wood.png b/src/main/resources/assets/rivencraft/textures/block/writing_desk_wood.png new file mode 100644 index 0000000..8dd0645 Binary files /dev/null and b/src/main/resources/assets/rivencraft/textures/block/writing_desk_wood.png differ diff --git a/src/main/resources/assets/rivencraft/textures/gui/writing_desk_legacy.png b/src/main/resources/assets/rivencraft/textures/gui/writing_desk_legacy.png new file mode 100644 index 0000000..32cea7a Binary files /dev/null and b/src/main/resources/assets/rivencraft/textures/gui/writing_desk_legacy.png differ