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:
		| @@ -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 | ||||
| } | ||||
| @@ -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 | ||||
| } | ||||
| @@ -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)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								projects/forge/src/examples/resources/META-INF/mods.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								projects/forge/src/examples/resources/META-INF/mods.toml
									
									
									
									
									
										Normal 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" | ||||
							
								
								
									
										6
									
								
								projects/forge/src/examples/resources/pack.mcmeta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								projects/forge/src/examples/resources/pack.mcmeta
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| { | ||||
|     "pack": { | ||||
|         "pack_format": 15, | ||||
|         "description": "Example Mod" | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates