diff --git a/projects/common-api/build.gradle.kts b/projects/common-api/build.gradle.kts index 3bdc0d282..b00eb56db 100644 --- a/projects/common-api/build.gradle.kts +++ b/projects/common-api/build.gradle.kts @@ -8,6 +8,8 @@ plugins { id("cc-tweaked.vanilla") } +val mcVersion: String by extra + java { withJavadocJar() } @@ -17,8 +19,36 @@ dependencies { } tasks.javadoc { + title = "CC: Tweaked $version Minecraft $mcVersion" include("dan200/computercraft/api/**/*.java") + options { + (this as StandardJavadocDocletOptions) + + groups = mapOf( + "Common" to listOf( + "dan200.computercraft.api", + "dan200.computercraft.api.lua", + "dan200.computercraft.api.peripheral", + ), + "Upgrades" to listOf( + "dan200.computercraft.api.client.turtle", + "dan200.computercraft.api.pocket", + "dan200.computercraft.api.turtle", + "dan200.computercraft.api.upgrades", + ), + ) + + addBooleanOption("-allow-script-in-comments", true) + bottom( + """ + + + + """.trimIndent(), + ) + } + // Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump. source(project(":core-api").sourceSets.main.map { it.allJava }) } diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/network/wired/WiredElement.java b/projects/common-api/src/main/java/dan200/computercraft/api/network/wired/WiredElement.java index 0d58975f3..01d197ebd 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/api/network/wired/WiredElement.java +++ b/projects/common-api/src/main/java/dan200/computercraft/api/network/wired/WiredElement.java @@ -14,7 +14,7 @@ import dan200.computercraft.api.ComputerCraftAPI; * as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant * for its lifespan. *
- * Elements are generally tied to a block or tile entity in world. In such as case, one should provide the + * Elements are generally tied to a block or block entity in world. In such as case, one should provide the * {@link WiredElement} capability for the appropriate sides. */ public interface WiredElement extends WiredSender { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java index b9574340b..10b937237 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java @@ -248,7 +248,7 @@ public class CommandAPI implements ILuaAPI { * Get some basic information about a block. *
* The returned table contains the current name, metadata and block state (as - * with [`turtle.inspect`]). If there is a tile entity for that block, its NBT + * with [`turtle.inspect`]). If there is a block entity for that block, its NBT * will also be returned. * * @param x The x position of the block to query. diff --git a/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java b/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java index cb1f4f319..63c328c92 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java @@ -15,7 +15,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; import java.util.Set; /** - * A loot condition which checks if the tile entity has a non-0 ID. + * A loot condition which checks if the block entity has a computer ID. */ public final class HasComputerIdLootCondition implements LootItemCondition { public static final HasComputerIdLootCondition INSTANCE = new HasComputerIdLootCondition(); diff --git a/projects/core-api/src/main/java/dan200/computercraft/api/lua/GenericSource.java b/projects/core-api/src/main/java/dan200/computercraft/api/lua/GenericSource.java index 515967ed7..99c8493bf 100644 --- a/projects/core-api/src/main/java/dan200/computercraft/api/lua/GenericSource.java +++ b/projects/core-api/src/main/java/dan200/computercraft/api/lua/GenericSource.java @@ -23,7 +23,7 @@ import dan200.computercraft.api.peripheral.IPeripheral; * *
{@code * public class InventoryMethods implements GenericSource { - * \@LuaFunction( mainThread = true ) + * \@LuaFunction(mainThread = true) * public int size(IItemHandler inventory) { * return inventory.getSlots(); * } diff --git a/projects/core-api/src/main/java/dan200/computercraft/api/package-info.java b/projects/core-api/src/main/java/dan200/computercraft/api/package-info.java index a19a3583d..9d15df9be 100644 --- a/projects/core-api/src/main/java/dan200/computercraft/api/package-info.java +++ b/projects/core-api/src/main/java/dan200/computercraft/api/package-info.java @@ -7,11 +7,13 @@ ** You probably want to start in the following places: *
- * However, in some cases it may be more appropriate to specify a more readable name. Overriding this method allows - * you to do so. + * However, in some cases it may be more appropriate to specify a more readable name, or provide + * {@linkplain PeripheralType#getAdditionalTypes() additional types}. Overriding this method allows you to do so. *
- * When multiple {@link GenericPeripheral}s return a non-empty peripheral type for a single tile entity, the - * lexicographically smallest will be chosen. In order to avoid this conflict, this method should only be - * implemented when your peripheral targets a single tile entity AND it's likely that you're the - * only mod to do so. Similarly this should NOT be implemented when your methods target a - * capability or other interface (such as Forge's {@code IItemHandler}). + * When multiple {@link GenericPeripheral}s provide a {@linkplain PeripheralType#getPrimaryType() primary peripheral + * type} for a single block entity, the lexicographically smallest will be chosen. In order to avoid this conflict, + * primary types should only be used when your peripheral targets a single block entity AND it's + * likely that you're the only mod to do so. * * @return The type of this peripheral or {@link PeripheralType#untyped()}. * @see IPeripheral#getType() + * @see IPeripheral#getAdditionalTypes() */ default PeripheralType getType() { return PeripheralType.untyped(); diff --git a/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java index 6d2b96c4a..230f7694f 100644 --- a/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java +++ b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IDynamicPeripheral.java @@ -10,7 +10,6 @@ import dan200.computercraft.api.lua.*; * A peripheral whose methods are not known at runtime. *
* This behaves similarly to {@link IDynamicLuaObject}, though also accepting the current {@link IComputerAccess}. - * Generally one may use {@link LuaFunction} instead of implementing this interface. */ public interface IDynamicPeripheral extends IPeripheral { /** diff --git a/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java index 3d96075a8..1b80787f0 100644 --- a/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java +++ b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/IPeripheral.java @@ -4,19 +4,28 @@ package dan200.computercraft.api.peripheral; +import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.LuaTask; import javax.annotation.Nullable; import java.util.Set; /** - * The interface that defines a peripheral. + * A peripheral is an external device that a computer can interact with. *
- * In order to expose a peripheral for your block or block entity, you should either attach a capability (Forge) or - * use the block lookup API (Fabric). This interface cannot be implemented directly on the block entity. + * Peripherals can be supplied by both a block (or block entity), or from + * {@linkplain dan200.computercraft.api.turtle.ITurtleUpgrade#createPeripheral(dan200.computercraft.api.turtle.ITurtleAccess, dan200.computercraft.api.turtle.TurtleSide) turtle} + * or {@linkplain dan200.computercraft.api.pocket.IPocketUpgrade#createPeripheral(dan200.computercraft.api.pocket.IPocketAccess) pocket} + * upgrades. *
- * Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing - * {@link IDynamicPeripheral}. + * See the {@linkplain dan200.computercraft.api.peripheral package documentation} for more information on registering peripherals. + *
+ * Peripherals should provide a series of methods to the user, typically by annotating Java methods with + * {@link LuaFunction}. Alternatively, {@link IDynamicPeripheral} may be used to provide a dynamic set of methods. + * Remember that peripheral methods are called on the computer thread, and so it is not safe to interact with + * the Minecraft world by default. One should use {@link LuaFunction#mainThread()} or + * {@link ILuaContext#executeMainThreadTask(LuaTask)} to run code on the main server thread. */ public interface IPeripheral { /** @@ -24,6 +33,7 @@ public interface IPeripheral { * This can be queried from lua by calling {@code peripheral.getType()} * * @return A string identifying the type of peripheral. + * @see PeripheralType#getPrimaryType() */ String getType(); @@ -81,7 +91,7 @@ public interface IPeripheral { } /** - * Get the object that this peripheral provides methods for. This will generally be the tile entity + * Get the object that this peripheral provides methods for. This will generally be the block entity * or block, but may be an inventory, entity, etc... * * @return The object this peripheral targets @@ -95,7 +105,7 @@ public interface IPeripheral { * Determine whether this peripheral is equivalent to another one. *
* The minimal example should at least check whether they are the same object. However, you may wish to check if
- * they point to the same block or tile entity.
+ * they point to the same block or block entity.
*
* @param other The peripheral to compare against. This may be {@code null}.
* @return Whether these peripherals are equivalent.
diff --git a/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/PeripheralType.java b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/PeripheralType.java
index 08cc97448..e651df006 100644
--- a/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/PeripheralType.java
+++ b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/PeripheralType.java
@@ -96,6 +96,7 @@ public final class PeripheralType {
* Get the name of this peripheral type. This may be {@code null}.
*
* @return The type of this peripheral.
+ * @see IPeripheral#getType()
*/
@Nullable
public String getPrimaryType() {
@@ -107,6 +108,7 @@ public final class PeripheralType {
* a peripheral might have.
*
* @return All additional types.
+ * @see IPeripheral#getAdditionalTypes()
*/
public Set
- * This is primarily intended for work done by peripherals on the main thread (such as on a tile entity's tick), but
+ * This is primarily intended for work done by peripherals on the main thread (such as on a block entity's tick), but
* could be used for other purposes (such as complex computations done on another thread).
*
* Before running a task, one should call {@link #canWork()} to determine if the computer is currently allowed to
diff --git a/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/package-info.java b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/package-info.java
new file mode 100644
index 000000000..dfc48e670
--- /dev/null
+++ b/projects/core-api/src/main/java/dan200/computercraft/api/peripheral/package-info.java
@@ -0,0 +1,205 @@
+// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
+//
+// SPDX-License-Identifier: MPL-2.0
+
+/**
+ * Peripherals for blocks and upgrades.
+ *
+ * A peripheral is an external device that a computer can interact with. Peripherals can be supplied by both a block (or
+ * block entity), or from {@linkplain dan200.computercraft.api.turtle.ITurtleUpgrade#createPeripheral(dan200.computercraft.api.turtle.ITurtleAccess, dan200.computercraft.api.turtle.TurtleSide) turtle}
+ * or {@linkplain dan200.computercraft.api.pocket.IPocketUpgrade#createPeripheral(dan200.computercraft.api.pocket.IPocketAccess) pocket}
+ * upgrades.
+ *
+ *
+ * There are currently two possible ways to define a peripheral in ComputerCraft:
+ *
+ * With a {@linkplain dan200.computercraft.api.peripheral.GenericPeripheral generic peripheral}:
+ * Generic peripherals are a way to add peripheral methods to any block entity, in a trait-based manner. This
+ * allows multiple mods to add methods to the same block entity.
+ *
+ * This is the recommended approach if you just want to add a couple of methods, and do not need any advanced
+ * functionality.
+ *
+ * With an {@link dan200.computercraft.api.peripheral.IPeripheral}: If your peripheral needs
+ * more advanced behaviour, such as knowing which computers it is attached to, then you can use an
+ * {@link dan200.computercraft.api.peripheral.IPeripheral}.
+ *
+ * These peripherals are currently NOT compatible with the generic peripheral system, so
+ * methods added by other mods (including CC's built-in inventory methods) will not be available.
+ *
+ * In the following examples, we'll write a peripheral method that returns the remaining burn time of a furnace, and
+ * demonstrate how to register this peripheral.
+ *
+ *
+ * Then, we can start adding methods to your block entity. Each method should take its target type as the first
+ * argument, which in this case is a {@code AbstractFurnaceBlockEntity}. We then annotate this method with
+ * {@link dan200.computercraft.api.lua.LuaFunction} to expose it to computers.
+ *
+ *
+ * Finally, we need to register our peripheral, so that ComputerCraft is aware of it:
+ *
+ *
+ * We can then start adding peripheral methods to our class. Each method should be {@code final}, and annotated with
+ * {@link dan200.computercraft.api.lua.LuaFunction}.
+ *
+ *
+ * Finally, we'll need to register our peripheral. This is done with capabilities on Forge, or the block lookup API on
+ * Fabric.
+ *
+ *
* Now, if anywhere during this period, we use more than our allocated time slice, the executor is marked as
* {@link State#HOT}. This means it will no longer be able to execute {@link MainThread} tasks (though will still
- * execute tile entity tasks, in order to prevent the main thread from exhausting work every tick).
+ * execute block entity tasks, in order to prevent the main thread from exhausting work every tick).
*
* At the beginning of the next tick, we increment the budget e by {@link MainThreadConfig#maxComputerTime()} and any
* {@link State#HOT} executors are marked as {@link State#COOLING}. They will remain cooling until their budget is fully
Creating peripherals for blocks
+ * One of the most common things you'll want to do with ComputerCraft's API is register new peripherals. This is
+ * relatively simple once you know how to do it, but may be a bit confusing the first time round.
+ *
+ *
+ * Creating a generic peripheral
+ * First, we'll need to create a new {@code final} class, that implements {@link dan200.computercraft.api.peripheral.GenericPeripheral}.
+ * You'll need to implement {@link dan200.computercraft.api.peripheral.GenericPeripheral#id()}, which should just return
+ * some namespaced-string with your mod id.
+ * {@code
+ * import dan200.computercraft.api.lua.LuaFunction;
+ * import dan200.computercraft.api.peripheral.GenericPeripheral;
+ * import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
+ *
+ * public final class FurnacePeripheral implements GenericPeripheral {
+ * @Override
+ * public String id() {
+ * return "mymod:furnace";
+ * }
+ *
+ * @LuaFunction(mainThread = true)
+ * public int getBurnTime(AbstractFurnaceBlockEntity furnace) {
+ * return furnace.litTime;
+ * }
+ * }
+ * }
+ * {@code
+ * import dan200.computercraft.api.ComputerCraftAPI;
+ *
+ * public class ComputerCraftCompat {
+ * public static void register() {
+ * ComputerCraftAPI.registerGenericSource(new FurnacePeripheral());
+ * }
+ * }
+ * }
+ *
+ * Creating a {@code IPeripheral}
+ * First, we'll need to create a new class that implements {@link dan200.computercraft.api.peripheral.IPeripheral}. This
+ * requires a couple of boilerplate methods: one to get the type of the peripheral, and an equality function.
+ * {@code
+ * import dan200.computercraft.api.lua.LuaFunction;
+ * import dan200.computercraft.api.peripheral.IPeripheral;
+ * import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
+ * import org.jetbrains.annotations.Nullable;
+ *
+ * public class FurnacePeripheral implements IPeripheral {
+ * private final AbstractFurnaceBlockEntity furnace;
+ *
+ * public FurnacePeripheral(AbstractFurnaceBlockEntity furnace) {
+ * this.furnace = furnace;
+ * }
+ *
+ * @Override
+ * public String getType() {
+ * return "furnace";
+ * }
+ *
+ * @LuaFunction(mainThread = true)
+ * public final int getBurnTime() {
+ * return furnace.litTime;
+ * }
+ *
+ * @Override
+ * public boolean equals(@Nullable IPeripheral other) {
+ * return this == other || other instanceof FurnacePeripheral p && furnace == p.furnace;
+ * }
+ * }
+ * }
+ * Registering {@code IPeripheral} on Forge
+ * Registering a peripheral on Forge can be done by attaching the {@link dan200.computercraft.api.peripheral.IPeripheral}
+ * to a block entity. Unfortunately, this requires quite a lot of boilerplate, due to the awkward nature of
+ * {@code ICapabilityProvider}. If you've got an existing system for dealing with this, we recommend you use that,
+ * otherwise you can use something similar to the code below:
+ *
+ * {@code
+ * import dan200.computercraft.api.peripheral.IPeripheral;
+ * import net.minecraft.core.Direction;
+ * import net.minecraft.resources.ResourceLocation;
+ * import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
+ * import net.minecraft.world.level.block.entity.BlockEntity;
+ * 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 org.jetbrains.annotations.Nullable;
+ *
+ * import java.util.function.Function;
+ *
+ * public class ComputerCraftCompat {
+ * public static final Capability
+ *
+ * Registering {@code IPeripheral} on Fabric
+ * Registering a peripheral on Fabric can be done using the block lookup API, via {@code PeripheralLookup}.
+ *
+ * {@code
+ * import dan200.computercraft.api.peripheral.PeripheralLookup;
+ * import dan200.computercraft.example.FurnacePeripheral;
+ * import net.minecraft.world.level.block.entity.BlockEntityType;
+ *
+ * public class ComputerCraftCompat {
+ * public static void register() {
+ * PeripheralLookup.get().registerForBlockEntity((f, s) -> new FurnacePeripheral(f), BlockEntityType.FURNACE);
+ * PeripheralLookup.get().registerForBlockEntity((f, s) -> new FurnacePeripheral(f), BlockEntityType.BLAST_FURNACE);
+ * PeripheralLookup.get().registerForBlockEntity((f, s) -> new FurnacePeripheral(f), BlockEntityType.SMOKER);
+ * }
+ * }
+ * }
+ */
+package dan200.computercraft.api.peripheral;
diff --git a/projects/core/src/main/java/dan200/computercraft/core/computer/mainthread/MainThreadExecutor.java b/projects/core/src/main/java/dan200/computercraft/core/computer/mainthread/MainThreadExecutor.java
index adf92fa7e..e72978d25 100644
--- a/projects/core/src/main/java/dan200/computercraft/core/computer/mainthread/MainThreadExecutor.java
+++ b/projects/core/src/main/java/dan200/computercraft/core/computer/mainthread/MainThreadExecutor.java
@@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit;
*