diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6df908ef2..92663e41e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -51,7 +51,7 @@ jqwik = "1.7.4" junit = "5.10.0" # Build tools -cctJavadoc = "1.8.1" +cctJavadoc = "1.8.2" checkstyle = "10.12.3" curseForgeGradle = "1.0.14" errorProne-core = "2.21.1" diff --git a/illuaminate.sexp b/illuaminate.sexp index f3f0eaa8c..c8d764567 100644 --- a/illuaminate.sexp +++ b/illuaminate.sexp @@ -6,7 +6,7 @@ (sources /doc/ - /projects/forge/build/docs/luaJavadoc/ + /projects/common/build/docs/luaJavadoc/ /projects/core/src/main/resources/data/computercraft/lua/bios.lua /projects/core/src/main/resources/data/computercraft/lua/rom/ /projects/core/src/test/resources/test-rom @@ -36,7 +36,7 @@ (library-path /doc/stub/ - /projects/forge/build/docs/luaJavadoc/ + /projects/common/build/docs/luaJavadoc/ /projects/core/src/main/resources/data/computercraft/lua/rom/apis/ /projects/core/src/main/resources/data/computercraft/lua/rom/apis/command/ @@ -88,7 +88,7 @@ (/doc/stub/ /projects/core/src/main/resources/data/computercraft/lua/bios.lua /projects/core/src/main/resources/data/computercraft/lua/rom/apis/ - /projects/forge/build/docs/luaJavadoc/) + /projects/common/build/docs/luaJavadoc/) (linters -var:unused-global) (lint (allow-toplevel-global true))) diff --git a/projects/common/build.gradle.kts b/projects/common/build.gradle.kts index 66528450c..cdd84846e 100644 --- a/projects/common/build.gradle.kts +++ b/projects/common/build.gradle.kts @@ -2,13 +2,12 @@ // // SPDX-License-Identifier: MPL-2.0 -import cc.tweaked.gradle.annotationProcessorEverywhere -import cc.tweaked.gradle.clientClasses -import cc.tweaked.gradle.commonClasses +import cc.tweaked.gradle.* plugins { id("cc-tweaked.vanilla") id("cc-tweaked.gametest") + id("cc-tweaked.illuaminate") id("cc-tweaked.publishing") } @@ -19,6 +18,10 @@ minecraft { ) } +configurations { + register("cctJavadoc") +} + dependencies { // Pull in our other projects. See comments in MinecraftConfigurations on this nastiness. implementation(project(":core")) @@ -41,4 +44,53 @@ dependencies { testModImplementation(libs.bundles.kotlin) testFixturesImplementation(testFixtures(project(":core"))) + + "cctJavadoc"(libs.cctJavadoc) +} + +illuaminate { + version.set(libs.versions.illuaminate) +} + +val luaJavadoc by tasks.registering(Javadoc::class) { + description = "Generates documentation for Java-side Lua functions." + group = JavaBasePlugin.DOCUMENTATION_GROUP + + val sourceSets = listOf(sourceSets.main.get(), project(":core").sourceSets.main.get()) + for (sourceSet in sourceSets) { + source(sourceSet.java) + classpath += sourceSet.compileClasspath + } + + destinationDir = layout.buildDirectory.dir("docs/luaJavadoc").get().asFile + + val options = options as StandardJavadocDocletOptions + options.docletpath = configurations["cctJavadoc"].files.toList() + options.doclet = "cc.tweaked.javadoc.LuaDoclet" + options.addStringOption("project-root", rootProject.file(".").absolutePath) + options.noTimestamp(false) + + javadocTool.set( + javaToolchains.javadocToolFor { + languageVersion.set(cc.tweaked.gradle.CCTweakedPlugin.JAVA_VERSION) + }, + ) +} + +val lintLua by tasks.registering(IlluaminateExec::class) { + group = JavaBasePlugin.VERIFICATION_GROUP + description = "Lint Lua (and Lua docs) with illuaminate" + + // Config files + inputs.file(rootProject.file("illuaminate.sexp")).withPropertyName("illuaminate.sexp") + // Sources + inputs.files(rootProject.fileTree("doc")).withPropertyName("docs") + inputs.files(project(":core").fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom") + inputs.files(luaJavadoc) + + args = listOf("lint") + workingDir = rootProject.projectDir + + doFirst { if (System.getenv("GITHUB_ACTIONS") != null) println("::add-matcher::.github/matchers/illuaminate.json") } + doLast { if (System.getenv("GITHUB_ACTIONS") != null) println("::remove-matcher owner=illuaminate::") } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractEnergyMethods.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractEnergyMethods.java new file mode 100644 index 000000000..92b27e449 --- /dev/null +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractEnergyMethods.java @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.shared.peripheral.generic.methods; + +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.peripheral.GenericPeripheral; +import dan200.computercraft.api.peripheral.PeripheralType; + +/** + * Methods for interacting with blocks which store energy. + *
+ * This works with energy storage blocks, as well as generators and machines which consume energy. + *
+ * > [!NOTE]
+ * > Due to limitations with Forge's energy API, it is not possible to measure throughput (i.e. FE used/generated per
+ * > tick).
+ *
+ * @param
+ * Each tank either contains some amount of fluid or is empty. Tanks with fluids inside will return some basic
+ * information about the fluid, including its name and amount.
+ *
+ * The returned table is sparse, and so empty tanks will be `nil` - it is recommended to loop over using [`pairs`]
+ * rather than [`ipairs`].
+ *
+ * @param fluids The current fluid handler.
+ * @return All tanks.
+ * @cc.treturn { (table|nil)... } All tanks in this fluid storage.
+ */
+ @LuaFunction(mainThread = true)
+ public abstract Map
+ * This allows you to pull fluid in the current fluid container to another container on the same wired
+ * network. Both containers must attached to wired modems which are connected via a cable.
+ *
+ * @param from Container to move fluid from.
+ * @param computer The current computer.
+ * @param toName The name of the peripheral/container to push to. This is the string given to [`peripheral.wrap`],
+ * and displayed by the wired modem.
+ * @param limit The maximum amount of fluid to move.
+ * @param fluidName The fluid to move. If not given, an arbitrary fluid will be chosen.
+ * @return The amount of moved fluid.
+ * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an fluid container.
+ * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
+ */
+ @LuaFunction(mainThread = true)
+ public abstract int pushFluid(
+ T from, IComputerAccess computer, String toName, Optional
+ * This allows you to pull fluid in the current fluid container from another container on the same wired
+ * network. Both containers must attached to wired modems which are connected via a cable.
+ *
+ * @param to Container to move fluid to.
+ * @param computer The current computer.
+ * @param fromName The name of the peripheral/container to push to. This is the string given to [`peripheral.wrap`],
+ * and displayed by the wired modem.
+ * @param limit The maximum amount of fluid to move.
+ * @param fluidName The fluid to move. If not given, an arbitrary fluid will be chosen.
+ * @return The amount of moved fluid.
+ * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an fluid container.
+ * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
+ */
+ @LuaFunction(mainThread = true)
+ public abstract int pullFluid(
+ T to, IComputerAccess computer, String fromName, Optional
+ * Each item in the inventory is represented by a table containing some basic information, much like
+ * {@link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail(ILuaContext, Optional, Optional)}
+ * includes. More information can be fetched with {@link #getItemDetail}. The table contains the item `name`, the
+ * `count` and an a (potentially nil) hash of the item's `nbt.` This NBT data doesn't contain anything useful, but
+ * allows you to distinguish identical items.
+ *
+ * The returned table is sparse, and so empty slots will be `nil` - it is recommended to loop over using [`pairs`]
+ * rather than [`ipairs`].
+ *
+ * @param inventory The current inventory.
+ * @return All items in this inventory.
+ * @cc.treturn { (table|nil)... } All items in this inventory.
+ * @cc.usage Find an adjacent chest and print all items in it.
+ *
+ *
+ * The returned information contains the same information as each item in
+ * {@link #list}, as well as additional details like the display name
+ * (`displayName`), and item and item durability (`damage`, `maxDamage`, `durability`).
+ *
+ * Some items include more information (such as enchantments) - it is
+ * recommended to print it out using [`textutils.serialize`] or in the Lua
+ * REPL, to explore what is available.
+ *
+ * > [Deprecated fields][!INFO]
+ * > Older versions of CC: Tweaked exposed an {@code itemGroups} field, listing the
+ * > creative tabs an item was available under. This information is no longer available on
+ * > more recent versions of the game, and so this field will always be empty. Do not use this
+ * > field in new code!
+ *
+ * @param inventory The current inventory.
+ * @param slot The slot to get information about.
+ * @return Information about the item in this slot, or {@code nil} if not present.
+ * @throws LuaException If the slot is out of range.
+ * @cc.treturn table Information about the item in this slot, or {@code nil} if not present.
+ * @cc.usage Print some information about the first in a chest.
+ *
+ *
+ * Typically this will be limited to 64 items. However, some inventories (such as barrels or caches) can store
+ * hundreds or thousands of items in one slot.
+ *
+ * @param inventory Inventory to probe.
+ * @param slot The slot
+ * @return The maximum number of items in this slot.
+ * @throws LuaException If the slot is out of range.
+ * @cc.usage Count the maximum number of items an adjacent chest can hold.
+ *
+ * This allows you to push an item in an inventory to another inventory on the same wired network. Both
+ * inventories must attached to wired modems which are connected via a cable.
+ *
+ * @param from Inventory to move items from.
+ * @param computer The current computer.
+ * @param toName The name of the peripheral/inventory to push to. This is the string given to [`peripheral.wrap`],
+ * and displayed by the wired modem.
+ * @param fromSlot The slot in the current inventory to move items to.
+ * @param limit The maximum number of items to move. Defaults to the current stack limit.
+ * @param toSlot The slot in the target inventory to move to. If not given, the item will be inserted into any slot.
+ * @return The number of transferred items.
+ * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an inventory.
+ * @throws LuaException If either source or destination slot is out of range.
+ * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
+ * @cc.usage Wrap two chests, and push an item from one to another.
+ *
+ * This allows you to transfer items between inventories on the same wired network. Both this and the source
+ * inventory must attached to wired modems which are connected via a cable.
+ *
+ * @param to Inventory to move items to.
+ * @param computer The current computer.
+ * @param fromName The name of the peripheral/inventory to pull from. This is the string given to [`peripheral.wrap`],
+ * and displayed by the wired modem.
+ * @param fromSlot The slot in the source inventory to move items from.
+ * @param limit The maximum number of items to move. Defaults to the current stack limit.
+ * @param toSlot The slot in current inventory to move to. If not given, the item will be inserted into any slot.
+ * @return The number of transferred items.
+ * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an inventory.
+ * @throws LuaException If either source or destination slot is out of range.
+ * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
+ * @cc.usage Wrap two chests, and push an item from one to another.
+ *
+ * The generic peripheral system doesn't (currently) support generics, and so we need to wrap this in a
+ * {@link StorageWrapper} box.
*/
@SuppressWarnings("UnstableApiUsage")
-public class InventoryMethods implements GenericPeripheral {
- @Override
- public PeripheralType getType() {
- return PeripheralType.ofAdditional("inventory");
- }
-
- @Override
- public String id() {
- return ComputerCraftAPI.MOD_ID + ":inventory";
- }
-
+public final class InventoryMethods extends AbstractInventoryMethods
- * The generic peripheral system doesn't (currently) support generics, and so we need put the inventory in a box.
*
* @param storage The underlying storage
*/
public record StorageWrapper(SlottedStorage
- * This works with energy storage blocks, as well as generators and machines which consume energy.
- *
- * > [!NOTE]
- * > Due to limitations with Forge's energy API, it is not possible to measure throughput (i.e. RF
- * > used/generated per tick).
- *
- * @cc.module energy_storage
- * @cc.since 1.94.0
+ * Fluid methods for Forge's {@link IEnergyStorage}.
*/
-public class EnergyMethods implements GenericPeripheral {
+public final class EnergyMethods extends AbstractEnergyMethods
- * Each tank either contains some amount of fluid or is empty. Tanks with fluids inside will return some basic
- * information about the fluid, including its name and amount.
- *
- * The returned table is sparse, and so empty tanks will be `nil` - it is recommended to loop over using `pairs`
- * rather than `ipairs`.
- *
- * @param fluids The current fluid handler.
- * @return All tanks.
- * @cc.treturn { (table|nil)... } All tanks in this fluid storage.
- */
@LuaFunction(mainThread = true)
- public static Map
- * This allows you to pull fluid in the current fluid container to another container on the same wired
- * network. Both containers must attached to wired modems which are connected via a cable.
- *
- * @param from Container to move fluid from.
- * @param computer The current computer.
- * @param toName The name of the peripheral/container to push to. This is the string given to [`peripheral.wrap`],
- * and displayed by the wired modem.
- * @param limit The maximum amount of fluid to move.
- * @param fluidName The fluid to move. If not given, an arbitrary fluid will be chosen.
- * @return The amount of moved fluid.
- * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an fluid container.
- * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
- */
+ @Override
@LuaFunction(mainThread = true)
- public static int pushFluid(
+ public int pushFluid(
IFluidHandler from, IComputerAccess computer,
String toName, Optional
- * This allows you to pull fluid in the current fluid container from another container on the same wired
- * network. Both containers must attached to wired modems which are connected via a cable.
- *
- * @param to Container to move fluid to.
- * @param computer The current computer.
- * @param fromName The name of the peripheral/container to push to. This is the string given to [`peripheral.wrap`],
- * and displayed by the wired modem.
- * @param limit The maximum amount of fluid to move.
- * @param fluidName The fluid to move. If not given, an arbitrary fluid will be chosen.
- * @return The amount of moved fluid.
- * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an fluid container.
- * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
- */
+ @Override
@LuaFunction(mainThread = true)
- public static int pullFluid(
+ public int pullFluid(
IFluidHandler to, IComputerAccess computer,
String fromName, Optional
- * Each item in the inventory is represented by a table containing some basic information, much like
- * {@link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail(ILuaContext, Optional, Optional)}
- * includes. More information can be fetched with {@link #getItemDetail}. The table contains the item `name`, the
- * `count` and an a (potentially nil) hash of the item's `nbt.` This NBT data doesn't contain anything useful, but
- * allows you to distinguish identical items.
- *
- * The returned table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs`
- * rather than `ipairs`.
- *
- * @param inventory The current inventory.
- * @return All items in this inventory.
- * @cc.treturn { (table|nil)... } All items in this inventory.
- * @cc.usage Find an adjacent chest and print all items in it.
- *
- *
- * The returned information contains the same information as each item in
- * {@link #list}, as well as additional details like the display name
- * (`displayName`), and item and item durability (`damage`, `maxDamage`, `durability`).
- *
- * Some items include more information (such as enchantments) - it is
- * recommended to print it out using [`textutils.serialize`] or in the Lua
- * REPL, to explore what is available.
- *
- * > [Deprecated fields][!INFO]
- * > Older versions of CC: Tweaked exposed an {@code itemGroups} field, listing the
- * > creative tabs an item was available under. This information is no longer available on
- * > more recent versions of the game, and so this field will always be empty. Do not use this
- * > field in new code!
- *
- * @param inventory The current inventory.
- * @param slot The slot to get information about.
- * @return Information about the item in this slot, or {@code nil} if not present.
- * @throws LuaException If the slot is out of range.
- * @cc.treturn table Information about the item in this slot, or {@code nil} if not present.
- * @cc.usage Print some information about the first in a chest.
- *
- *
- * Typically this will be limited to 64 items. However, some inventories (such as barrels or caches) can store
- * hundreds or thousands of items in one slot.
- *
- * @param inventory Inventory to probe.
- * @param slot The slot
- * @return The maximum number of items in this slot.
- * @throws LuaException If the slot is out of range.
- * @cc.usage Count the maximum number of items an adjacent chest can hold.
- *
- * This allows you to push an item in an inventory to another inventory on the same wired network. Both
- * inventories must attached to wired modems which are connected via a cable.
- *
- * @param from Inventory to move items from.
- * @param computer The current computer.
- * @param toName The name of the peripheral/inventory to push to. This is the string given to [`peripheral.wrap`],
- * and displayed by the wired modem.
- * @param fromSlot The slot in the current inventory to move items to.
- * @param limit The maximum number of items to move. Defaults to the current stack limit.
- * @param toSlot The slot in the target inventory to move to. If not given, the item will be inserted into any slot.
- * @return The number of transferred items.
- * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an inventory.
- * @throws LuaException If either source or destination slot is out of range.
- * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
- * @cc.usage Wrap two chests, and push an item from one to another.
- *
- * This allows you to transfer items between inventories on the same wired network. Both this and the source
- * inventory must attached to wired modems which are connected via a cable.
- *
- * @param to Inventory to move items to.
- * @param computer The current computer.
- * @param fromName The name of the peripheral/inventory to pull from. This is the string given to [`peripheral.wrap`],
- * and displayed by the wired modem.
- * @param fromSlot The slot in the source inventory to move items from.
- * @param limit The maximum number of items to move. Defaults to the current stack limit.
- * @param toSlot The slot in current inventory to move to. If not given, the item will be inserted into any slot.
- * @return The number of transferred items.
- * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an inventory.
- * @throws LuaException If either source or destination slot is out of range.
- * @cc.see peripheral.getName Allows you to get the name of a [wrapped][`peripheral.wrap`] peripheral.
- * @cc.usage Wrap two chests, and push an item from one to another.
- * {@code
+ * local chest = peripheral.find("minecraft:chest")
+ * for slot, item in pairs(chest.list()) do
+ * print(("%d x %s in slot %d"):format(item.count, item.name, slot))
+ * end
+ * }
+ */
+ @LuaFunction(mainThread = true)
+ public abstract Map{@code
+ * local chest = peripheral.find("minecraft:chest")
+ * local item = chest.getItemDetail(1)
+ * if not item then print("No item") return end
+ *
+ * print(("%s (%s)"):format(item.displayName, item.name))
+ * print(("Count: %d/%d"):format(item.count, item.maxCount))
+ *
+ * if item.damage then
+ * print(("Damage: %d/%d"):format(item.damage, item.maxDamage))
+ * end
+ * }
+ */
+ @Nullable
+ @LuaFunction(mainThread = true)
+ public abstract Map{@code
+ * local chest = peripheral.find("minecraft:chest")
+ * local total = 0
+ * for i = 1, chest.size() do
+ * total = total + chest.getItemLimit(i)
+ * end
+ * print(total)
+ * }
+ * @cc.since 1.96.0
+ */
+ @LuaFunction(mainThread = true)
+ public abstract long getItemLimit(T inventory, int slot) throws LuaException;
+
+ /**
+ * Push items from one inventory to another connected one.
+ * {@code
+ * local chest_a = peripheral.wrap("minecraft:chest_0")
+ * local chest_b = peripheral.wrap("minecraft:chest_1")
+ *
+ * chest_a.pushItems(peripheral.getName(chest_b), 1)
+ * }
+ */
+ @LuaFunction(mainThread = true)
+ public abstract int pushItems(
+ T from, IComputerAccess computer, String toName, int fromSlot, Optional{@code
+ * local chest_a = peripheral.wrap("minecraft:chest_0")
+ * local chest_b = peripheral.wrap("minecraft:chest_1")
+ *
+ * chest_a.pullItems(peripheral.getName(chest_b), 1)
+ * }
+ */
+ @LuaFunction(mainThread = true)
+ public abstract int pullItems(
+ T to, IComputerAccess computer, String fromName, int fromSlot, Optional{@code
- * local chest = peripheral.find("minecraft:chest")
- * for slot, item in pairs(chest.list()) do
- * print(("%d x %s in slot %d"):format(item.count, item.name, slot))
- * end
- * }
- */
+ @Override
@LuaFunction(mainThread = true)
- public static Map{@code
- * local chest = peripheral.find("minecraft:chest")
- * local item = chest.getItemDetail(1)
- * if not item then print("No item") return end
- *
- * print(("%s (%s)"):format(item.displayName, item.name))
- * print(("Count: %d/%d"):format(item.count, item.maxCount))
- *
- * if item.damage then
- * print(("Damage: %d/%d"):format(item.damage, item.maxDamage))
- * end
- * }
- */
+ @Override
@Nullable
@LuaFunction(mainThread = true)
- public static Map{@code
- * local chest = peripheral.find("minecraft:chest")
- * local total = 0
- * for i = 1, chest.size() do
- * total = total + chest.getItemLimit(i)
- * end
- * print(total)
- * }
- * @cc.since 1.96.0
- */
+ @Override
@LuaFunction(mainThread = true)
- public static int getItemLimit(IItemHandler inventory, int slot) throws LuaException {
+ public long getItemLimit(IItemHandler inventory, int slot) throws LuaException {
assertBetween(slot, 1, inventory.getSlots(), "Slot out of range (%s)");
return inventory.getSlotLimit(slot - 1);
}
- /**
- * Push items from one inventory to another connected one.
- * {@code
- * local chest_a = peripheral.wrap("minecraft:chest_0")
- * local chest_b = peripheral.wrap("minecraft:chest_1")
- *
- * chest_a.pushItems(peripheral.getName(chest_b), 1)
- * }
- */
+ @Override
@LuaFunction(mainThread = true)
- public static int pushItems(
+ public int pushItems(
IItemHandler from, IComputerAccess computer,
String toName, int fromSlot, Optional{@code
- * local chest_a = peripheral.wrap("minecraft:chest_0")
- * local chest_b = peripheral.wrap("minecraft:chest_1")
- *
- * chest_a.pullItems(peripheral.getName(chest_b), 1)
- * }
- */
+ @Override
@LuaFunction(mainThread = true)
- public static int pullItems(
+ public int pullItems(
IItemHandler to, IComputerAccess computer,
String fromName, int fromSlot, Optional