1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-31 13:42:59 +00:00

Clean up Javadocs a little

I've no motivation for modding right now, but always got time for build
system busywork!

CC:T (and CC before that) has always published its API docs. However,
they're not always the most helpful — they're useful if you know what
you're looking for, but aren't a good getting-started guide.

Part of the issue here is there's no examples, and everything is
described pretty abstractly. I have occasionally tried to improve this
(e.g. the peripheral docs in bdffabc08e),
but it's a long road.

This commit adds a new example mod, which registers peripherals, an API
and a turtle upgrade. While the mod itself isn't exported as part of the
docs, we reference blocks of it using Java's new {@snippet} tag.

 - Switch the Forge project to use NeoForge's new Legacy MDG plugin. We
   don't *need* to do this, but it means the build logic for Forge and
   NeoForge is more closely aligned.

 - Add a new SnippetTaglet, which is a partial backport of Java 18+'s
   {@snippet}.

 - Add an example mod. This is a working multi-loader mod, complete with
   datagen (albeit with no good multi-loader abstractions).

 - Move our existing <pre>{@code ...}</pre> blocks into the example mod,
   replacing them with {@snippet}s.

 - Add a new overview page to the docs, providing some getting-started
   information. We had this already in the dan200.computercraft.api
   package docs, but it's not especially visible there.
This commit is contained in:
Jonathan Coates
2025-01-09 20:47:51 +00:00
parent d9fc1c3a80
commit 3c46b8acd7
57 changed files with 1089 additions and 616 deletions

View File

@@ -0,0 +1,92 @@
package com.example.examplemod;
import com.example.examplemod.peripheral.BrewingStandPeripheral;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.CapabilityToken;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.RegisterEvent;
import javax.annotation.Nullable;
import java.util.function.Function;
/**
* The main entry point for the Forge version of our example mod.
*/
@Mod(ExampleMod.MOD_ID)
public class ForgeExampleMod {
public ForgeExampleMod() {
// Register our turtle upgrade. If writing a Forge-only mod, you'd normally use DeferredRegister instead.
// However, this is an easy way to implement this in a multi-loader-compatible manner.
// @start region=turtle_upgrades
var modBus = FMLJavaModLoadingContext.get().getModEventBus();
modBus.addListener((RegisterEvent event) -> {
event.register(TurtleUpgradeSerialiser.registryId(), new ResourceLocation(ExampleMod.MOD_ID, "example_turtle_upgrade"), () -> ExampleMod.EXAMPLE_TURTLE_UPGRADE);
});
// @end region=turtle_upgrades
modBus.addListener((FMLCommonSetupEvent event) -> ExampleMod.registerComputerCraft());
MinecraftForge.EVENT_BUS.addGenericListener(BlockEntity.class, ForgeExampleMod::attachPeripherals);
}
// @start region=peripherals
// The main function to attach peripherals to block entities. This should be added to the Forge event bus.
public static void attachPeripherals(AttachCapabilitiesEvent<BlockEntity> event) {
if (event.getObject() instanceof BrewingStandBlockEntity brewingStand) {
PeripheralProvider.attach(event, brewingStand, BrewingStandPeripheral::new);
}
}
// Boilerplate for adding a new capability provider
public static final Capability<IPeripheral> CAPABILITY_PERIPHERAL = CapabilityManager.get(new CapabilityToken<>() {
});
private static final ResourceLocation PERIPHERAL = new ResourceLocation(ExampleMod.MOD_ID, "peripheral");
// A {@link ICapabilityProvider} that lazily creates an {@link IPeripheral} when required.
private static final class PeripheralProvider<O extends BlockEntity> implements ICapabilityProvider {
private final O blockEntity;
private final Function<O, IPeripheral> factory;
private @Nullable LazyOptional<IPeripheral> peripheral;
private PeripheralProvider(O blockEntity, Function<O, IPeripheral> factory) {
this.blockEntity = blockEntity;
this.factory = factory;
}
private static <O extends BlockEntity> void attach(AttachCapabilitiesEvent<BlockEntity> event, O blockEntity, Function<O, IPeripheral> factory) {
var provider = new PeripheralProvider<>(blockEntity, factory);
event.addCapability(PERIPHERAL, provider);
event.addListener(provider::invalidate);
}
private void invalidate() {
if (peripheral != null) peripheral.invalidate();
peripheral = null;
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction direction) {
if (capability != CAPABILITY_PERIPHERAL) return LazyOptional.empty();
if (blockEntity.isRemoved()) return LazyOptional.empty();
var peripheral = this.peripheral;
return (peripheral == null ? (this.peripheral = LazyOptional.of(() -> factory.apply(blockEntity))) : peripheral).cast();
}
}
// @end region=peripherals
}

View File

@@ -0,0 +1,20 @@
package com.example.examplemod;
import dan200.computercraft.api.client.turtle.RegisterTurtleModellersEvent;
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
/**
* The client-side entry point for the Forge version of our example mod.
*/
@Mod.EventBusSubscriber(modid = ExampleMod.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ForgeExampleModClient {
// @start region=turtle_modellers
@SubscribeEvent
public static void onRegisterTurtleModellers(RegisterTurtleModellersEvent event) {
event.register(ExampleMod.EXAMPLE_TURTLE_UPGRADE, TurtleUpgradeModeller.flatItem());
}
// @end region=turtle_modellers
}

View File

@@ -0,0 +1,19 @@
package com.example.examplemod;
import com.example.examplemod.data.ExampleModDataGenerators;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
/**
* The data generator entrypoint for the Forge version of our example mod.
*
* @see ExampleModDataGenerators The main implementation
*/
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class ForgeExampleModDataGenerator {
@SubscribeEvent
public static void gather(GatherDataEvent event) {
ExampleModDataGenerators.run(event.getGenerator().getVanillaPack(true));
}
}

View File

@@ -0,0 +1,14 @@
modLoader="javafml"
loaderVersion="[1,)"
license="CC0-1.0"
[[mods]]
modId="examplemod"
version="1.0.0"
[[dependencies.examplemod]]
modId="computercraft"
mandatory=true
versionRange="[1.0,)"
ordering="AFTER"
side="BOTH"

View File

@@ -0,0 +1,6 @@
{
"pack": {
"pack_format": 15,
"description": "Example Mod"
}
}