Public Access
This commit is contained in:
1 parent
0e602f0154
commit
3109938a97
15 files changed
+390
-8
No files matched your search
@@ -18,6 +18,12 @@ there. The destination is stored on the item and survives inventory and world
|
|||||||
saves. Travel only succeeds if the target dimension is loaded and a solid,
|
saves. Travel only succeeds if the target dimension is loaded and a solid,
|
||||||
collision-free landing position can be found nearby.
|
collision-free landing position can be found nearby.
|
||||||
|
|
||||||
|
Right-click an empty vanilla lectern with a Rivencraft book to convert it into
|
||||||
|
a Book Stand and place the book on it. Use a Linking Book on the stand by
|
||||||
|
right-clicking with an empty hand. Sneak-right-click with an empty hand to take
|
||||||
|
the book back and restore the vanilla lectern. Breaking a Book Stand drops both
|
||||||
|
the stored book and a vanilla lectern.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- A Java 21 JDK
|
- A Java 21 JDK
|
||||||
|
|||||||
+13
-1
@@ -46,7 +46,8 @@ the symbol grammar is introduced.
|
|||||||
- [x] Nearby landing search and clear failure messages.
|
- [x] Nearby landing search and clear failure messages.
|
||||||
- [x] Descriptive Book identity and Age reference components.
|
- [x] Descriptive Book identity and Age reference components.
|
||||||
- [ ] Return-link creation as part of Descriptive Book travel.
|
- [ ] Return-link creation as part of Descriptive Book travel.
|
||||||
- [ ] Lectern/book-stand interaction.
|
- [x] Lectern-to-Book-Stand conversion, displayed book, activation, removal,
|
||||||
|
persistence, and drops.
|
||||||
- [ ] Automated in-game tests for binding, persistence, and travel.
|
- [ ] Automated in-game tests for binding, persistence, and travel.
|
||||||
|
|
||||||
The temporary shapeless Linking Book recipe makes the linking subsystem easy
|
The temporary shapeless Linking Book recipe makes the linking subsystem easy
|
||||||
@@ -57,6 +58,17 @@ Age references use UUIDs rather than dimension keys. Milestone 3 will own the
|
|||||||
mapping from that stable identity to server data and a runtime dimension. This
|
mapping from that stable identity to server data and a runtime dimension. This
|
||||||
keeps saved books valid if an Age is migrated or regenerated.
|
keeps saved books valid if an Age is migrated or regenerated.
|
||||||
|
|
||||||
|
Vanilla lecterns accept extensible item tags when inserting books, but their
|
||||||
|
block entity still validates only vanilla writable and written books. To avoid
|
||||||
|
an invalid lectern state, inserting a Rivencraft book converts the lectern into
|
||||||
|
a visually compatible Rivencraft Book Stand. Removing the book converts it
|
||||||
|
back.
|
||||||
|
|
||||||
|
Mystcraft Legacy did not impose an item cooldown when linking. Rivencraft's
|
||||||
|
initial cooldown used Minecraft's item-type cooldown system, which delayed all
|
||||||
|
Linking Book stacks at once. Version 0.1.3 removes that cooldown to match the
|
||||||
|
legacy behavior.
|
||||||
|
|
||||||
## Version policy
|
## Version policy
|
||||||
|
|
||||||
Versions follow `x.y.z`:
|
Versions follow `x.y.z`:
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ mod_name=Rivencraft
|
|||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# 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
|
mod_license=LGPL-3.0-or-later
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=0.1.2
|
mod_version=0.1.3
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# 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.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import com.mojang.logging.LogUtils;
|
|||||||
import net.dnorberg.rivencraft.registry.ModCreativeTabs;
|
import net.dnorberg.rivencraft.registry.ModCreativeTabs;
|
||||||
import net.dnorberg.rivencraft.registry.ModDataComponents;
|
import net.dnorberg.rivencraft.registry.ModDataComponents;
|
||||||
import net.dnorberg.rivencraft.registry.ModItems;
|
import net.dnorberg.rivencraft.registry.ModItems;
|
||||||
|
import net.dnorberg.rivencraft.registry.ModBlocks;
|
||||||
|
import net.dnorberg.rivencraft.registry.ModBlockEntities;
|
||||||
|
import net.dnorberg.rivencraft.event.BookStandConversionHandler;
|
||||||
import net.neoforged.bus.api.IEventBus;
|
import net.neoforged.bus.api.IEventBus;
|
||||||
import net.neoforged.fml.common.Mod;
|
import net.neoforged.fml.common.Mod;
|
||||||
|
import net.neoforged.neoforge.common.NeoForge;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
@Mod(Rivencraft.MOD_ID)
|
@Mod(Rivencraft.MOD_ID)
|
||||||
@@ -15,8 +19,11 @@ public final class Rivencraft {
|
|||||||
|
|
||||||
public Rivencraft(IEventBus modEventBus) {
|
public Rivencraft(IEventBus modEventBus) {
|
||||||
ModDataComponents.register(modEventBus);
|
ModDataComponents.register(modEventBus);
|
||||||
|
ModBlocks.register(modEventBus);
|
||||||
|
ModBlockEntities.register(modEventBus);
|
||||||
ModItems.register(modEventBus);
|
ModItems.register(modEventBus);
|
||||||
ModCreativeTabs.register(modEventBus);
|
ModCreativeTabs.register(modEventBus);
|
||||||
|
NeoForge.EVENT_BUS.addListener(BookStandConversionHandler::onRightClickBlock);
|
||||||
LOGGER.info("Initializing Rivencraft");
|
LOGGER.info("Initializing Rivencraft");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package net.dnorberg.rivencraft.block;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
|
||||||
|
import net.dnorberg.rivencraft.item.LinkingBookItem;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.LecternBlock;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
|
||||||
|
/** A lectern-compatible stand that safely stores and activates Rivencraft books. */
|
||||||
|
public final class BookStandBlock extends LecternBlock {
|
||||||
|
public static final MapCodec<LecternBlock> CODEC = simpleCodec(BookStandBlock::new);
|
||||||
|
|
||||||
|
public BookStandBlock(BlockBehaviour.Properties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapCodec<LecternBlock> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
return new BookStandBlockEntity(pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected InteractionResult useWithoutItem(
|
||||||
|
BlockState state,
|
||||||
|
Level level,
|
||||||
|
BlockPos pos,
|
||||||
|
Player player,
|
||||||
|
BlockHitResult hitResult
|
||||||
|
) {
|
||||||
|
if (!(level.getBlockEntity(pos) instanceof BookStandBlockEntity stand)) {
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.isShiftKeyDown()) {
|
||||||
|
if (!level.isClientSide) {
|
||||||
|
ItemStack book = stand.takeBook();
|
||||||
|
BlockState lectern = Blocks.LECTERN.defaultBlockState()
|
||||||
|
.setValue(FACING, state.getValue(FACING));
|
||||||
|
level.setBlock(pos, lectern, 3);
|
||||||
|
if (!player.getInventory().add(book)) {
|
||||||
|
player.drop(book, false);
|
||||||
|
}
|
||||||
|
level.playSound(null, pos, SoundEvents.BOOK_PAGE_TURN, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack book = stand.getBook();
|
||||||
|
if (book.getItem() instanceof LinkingBookItem && player instanceof ServerPlayer serverPlayer) {
|
||||||
|
LinkingBookItem.useBoundBook(serverPlayer, book);
|
||||||
|
}
|
||||||
|
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||||
|
if (!state.is(newState.getBlock()) && level.getBlockEntity(pos) instanceof BookStandBlockEntity stand) {
|
||||||
|
ItemStack book = stand.takeBook();
|
||||||
|
if (!book.isEmpty()) {
|
||||||
|
ItemEntity droppedBook = new ItemEntity(
|
||||||
|
level,
|
||||||
|
pos.getX() + 0.5,
|
||||||
|
pos.getY() + 1.0,
|
||||||
|
pos.getZ() + 0.5,
|
||||||
|
book
|
||||||
|
);
|
||||||
|
droppedBook.setDefaultPickUpDelay();
|
||||||
|
level.addFreshEntity(droppedBook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onRemove(state, level, pos, newState, isMoving);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package net.dnorberg.rivencraft.block.entity;
|
||||||
|
|
||||||
|
import net.dnorberg.rivencraft.registry.ModBlockEntities;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public final class BookStandBlockEntity extends BlockEntity {
|
||||||
|
private static final String BOOK_TAG = "Book";
|
||||||
|
private ItemStack book = ItemStack.EMPTY;
|
||||||
|
|
||||||
|
public BookStandBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
super(ModBlockEntities.BOOK_STAND.get(), pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getBook() {
|
||||||
|
return book;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBook(ItemStack book) {
|
||||||
|
this.book = book;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack takeBook() {
|
||||||
|
ItemStack result = book;
|
||||||
|
book = ItemStack.EMPTY;
|
||||||
|
setChanged();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
|
super.loadAdditional(tag, registries);
|
||||||
|
book = tag.contains(BOOK_TAG, CompoundTag.TAG_COMPOUND)
|
||||||
|
? ItemStack.parse(registries, tag.getCompound(BOOK_TAG)).orElse(ItemStack.EMPTY)
|
||||||
|
: ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
|
super.saveAdditional(tag, registries);
|
||||||
|
if (!book.isEmpty()) {
|
||||||
|
tag.put(BOOK_TAG, book.save(registries));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package net.dnorberg.rivencraft.client;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import com.mojang.math.Axis;
|
||||||
|
import net.dnorberg.rivencraft.block.BookStandBlock;
|
||||||
|
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
|
||||||
|
import net.minecraft.client.model.BookModel;
|
||||||
|
import net.minecraft.client.model.geom.ModelLayers;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
|
import net.minecraft.client.renderer.blockentity.EnchantTableRenderer;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public final class BookStandRenderer implements BlockEntityRenderer<BookStandBlockEntity> {
|
||||||
|
private final BookModel bookModel;
|
||||||
|
|
||||||
|
public BookStandRenderer(BlockEntityRendererProvider.Context context) {
|
||||||
|
bookModel = new BookModel(context.bakeLayer(ModelLayers.BOOK));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(
|
||||||
|
BookStandBlockEntity blockEntity,
|
||||||
|
float partialTick,
|
||||||
|
PoseStack poseStack,
|
||||||
|
MultiBufferSource bufferSource,
|
||||||
|
int packedLight,
|
||||||
|
int packedOverlay
|
||||||
|
) {
|
||||||
|
BlockState state = blockEntity.getBlockState();
|
||||||
|
if (!state.getValue(BookStandBlock.HAS_BOOK)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.translate(0.5F, 1.0625F, 0.5F);
|
||||||
|
float rotation = state.getValue(BookStandBlock.FACING).getClockWise().toYRot();
|
||||||
|
poseStack.mulPose(Axis.YP.rotationDegrees(-rotation));
|
||||||
|
poseStack.mulPose(Axis.ZP.rotationDegrees(67.5F));
|
||||||
|
poseStack.translate(0.0F, -0.125F, 0.0F);
|
||||||
|
bookModel.setupAnim(0.0F, 0.1F, 0.9F, 1.2F);
|
||||||
|
VertexConsumer consumer = EnchantTableRenderer.BOOK_LOCATION.buffer(bufferSource, RenderType::entitySolid);
|
||||||
|
bookModel.render(poseStack, consumer, packedLight, packedOverlay, -1);
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package net.dnorberg.rivencraft.client;
|
||||||
|
|
||||||
|
import net.dnorberg.rivencraft.Rivencraft;
|
||||||
|
import net.dnorberg.rivencraft.registry.ModBlockEntities;
|
||||||
|
import net.neoforged.api.distmarker.Dist;
|
||||||
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
|
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
||||||
|
|
||||||
|
@EventBusSubscriber(modid = Rivencraft.MOD_ID, value = Dist.CLIENT)
|
||||||
|
public final class ClientEvents {
|
||||||
|
private ClientEvents() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
|
||||||
|
event.registerBlockEntityRenderer(ModBlockEntities.BOOK_STAND.get(), BookStandRenderer::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package net.dnorberg.rivencraft.event;
|
||||||
|
|
||||||
|
import net.dnorberg.rivencraft.block.BookStandBlock;
|
||||||
|
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
|
||||||
|
import net.dnorberg.rivencraft.registry.ModBlocks;
|
||||||
|
import net.dnorberg.rivencraft.registry.ModItems;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.LecternBlock;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
|
||||||
|
|
||||||
|
public final class BookStandConversionHandler {
|
||||||
|
private BookStandConversionHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onRightClickBlock(PlayerInteractEvent.RightClickBlock event) {
|
||||||
|
ItemStack heldBook = event.getItemStack();
|
||||||
|
if (!heldBook.is(ModItems.LINKING_BOOK.get()) && !heldBook.is(ModItems.DESCRIPTIVE_BOOK.get())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockState lectern = event.getLevel().getBlockState(event.getPos());
|
||||||
|
if (!lectern.is(Blocks.LECTERN) || lectern.getValue(LecternBlock.HAS_BOOK)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.setCanceled(true);
|
||||||
|
event.setCancellationResult(InteractionResult.sidedSuccess(event.getLevel().isClientSide));
|
||||||
|
if (event.getLevel().isClientSide) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockState bookStand = ModBlocks.BOOK_STAND.get().defaultBlockState()
|
||||||
|
.setValue(BookStandBlock.FACING, lectern.getValue(LecternBlock.FACING))
|
||||||
|
.setValue(BookStandBlock.HAS_BOOK, true);
|
||||||
|
event.getLevel().setBlock(event.getPos(), bookStand, 3);
|
||||||
|
if (event.getLevel().getBlockEntity(event.getPos()) instanceof BookStandBlockEntity stand) {
|
||||||
|
stand.setBook(heldBook.consumeAndReturn(1, event.getEntity()));
|
||||||
|
}
|
||||||
|
event.getLevel().playSound(
|
||||||
|
null,
|
||||||
|
event.getPos(),
|
||||||
|
SoundEvents.BOOK_PUT,
|
||||||
|
SoundSource.BLOCKS,
|
||||||
|
1.0F,
|
||||||
|
1.0F
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,8 +20,6 @@ import net.minecraft.world.item.TooltipFlag;
|
|||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public final class LinkingBookItem extends Item {
|
public final class LinkingBookItem extends Item {
|
||||||
private static final int LINK_COOLDOWN_TICKS = 40;
|
|
||||||
|
|
||||||
public LinkingBookItem(Properties properties) {
|
public LinkingBookItem(Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
}
|
}
|
||||||
@@ -47,12 +45,21 @@ public final class LinkingBookItem extends Item {
|
|||||||
return InteractionResultHolder.success(stack);
|
return InteractionResultHolder.success(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkingService.LinkResult result = LinkingService.travel(serverPlayer, target);
|
return useBoundBook(serverPlayer, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InteractionResultHolder<ItemStack> useBoundBook(ServerPlayer player, ItemStack stack) {
|
||||||
|
LinkTarget target = stack.get(ModDataComponents.LINK_TARGET.get());
|
||||||
|
if (target == null) {
|
||||||
|
player.displayClientMessage(Component.translatable("message.rivencraft.linking_book.unbound"), true);
|
||||||
|
return InteractionResultHolder.fail(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkingService.LinkResult result = LinkingService.travel(player, target);
|
||||||
if (result == LinkingService.LinkResult.SUCCESS) {
|
if (result == LinkingService.LinkResult.SUCCESS) {
|
||||||
serverPlayer.getCooldowns().addCooldown(this, LINK_COOLDOWN_TICKS);
|
player.level().playSound(
|
||||||
serverPlayer.level().playSound(
|
|
||||||
null,
|
null,
|
||||||
serverPlayer.blockPosition(),
|
player.blockPosition(),
|
||||||
SoundEvents.PORTAL_TRAVEL,
|
SoundEvents.PORTAL_TRAVEL,
|
||||||
SoundSource.PLAYERS,
|
SoundSource.PLAYERS,
|
||||||
0.35F,
|
0.35F,
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package net.dnorberg.rivencraft.registry;
|
||||||
|
|
||||||
|
import net.dnorberg.rivencraft.Rivencraft;
|
||||||
|
import net.dnorberg.rivencraft.block.entity.BookStandBlockEntity;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.neoforged.bus.api.IEventBus;
|
||||||
|
import net.neoforged.neoforge.registries.DeferredHolder;
|
||||||
|
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||||
|
|
||||||
|
public final class ModBlockEntities {
|
||||||
|
private static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES =
|
||||||
|
DeferredRegister.create(Registries.BLOCK_ENTITY_TYPE, Rivencraft.MOD_ID);
|
||||||
|
|
||||||
|
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<BookStandBlockEntity>> BOOK_STAND =
|
||||||
|
BLOCK_ENTITIES.register("book_stand", () -> BlockEntityType.Builder
|
||||||
|
.of(BookStandBlockEntity::new, ModBlocks.BOOK_STAND.get())
|
||||||
|
.build(null));
|
||||||
|
|
||||||
|
private ModBlockEntities() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(IEventBus modEventBus) {
|
||||||
|
BLOCK_ENTITIES.register(modEventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package net.dnorberg.rivencraft.registry;
|
||||||
|
|
||||||
|
import net.dnorberg.rivencraft.Rivencraft;
|
||||||
|
import net.dnorberg.rivencraft.block.BookStandBlock;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
|
import net.neoforged.bus.api.IEventBus;
|
||||||
|
import net.neoforged.neoforge.registries.DeferredBlock;
|
||||||
|
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||||
|
|
||||||
|
public final class ModBlocks {
|
||||||
|
private static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(Rivencraft.MOD_ID);
|
||||||
|
|
||||||
|
public static final DeferredBlock<BookStandBlock> BOOK_STAND = BLOCKS.registerBlock(
|
||||||
|
"book_stand",
|
||||||
|
BookStandBlock::new,
|
||||||
|
BlockBehaviour.Properties.ofFullCopy(Blocks.LECTERN)
|
||||||
|
);
|
||||||
|
|
||||||
|
private ModBlocks() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(IEventBus modEventBus) {
|
||||||
|
BLOCKS.register(modEventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=east": {
|
||||||
|
"model": "minecraft:block/lectern",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=north": {
|
||||||
|
"model": "minecraft:block/lectern"
|
||||||
|
},
|
||||||
|
"facing=south": {
|
||||||
|
"model": "minecraft:block/lectern",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west": {
|
||||||
|
"model": "minecraft:block/lectern",
|
||||||
|
"y": 270
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
"item.rivencraft.linking_book.unbound": "Unbound — sneak-use to bind",
|
"item.rivencraft.linking_book.unbound": "Unbound — sneak-use to bind",
|
||||||
"item.rivencraft.linking_book.destination": "%s (%s, %s, %s)",
|
"item.rivencraft.linking_book.destination": "%s (%s, %s, %s)",
|
||||||
"message.rivencraft.linking_book.bind_hint": "Sneak-use to bind this book to your current location",
|
"message.rivencraft.linking_book.bind_hint": "Sneak-use to bind this book to your current location",
|
||||||
|
"message.rivencraft.linking_book.unbound": "This Linking Book is unbound",
|
||||||
"message.rivencraft.linking_book.bound": "Linking Book bound",
|
"message.rivencraft.linking_book.bound": "Linking Book bound",
|
||||||
"message.rivencraft.linking_book.linked": "Linked",
|
"message.rivencraft.linking_book.linked": "Linked",
|
||||||
"message.rivencraft.linking_book.missing_dimension": "That dimension is unavailable",
|
"message.rivencraft.linking_book.missing_dimension": "That dimension is unavailable",
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"bonus_rolls": 0.0,
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "minecraft:lectern"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rolls": 1.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"random_sequence": "rivencraft:blocks/book_stand"
|
||||||
|
}
|
||||||
Reference in new issue
Block a user