Complete bootstrap milestone
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-09-21 06:38:44 -04:00
1 parent 8e3baefa3b
commit db768bb4f7
7 files changed
+103 -29

No files matched your search

+4 -3
View File
@@ -4,9 +4,10 @@ Rivencraft is a clean, incremental port of the ideas and gameplay of
[Mystcraft Legacy](https://github.com/Mystcraft/Mystcraft-Legacy) to Minecraft [Mystcraft Legacy](https://github.com/Mystcraft/Mystcraft-Legacy) to Minecraft
1.21.1 on NeoForge. 1.21.1 on NeoForge.
The project is at the bootstrap stage. It currently provides a valid NeoForge The bootstrap milestone is complete. The project currently provides a valid
mod, a creative tab, and a placeholder Descriptive Book item. Age generation, NeoForge mod, a creative tab, and an unwritten Descriptive Book item. Age
linking, symbols, instability, and writing mechanics have not been ported yet. generation, linking, symbols, instability, and writing mechanics have not been
ported yet.
## Requirements ## Requirements
+9 -1
View File
@@ -8,7 +8,7 @@ split into independently testable milestones.
## Milestones ## Milestones
1. **Bootstrap** — NeoForge 1.21.1 build, mod metadata, item registration, and 1. **Bootstrap** — NeoForge 1.21.1 build, mod metadata, item registration, and
CI. (In progress.) CI. **Complete.**
2. **Books and linking** — descriptive/linking book data components, lectern-like 2. **Books and linking** — descriptive/linking book data components, lectern-like
interaction, safe teleportation, and return links. interaction, safe teleportation, and return links.
3. **Ages** — dimension definitions backed by data packs, deterministic seeds, 3. **Ages** — dimension definitions backed by data packs, deterministic seeds,
@@ -36,3 +36,11 @@ The first functional target is: create a Descriptive Book, bind it to one
server-managed Age definition, travel to that Age, and use a Linking Book to server-managed Age definition, travel to that Age, and use a Linking Book to
return. This exercises persistence, networking, dimensions, and safety before return. This exercises persistence, networking, dimensions, and safety before
the symbol grammar is introduced. the symbol grammar is introduced.
## Milestone 1 acceptance record
- The project builds on a Java 21 JDK with `./gradlew build`.
- Mod identity and dependencies are declared in generated NeoForge metadata.
- Registrations are isolated by registry type and use deferred registration.
- The Descriptive Book loads with a model, name, tooltip, and creative tab.
- CI builds every pushed commit and pull request.
@@ -1,15 +1,10 @@
package net.dnorberg.rivencraft; package net.dnorberg.rivencraft;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
import net.minecraft.core.registries.Registries; import net.dnorberg.rivencraft.registry.ModCreativeTabs;
import net.minecraft.network.chat.Component; import net.dnorberg.rivencraft.registry.ModItems;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
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.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
import org.slf4j.Logger; import org.slf4j.Logger;
@Mod(Rivencraft.MOD_ID) @Mod(Rivencraft.MOD_ID)
@@ -17,25 +12,9 @@ public final class Rivencraft {
public static final String MOD_ID = "rivencraft"; public static final String MOD_ID = "rivencraft";
public static final Logger LOGGER = LogUtils.getLogger(); public static final Logger LOGGER = LogUtils.getLogger();
private static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MOD_ID);
private static final DeferredRegister<CreativeModeTab> CREATIVE_TABS =
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MOD_ID);
public static final DeferredItem<Item> DESCRIPTIVE_BOOK = ITEMS.registerSimpleItem(
"descriptive_book",
new Item.Properties().stacksTo(1)
);
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> RIVENCRAFT_TAB =
CREATIVE_TABS.register("rivencraft", () -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.rivencraft"))
.icon(() -> DESCRIPTIVE_BOOK.get().getDefaultInstance())
.displayItems((parameters, output) -> output.accept(DESCRIPTIVE_BOOK.get()))
.build());
public Rivencraft(IEventBus modEventBus) { public Rivencraft(IEventBus modEventBus) {
ITEMS.register(modEventBus); ModItems.register(modEventBus);
CREATIVE_TABS.register(modEventBus); ModCreativeTabs.register(modEventBus);
LOGGER.info("Initializing Rivencraft"); LOGGER.info("Initializing Rivencraft");
} }
} }
@@ -0,0 +1,32 @@
package net.dnorberg.rivencraft.item;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
/**
* A book that will eventually describe and link to a generated Age.
*
* <p>The bootstrap implementation deliberately has no interaction behavior.
* Binding and travel belong to the books-and-linking milestone, where their
* server-authoritative data model can be introduced together.</p>
*/
public final class DescriptiveBookItem extends Item {
public DescriptiveBookItem(Properties properties) {
super(properties);
}
@Override
public void appendHoverText(
ItemStack stack,
TooltipContext context,
List<Component> tooltipComponents,
TooltipFlag tooltipFlag
) {
tooltipComponents.add(Component.translatable("item.rivencraft.descriptive_book.unwritten")
.withStyle(ChatFormatting.GRAY));
}
}
@@ -0,0 +1,28 @@
package net.dnorberg.rivencraft.registry;
import net.dnorberg.rivencraft.Rivencraft;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.CreativeModeTab;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
public final class ModCreativeTabs {
private static final DeferredRegister<CreativeModeTab> CREATIVE_TABS =
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Rivencraft.MOD_ID);
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> RIVENCRAFT =
CREATIVE_TABS.register("rivencraft", () -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.rivencraft"))
.icon(() -> ModItems.DESCRIPTIVE_BOOK.get().getDefaultInstance())
.displayItems((parameters, output) -> output.accept(ModItems.DESCRIPTIVE_BOOK.get()))
.build());
private ModCreativeTabs() {
}
public static void register(IEventBus modEventBus) {
CREATIVE_TABS.register(modEventBus);
}
}
@@ -0,0 +1,25 @@
package net.dnorberg.rivencraft.registry;
import net.dnorberg.rivencraft.Rivencraft;
import net.dnorberg.rivencraft.item.DescriptiveBookItem;
import net.minecraft.world.item.Item;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
public final class ModItems {
private static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(Rivencraft.MOD_ID);
public static final DeferredItem<DescriptiveBookItem> DESCRIPTIVE_BOOK = ITEMS.registerItem(
"descriptive_book",
DescriptiveBookItem::new,
new Item.Properties().stacksTo(1)
);
private ModItems() {
}
public static void register(IEventBus modEventBus) {
ITEMS.register(modEventBus);
}
}
@@ -1,4 +1,5 @@
{ {
"item.rivencraft.descriptive_book": "Descriptive Book", "item.rivencraft.descriptive_book": "Descriptive Book",
"item.rivencraft.descriptive_book.unwritten": "Unwritten",
"itemGroup.rivencraft": "Rivencraft" "itemGroup.rivencraft": "Rivencraft"
} }