mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 05:33:00 +00:00 
			
		
		
		
	Clarify docs around registering peripherals
This commit is contained in:
		| @@ -8,6 +8,8 @@ plugins { | |||||||
|     id("cc-tweaked.vanilla") |     id("cc-tweaked.vanilla") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | val mcVersion: String by extra | ||||||
|  | 
 | ||||||
| java { | java { | ||||||
|     withJavadocJar() |     withJavadocJar() | ||||||
| } | } | ||||||
| @@ -17,8 +19,36 @@ dependencies { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| tasks.javadoc { | tasks.javadoc { | ||||||
|  |     title = "CC: Tweaked $version Minecraft $mcVersion" | ||||||
|     include("dan200/computercraft/api/**/*.java") |     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( | ||||||
|  |             """ | ||||||
|  |             <script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/components/prism-core.min.js"></script> | ||||||
|  |             <script src="https://cdn.jsdelivr.net/npm/prismjs@v1.29.0/plugins/autoloader/prism-autoloader.min.js"></script> | ||||||
|  |             <link href=" https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css " rel="stylesheet"> | ||||||
|  |             """.trimIndent(), | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump. |     // 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 }) |     source(project(":core-api").sourceSets.main.map { it.allJava }) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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 |  * as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant | ||||||
|  * for its lifespan. |  * for its lifespan. | ||||||
|  * <p> |  * <p> | ||||||
|  * 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. |  * {@link WiredElement} capability for the appropriate sides. | ||||||
|  */ |  */ | ||||||
| public interface WiredElement extends WiredSender { | public interface WiredElement extends WiredSender { | ||||||
|   | |||||||
| @@ -248,7 +248,7 @@ public class CommandAPI implements ILuaAPI { | |||||||
|      * Get some basic information about a block. |      * Get some basic information about a block. | ||||||
|      * <p> |      * <p> | ||||||
|      * The returned table contains the current name, metadata and block state (as |      * 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. |      * will also be returned. | ||||||
|      * |      * | ||||||
|      * @param x         The x position of the block to query. |      * @param x         The x position of the block to query. | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; | |||||||
| import java.util.Set; | 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 final class HasComputerIdLootCondition implements LootItemCondition { | ||||||
|     public static final HasComputerIdLootCondition INSTANCE = new HasComputerIdLootCondition(); |     public static final HasComputerIdLootCondition INSTANCE = new HasComputerIdLootCondition(); | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ import dan200.computercraft.api.peripheral.IPeripheral; | |||||||
|  * |  * | ||||||
|  * <pre>{@code |  * <pre>{@code | ||||||
|  * public class InventoryMethods implements GenericSource { |  * public class InventoryMethods implements GenericSource { | ||||||
|  *     \@LuaFunction( mainThread = true ) |  *     \@LuaFunction(mainThread = true) | ||||||
|  *     public int size(IItemHandler inventory) { |  *     public int size(IItemHandler inventory) { | ||||||
|  *         return inventory.getSlots(); |  *         return inventory.getSlots(); | ||||||
|  *     } |  *     } | ||||||
|   | |||||||
| @@ -7,11 +7,13 @@ | |||||||
|  * <p> |  * <p> | ||||||
|  * You probably want to start in the following places: |  * You probably want to start in the following places: | ||||||
|  * <ul> |  * <ul> | ||||||
|  *     <li>{@link dan200.computercraft.api.peripheral.IPeripheral} for registering new peripherals.</li> |  *     <li>{@link dan200.computercraft.api.peripheral} for registering new peripherals.</li> | ||||||
|  *     <li> |  *     <li> | ||||||
|  *         {@link dan200.computercraft.api.lua.LuaFunction} and {@link dan200.computercraft.api.lua.IArguments} for |  *         {@link dan200.computercraft.api.lua.LuaFunction} and {@link dan200.computercraft.api.lua.IArguments} for | ||||||
|  *          adding methods to your peripheral or Lua objects. |  *          adding methods to your peripheral or Lua objects. | ||||||
|  *     </li> |  *     </li> | ||||||
|  |  *     <li>{@link dan200.computercraft.api.turtle.ITurtleUpgrade} for turtle upgrades.</li> | ||||||
|  |  *     <li>{@link dan200.computercraft.api.pocket.IPocketUpgrade} for pocket upgrades.</li> | ||||||
|  * </ul> |  * </ul> | ||||||
|  */ |  */ | ||||||
| @DefaultQualifier(value = NonNull.class, locations = { | @DefaultQualifier(value = NonNull.class, locations = { | ||||||
|   | |||||||
| @@ -19,17 +19,17 @@ public interface GenericPeripheral extends GenericSource { | |||||||
|      * Unlike normal {@link IPeripheral}s, {@link GenericPeripheral} do not have to have a type. By default, the |      * Unlike normal {@link IPeripheral}s, {@link GenericPeripheral} do not have to have a type. By default, the | ||||||
|      * resulting peripheral uses the resource name of the wrapped block entity (for instance {@code minecraft:chest}). |      * resulting peripheral uses the resource name of the wrapped block entity (for instance {@code minecraft:chest}). | ||||||
|      * <p> |      * <p> | ||||||
|      * However, in some cases it may be more appropriate to specify a more readable name. Overriding this method allows |      * However, in some cases it may be more appropriate to specify a more readable name, or provide | ||||||
|      * you to do so. |      * {@linkplain PeripheralType#getAdditionalTypes() additional types}. Overriding this method allows you to do so. | ||||||
|      * <p> |      * <p> | ||||||
|      * When multiple {@link GenericPeripheral}s return a non-empty peripheral type for a single tile entity, the |      * When multiple {@link GenericPeripheral}s provide a {@linkplain PeripheralType#getPrimaryType() primary peripheral | ||||||
|      * lexicographically smallest will be chosen. In order to avoid this conflict, this method should only be |      * type} for a single block entity, the lexicographically smallest will be chosen. In order to avoid this conflict, | ||||||
|      * implemented when your peripheral targets a single tile entity <strong>AND</strong> it's likely that you're the |      * primary types should only be used when your peripheral targets a single block entity <strong>AND</strong> it's | ||||||
|      * only mod to do so. Similarly this should <strong>NOT</strong> be implemented when your methods target a |      * likely that you're the only mod to do so. | ||||||
|      * capability or other interface (such as Forge's {@code IItemHandler}). |  | ||||||
|      * |      * | ||||||
|      * @return The type of this peripheral or {@link PeripheralType#untyped()}. |      * @return The type of this peripheral or {@link PeripheralType#untyped()}. | ||||||
|      * @see IPeripheral#getType() |      * @see IPeripheral#getType() | ||||||
|  |      * @see IPeripheral#getAdditionalTypes() | ||||||
|      */ |      */ | ||||||
|     default PeripheralType getType() { |     default PeripheralType getType() { | ||||||
|         return PeripheralType.untyped(); |         return PeripheralType.untyped(); | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ import dan200.computercraft.api.lua.*; | |||||||
|  * A peripheral whose methods are not known at runtime. |  * A peripheral whose methods are not known at runtime. | ||||||
|  * <p> |  * <p> | ||||||
|  * This behaves similarly to {@link IDynamicLuaObject}, though also accepting the current {@link IComputerAccess}. |  * 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 { | public interface IDynamicPeripheral extends IPeripheral { | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -4,19 +4,28 @@ | |||||||
| 
 | 
 | ||||||
| package dan200.computercraft.api.peripheral; | package dan200.computercraft.api.peripheral; | ||||||
| 
 | 
 | ||||||
|  | import dan200.computercraft.api.lua.ILuaContext; | ||||||
| import dan200.computercraft.api.lua.LuaFunction; | import dan200.computercraft.api.lua.LuaFunction; | ||||||
|  | import dan200.computercraft.api.lua.LuaTask; | ||||||
| 
 | 
 | ||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * The interface that defines a peripheral. |  * A peripheral is an external device that a computer can interact with. | ||||||
|  * <p> |  * <p> | ||||||
|  * In order to expose a peripheral for your block or block entity, you should either attach a capability (Forge) or |  * Peripherals can be supplied by both a block (or block entity), or from | ||||||
|  * use the block lookup API (Fabric). This interface <em>cannot</em> be implemented directly on the block entity. |  * {@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. | ||||||
|  * <p> |  * <p> | ||||||
|  * Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing |  * See the {@linkplain dan200.computercraft.api.peripheral package documentation} for more information on registering peripherals. | ||||||
|  * {@link IDynamicPeripheral}. |  * <p> | ||||||
|  |  * 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 <em>computer</em> 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 { | public interface IPeripheral { | ||||||
|     /** |     /** | ||||||
| @@ -24,6 +33,7 @@ public interface IPeripheral { | |||||||
|      * This can be queried from lua by calling {@code peripheral.getType()} |      * This can be queried from lua by calling {@code peripheral.getType()} | ||||||
|      * |      * | ||||||
|      * @return A string identifying the type of peripheral. |      * @return A string identifying the type of peripheral. | ||||||
|  |      * @see PeripheralType#getPrimaryType() | ||||||
|      */ |      */ | ||||||
|     String getType(); |     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... |      * or block, but may be an inventory, entity, etc... | ||||||
|      * |      * | ||||||
|      * @return The object this peripheral targets |      * @return The object this peripheral targets | ||||||
| @@ -95,7 +105,7 @@ public interface IPeripheral { | |||||||
|      * Determine whether this peripheral is equivalent to another one. |      * Determine whether this peripheral is equivalent to another one. | ||||||
|      * <p> |      * <p> | ||||||
|      * The minimal example should at least check whether they are the same object. However, you may wish to check if |      * 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}. |      * @param other The peripheral to compare against. This may be {@code null}. | ||||||
|      * @return Whether these peripherals are equivalent. |      * @return Whether these peripherals are equivalent. | ||||||
|   | |||||||
| @@ -96,6 +96,7 @@ public final class PeripheralType { | |||||||
|      * Get the name of this peripheral type. This may be {@code null}. |      * Get the name of this peripheral type. This may be {@code null}. | ||||||
|      * |      * | ||||||
|      * @return The type of this peripheral. |      * @return The type of this peripheral. | ||||||
|  |      * @see IPeripheral#getType() | ||||||
|      */ |      */ | ||||||
|     @Nullable |     @Nullable | ||||||
|     public String getPrimaryType() { |     public String getPrimaryType() { | ||||||
| @@ -107,6 +108,7 @@ public final class PeripheralType { | |||||||
|      * a peripheral might have. |      * a peripheral might have. | ||||||
|      * |      * | ||||||
|      * @return All additional types. |      * @return All additional types. | ||||||
|  |      * @see IPeripheral#getAdditionalTypes() | ||||||
|      */ |      */ | ||||||
|     public Set<String> getAdditionalTypes() { |     public Set<String> getAdditionalTypes() { | ||||||
|         return additionalTypes; |         return additionalTypes; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit; | |||||||
|  * Monitors "work" associated with a computer, keeping track of how much a computer has done, and ensuring every |  * Monitors "work" associated with a computer, keeping track of how much a computer has done, and ensuring every | ||||||
|  * computer receives a fair share of any processing time. |  * computer receives a fair share of any processing time. | ||||||
|  * <p> |  * <p> | ||||||
|  * 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). |  * could be used for other purposes (such as complex computations done on another thread). | ||||||
|  * <p> |  * <p> | ||||||
|  * Before running a task, one should call {@link #canWork()} to determine if the computer is currently allowed to |  * Before running a task, one should call {@link #canWork()} to determine if the computer is currently allowed to | ||||||
|   | |||||||
| @@ -0,0 +1,205 @@ | |||||||
|  | // SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers | ||||||
|  | // | ||||||
|  | // SPDX-License-Identifier: MPL-2.0 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Peripherals for blocks and upgrades. | ||||||
|  |  * <p> | ||||||
|  |  * 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. | ||||||
|  |  * | ||||||
|  |  * <h2>Creating peripherals for blocks</h2> | ||||||
|  |  * 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. | ||||||
|  |  * <p> | ||||||
|  |  * There are currently two possible ways to define a peripheral in ComputerCraft: | ||||||
|  |  * <ul> | ||||||
|  |  *     <li> | ||||||
|  |  * <p> | ||||||
|  |  *         <strong>With a {@linkplain dan200.computercraft.api.peripheral.GenericPeripheral generic peripheral}:</strong> | ||||||
|  |  *         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. | ||||||
|  |  * <p> | ||||||
|  |  *         This is the recommended approach if you just want to add a couple of methods, and do not need any advanced | ||||||
|  |  *         functionality. | ||||||
|  |  *     </li> | ||||||
|  |  *     <li> | ||||||
|  |  * <p> | ||||||
|  |  *         <strong>With an {@link dan200.computercraft.api.peripheral.IPeripheral}:</strong> 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}. | ||||||
|  |  * <p> | ||||||
|  |  *          These peripherals are currently <strong>NOT</strong> compatible with the generic peripheral system, so | ||||||
|  |  *          methods added by other mods (including CC's built-in inventory methods) will not be available. | ||||||
|  |  *     </li> | ||||||
|  |  * </ul> | ||||||
|  |  * <p> | ||||||
|  |  * 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. | ||||||
|  |  * | ||||||
|  |  * <h3>Creating a generic peripheral</h3> | ||||||
|  |  * 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. | ||||||
|  |  * <p> | ||||||
|  |  * 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. | ||||||
|  |  * | ||||||
|  |  * <pre class="language language-java">{@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; | ||||||
|  |  *     } | ||||||
|  |  * } | ||||||
|  |  * }</pre> | ||||||
|  |  * <p> | ||||||
|  |  * Finally, we need to register our peripheral, so that ComputerCraft is aware of it: | ||||||
|  |  * | ||||||
|  |  * <pre class="language language-java">{@code | ||||||
|  |  * import dan200.computercraft.api.ComputerCraftAPI; | ||||||
|  |  * | ||||||
|  |  * public class ComputerCraftCompat { | ||||||
|  |  *     public static void register() { | ||||||
|  |  *         ComputerCraftAPI.registerGenericSource(new FurnacePeripheral()); | ||||||
|  |  *     } | ||||||
|  |  * } | ||||||
|  |  * }</pre> | ||||||
|  |  * | ||||||
|  |  * <h3>Creating a {@code IPeripheral}</h3> | ||||||
|  |  * 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. | ||||||
|  |  * <p> | ||||||
|  |  * 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}. | ||||||
|  |  * | ||||||
|  |  * <pre class="language language-java">{@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; | ||||||
|  |  *     } | ||||||
|  |  * } | ||||||
|  |  * }</pre> | ||||||
|  |  * <p> | ||||||
|  |  * Finally, we'll need to register our peripheral. This is done with capabilities on Forge, or the block lookup API on | ||||||
|  |  * Fabric. | ||||||
|  |  * | ||||||
|  |  * <h4>Registering {@code IPeripheral} on Forge</h4> | ||||||
|  |  * 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: | ||||||
|  |  * | ||||||
|  |  * <pre class="language language-java">{@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<IPeripheral> CAPABILITY_PERIPHERAL = CapabilityManager.get(new CapabilityToken<>() { | ||||||
|  |  *     }); | ||||||
|  |  *     private static final ResourceLocation PERIPHERAL = new ResourceLocation("mymod", "peripheral"); | ||||||
|  |  * | ||||||
|  |  *     public static void register(AttachCapabilitiesEvent<BlockEntity> event) { | ||||||
|  |  *         if (event.getObject() instanceof AbstractFurnaceBlockEntity furnace) { | ||||||
|  |  *             PeripheralProvider.attach(event, furnace, FurnacePeripheral::new); | ||||||
|  |  *         } | ||||||
|  |  *     } | ||||||
|  |  * | ||||||
|  |  *     // A {@link ICapabilityProvider} that lazily creates an {@link IPeripheral} when required. | ||||||
|  |  *     private static 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(); | ||||||
|  |  *         } | ||||||
|  |  *     } | ||||||
|  |  * } | ||||||
|  |  * }</pre> | ||||||
|  |  * | ||||||
|  |  * <h4>Registering {@code IPeripheral} on Fabric</h4> | ||||||
|  |  * Registering a peripheral on Fabric can be done using the block lookup API, via {@code PeripheralLookup}. | ||||||
|  |  * | ||||||
|  |  * <pre class="language language-java">{@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); | ||||||
|  |  *     } | ||||||
|  |  * } | ||||||
|  |  * }</pre> | ||||||
|  |  */ | ||||||
|  | package dan200.computercraft.api.peripheral; | ||||||
| @@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit; | |||||||
|  * <p> |  * <p> | ||||||
|  * Now, if anywhere during this period, we use more than our allocated time slice, the executor is marked as |  * 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 |  * {@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). | ||||||
|  * <p> |  * <p> | ||||||
|  * At the beginning of the next tick, we increment the budget e by {@link MainThreadConfig#maxComputerTime()} and any |  * 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 |  * {@link State#HOT} executors are marked as {@link State#COOLING}. They will remain cooling until their budget is fully | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates