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 The type for energy storage. + * @cc.module energy_storage + * @cc.since 1.94.0 + */ +public abstract class AbstractEnergyMethods implements GenericPeripheral { + @Override + public final PeripheralType getType() { + return PeripheralType.ofAdditional("energy_storage"); + } + + @Override + public final String id() { + return ComputerCraftAPI.MOD_ID + ":energy"; + } + + /** + * Get the energy of this block. + * + * @param energy The current energy storage. + * @return The energy stored in this block, in FE. + */ + @LuaFunction(mainThread = true) + public abstract int getEnergy(T energy); + + /** + * Get the maximum amount of energy this block can store. + * + * @param energy The current energy storage. + * @return The energy capacity of this block. + */ + @LuaFunction(mainThread = true) + public abstract int getEnergyCapacity(T energy); +} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractFluidMethods.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractFluidMethods.java new file mode 100644 index 000000000..e409a558c --- /dev/null +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractFluidMethods.java @@ -0,0 +1,92 @@ +// 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.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.peripheral.GenericPeripheral; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.PeripheralType; + +import java.util.Map; +import java.util.Optional; + +/** + * Methods for interacting with tanks and other fluid storage blocks. + * + * @param The type for fluid inventories. + * @cc.module fluid_storage + * @cc.since 1.94.0 + */ +public abstract class AbstractFluidMethods implements GenericPeripheral { + @Override + public final PeripheralType getType() { + return PeripheralType.ofAdditional("fluid_storage"); + } + + @Override + public final String id() { + return ComputerCraftAPI.MOD_ID + ":fluid"; + } + + /** + * Get all "tanks" in this fluid storage. + *

+ * 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> tanks(T fluids); + + /** + * Move a fluid from one fluid container to another connected one. + *

+ * 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 limit, Optional fluidName + ) throws LuaException; + + /** + * Move a fluid from a connected fluid container into this oneone. + *

+ * 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 limit, Optional fluidName + ) throws LuaException; +} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractInventoryMethods.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractInventoryMethods.java new file mode 100644 index 000000000..1115a46a8 --- /dev/null +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/AbstractInventoryMethods.java @@ -0,0 +1,197 @@ +// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers +// +// SPDX-License-Identifier: LicenseRef-CCPL + +package dan200.computercraft.shared.peripheral.generic.methods; + +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.peripheral.GenericPeripheral; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.PeripheralType; + +import javax.annotation.Nullable; +import java.util.Map; +import java.util.Optional; + +/** + * Methods for interacting with inventories. + * + * @param The type for inventories. + * @cc.module inventory + * @cc.since 1.94.0 + */ +public abstract class AbstractInventoryMethods implements GenericPeripheral { + @Override + public final PeripheralType getType() { + return PeripheralType.ofAdditional("inventory"); + } + + @Override + public final String id() { + return ComputerCraftAPI.MOD_ID + ":inventory"; + } + + /** + * Get the size of this inventory. + * + * @param inventory The current inventory. + * @return The number of slots in this inventory. + */ + @LuaFunction(mainThread = true) + public abstract int size(T inventory); + + /** + * List all items in this inventory. This returns a table, with an entry for each slot. + *

+ * 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. + * + *

{@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> list(T inventory); + + /** + * Get detailed information about an item. + *

+ * 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. + * + *

{@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 getItemDetail(T inventory, int slot) throws LuaException; + + /** + * Get the maximum number of items which can be stored in this slot. + *

+ * 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. + *

{@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. + *

+ * 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. + *

{@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 limit, Optional toSlot + ) throws LuaException; + + /** + * Pull items from a connected inventory into this one. + *

+ * 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_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 limit, Optional toSlot + ) throws LuaException; +} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java index 77f291ebb..3999149c3 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -11,6 +11,7 @@ import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.core.apis.IAPIEnvironment; import dan200.computercraft.core.metrics.Metrics; +import dan200.computercraft.shared.peripheral.generic.methods.AbstractInventoryMethods; import dan200.computercraft.shared.turtle.core.*; import java.util.Optional; @@ -749,7 +750,7 @@ public class TurtleAPI implements ILuaAPI { * -- count = 13, * -- } * } - * @see dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods#getItemDetail Describes the information returned by a detailed query. + * @see AbstractInventoryMethods#getItemDetail Describes the information returned by a detailed query. */ @LuaFunction public final MethodResult getItemDetail(ILuaContext context, Optional slot, Optional detailed) throws LuaException { diff --git a/projects/core/src/main/java/dan200/computercraft/core/asm/Generator.java b/projects/core/src/main/java/dan200/computercraft/core/asm/Generator.java index 2a95e1c7a..8124a54c4 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/asm/Generator.java +++ b/projects/core/src/main/java/dan200/computercraft/core/asm/Generator.java @@ -171,7 +171,7 @@ final class Generator { // Instance methods must be final - this prevents them being overridden and potentially exposed twice. var modifiers = method.getModifiers(); - if (!Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) { + if (!Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers) && !Modifier.isFinal(method.getDeclaringClass().getModifiers())) { LOG.warn("Lua Method {}.{} should be final.", method.getDeclaringClass().getName(), method.getName()); } diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java index dfbbdf5b7..e1848775b 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java @@ -4,14 +4,11 @@ package dan200.computercraft.shared.peripheral.generic.methods; -import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.detail.VanillaDetailRegistries; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.GenericPeripheral; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.PeripheralType; import dan200.computercraft.shared.platform.FabricContainerTransfer; import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; @@ -32,37 +29,30 @@ import java.util.Optional; import static dan200.computercraft.core.util.ArgumentHelpers.assertBetween; /** - * Methods for interacting with inventories. This mirrors the Forge version. + * Inventory methods for Fabric's {@link SlottedStorage} and {@link ItemVariant}s. + *

+ * 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 { /** * Wrapper over a {@link SlottedStorage}. - *

- * 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 storage) { } + @Override @LuaFunction(mainThread = true) - public static int size(StorageWrapper inventory) { + public int size(StorageWrapper inventory) { return inventory.storage().getSlots().size(); } + @Override @LuaFunction(mainThread = true) - public static Map> list(StorageWrapper inventory) { + public Map> list(StorageWrapper inventory) { Map> result = new HashMap<>(); var slots = inventory.storage().getSlots(); var size = slots.size(); @@ -74,23 +64,26 @@ public class InventoryMethods implements GenericPeripheral { return result; } + @Override @Nullable @LuaFunction(mainThread = true) - public static Map getItemDetail(StorageWrapper inventory, int slot) throws LuaException { + public Map getItemDetail(StorageWrapper inventory, int slot) throws LuaException { assertBetween(slot, 1, inventory.storage().getSlotCount(), "Slot out of range (%s)"); var stack = toStack(inventory.storage().getSlot(slot - 1)); return stack.isEmpty() ? null : VanillaDetailRegistries.ITEM_STACK.getDetails(stack); } + @Override @LuaFunction(mainThread = true) - public static long getItemLimit(StorageWrapper inventory, int slot) throws LuaException { + public long getItemLimit(StorageWrapper inventory, int slot) throws LuaException { assertBetween(slot, 1, inventory.storage().getSlotCount(), "Slot out of range (%s)"); return inventory.storage().getSlot(slot - 1).getCapacity(); } + @Override @LuaFunction(mainThread = true) - public static int pushItems( + public int pushItems( StorageWrapper from, IComputerAccess computer, String toName, int fromSlot, Optional limit, Optional toSlot ) throws LuaException { @@ -112,8 +105,9 @@ public class InventoryMethods implements GenericPeripheral { return moveItem(fromStorage, fromSlot - 1, to, toSlot.orElse(0) - 1, actualLimit); } + @Override @LuaFunction(mainThread = true) - public static int pullItems( + public int pullItems( StorageWrapper to, IComputerAccess computer, String fromName, int fromSlot, Optional limit, Optional toSlot ) throws LuaException { diff --git a/projects/forge/build.gradle.kts b/projects/forge/build.gradle.kts index 4a840b561..64b839fb3 100644 --- a/projects/forge/build.gradle.kts +++ b/projects/forge/build.gradle.kts @@ -9,7 +9,6 @@ plugins { id("cc-tweaked.forge") id("cc-tweaked.gametest") alias(libs.plugins.mixinGradle) - id("cc-tweaked.illuaminate") id("cc-tweaked.mod-publishing") } @@ -117,7 +116,6 @@ mixin { } configurations { - register("cctJavadoc") minecraftLibrary { extendsFrom(minecraftEmbed.get()) } } @@ -167,40 +165,10 @@ dependencies { testModImplementation(testFixtures(project(":forge"))) testFixturesImplementation(testFixtures(project(":core"))) - - "cctJavadoc"(libs.cctJavadoc) -} - -illuaminate { - version.set(libs.versions.illuaminate) } // Compile tasks -val luaJavadoc by tasks.registering(Javadoc::class) { - description = "Generates documentation for Java-side Lua functions." - group = JavaBasePlugin.DOCUMENTATION_GROUP - - source(sourceSets.main.get().java) - source(project(":core").sourceSets.main.get().java) - source(project(":common").sourceSets.main.get().java) - - destinationDir = layout.buildDirectory.dir("docs/luaJavadoc").get().asFile - classpath = sourceSets.main.get().compileClasspath - - 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) - }, - ) -} - tasks.processResources { inputs.property("modVersion", modVersion) inputs.property("forgeVersion", libs.versions.forge.get()) @@ -240,24 +208,6 @@ tasks.test { systemProperty("cct.test-files", layout.buildDirectory.dir("tmp/testFiles").getAbsolutePath()) } -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::") } -} - val runGametest by tasks.registering(JavaExec::class) { group = LifecycleBasePlugin.VERIFICATION_GROUP description = "Runs tests on a temporary Minecraft instance." diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/EnergyMethods.java b/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/EnergyMethods.java index 992675cbf..0ed265585 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/EnergyMethods.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/EnergyMethods.java @@ -4,54 +4,22 @@ 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; import net.minecraftforge.energy.IEnergyStorage; /** - * Methods for interacting with blocks using Forge's energy storage system. - *

- * 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 { @Override - public PeripheralType getType() { - return PeripheralType.ofAdditional("energy_storage"); - } - - @Override - public String id() { - return ComputerCraftAPI.MOD_ID + ":energy"; - } - - /** - * Get the energy of this block. - * - * @param energy The current energy storage. - * @return The energy stored in this block, in FE. - */ @LuaFunction(mainThread = true) - public static int getEnergy(IEnergyStorage energy) { + public int getEnergy(IEnergyStorage energy) { return energy.getEnergyStored(); } - /** - * Get the maximum amount of energy this block can store. - * - * @param energy The current energy storage. - * @return The energy capacity of this block. - */ + @Override @LuaFunction(mainThread = true) - public static int getEnergyCapacity(IEnergyStorage energy) { + public int getEnergyCapacity(IEnergyStorage energy) { return energy.getMaxEnergyStored(); } } diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java b/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java index aebd51b66..a550b073f 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java @@ -4,13 +4,10 @@ package dan200.computercraft.shared.peripheral.generic.methods; -import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.detail.ForgeDetailRegistries; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.GenericPeripheral; import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.PeripheralType; import dan200.computercraft.shared.platform.RegistryWrappers; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.common.capabilities.ForgeCapabilities; @@ -26,37 +23,12 @@ import java.util.Optional; import static dan200.computercraft.shared.util.ArgumentHelpers.getRegistryEntry; /** - * Methods for interacting with tanks and other fluid storage blocks. - * - * @cc.module fluid_storage - * @cc.since 1.94.0 + * Fluid methods for Forge's {@link IFluidHandler}. */ -public class FluidMethods implements GenericPeripheral { +public final class FluidMethods extends AbstractFluidMethods { @Override - public PeripheralType getType() { - return PeripheralType.ofAdditional("fluid_storage"); - } - - @Override - public String id() { - return ComputerCraftAPI.MOD_ID + ":fluid"; - } - - /** - * Get all "tanks" in this fluid storage. - *

- * 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> tanks(IFluidHandler fluids) { + public Map> tanks(IFluidHandler fluids) { Map> result = new HashMap<>(); var size = fluids.getTanks(); for (var i = 0; i < size; i++) { @@ -67,24 +39,9 @@ public class FluidMethods implements GenericPeripheral { return result; } - /** - * Move a fluid from one fluid container to another connected one. - *

- * 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 limit, Optional fluidName ) throws LuaException { @@ -107,24 +64,9 @@ public class FluidMethods implements GenericPeripheral { : moveFluid(from, new FluidStack(fluid, actualLimit), to); } - /** - * Move a fluid from a connected fluid container into this oneone. - *

- * 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 limit, Optional fluidName ) throws LuaException { @@ -194,7 +136,7 @@ public class FluidMethods implements GenericPeripheral { * @return The amount of fluid moved. */ private static int moveFluid(IFluidHandler from, FluidStack extracted, int limit, IFluidHandler to) { - if (extracted == null || extracted.getAmount() <= 0) return 0; + if (extracted.getAmount() <= 0) return 0; // Limit the amount to extract. extracted = extracted.copy(); diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java index 1fead136b..49ab64b2d 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java @@ -4,14 +4,10 @@ package dan200.computercraft.shared.peripheral.generic.methods; -import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.detail.VanillaDetailRegistries; -import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.GenericPeripheral; import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.PeripheralType; import dan200.computercraft.shared.platform.ForgeContainerTransfer; import net.minecraft.world.Container; import net.minecraft.world.level.block.entity.BlockEntity; @@ -28,59 +24,18 @@ import java.util.Optional; import static dan200.computercraft.core.util.ArgumentHelpers.assertBetween; /** - * Methods for interacting with inventories. - * - * @cc.module inventory - * @cc.since 1.94.0 + * Inventory methods for Forge's {@link IItemHandler}. */ -public class InventoryMethods implements GenericPeripheral { +public final class InventoryMethods extends AbstractInventoryMethods { @Override - public PeripheralType getType() { - return PeripheralType.ofAdditional("inventory"); - } - - @Override - public String id() { - return ComputerCraftAPI.MOD_ID + ":inventory"; - } - - /** - * Get the size of this inventory. - * - * @param inventory The current inventory. - * @return The number of slots in this inventory. - */ @LuaFunction(mainThread = true) - public static int size(IItemHandler inventory) { + public int size(IItemHandler inventory) { return inventory.getSlots(); } - /** - * List all items in this inventory. This returns a table, with an entry for each slot. - *

- * 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. - * - *

{@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> list(IItemHandler inventory) { + public Map> list(IItemHandler inventory) { Map> result = new HashMap<>(); var size = inventory.getSlots(); for (var i = 0; i < size; i++) { @@ -91,106 +46,26 @@ public class InventoryMethods implements GenericPeripheral { return result; } - /** - * Get detailed information about an item. - *

- * 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. - * - *

{@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 getItemDetail(IItemHandler inventory, int slot) throws LuaException { + public Map getItemDetail(IItemHandler inventory, int slot) throws LuaException { assertBetween(slot, 1, inventory.getSlots(), "Slot out of range (%s)"); var stack = inventory.getStackInSlot(slot - 1); return stack.isEmpty() ? null : VanillaDetailRegistries.ITEM_STACK.getDetails(stack); } - /** - * Get the maximum number of items which can be stored in this slot. - *

- * 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. - *

{@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. - *

- * 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. - *

{@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 limit, Optional toSlot ) throws LuaException { @@ -210,33 +85,9 @@ public class InventoryMethods implements GenericPeripheral { return moveItem(from, fromSlot - 1, to, toSlot.orElse(0) - 1, actualLimit); } - /** - * Pull items from a connected inventory into this one. - *

- * 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_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 limit, Optional toSlot ) throws LuaException { diff --git a/projects/web/build.gradle.kts b/projects/web/build.gradle.kts index 58a4d0189..c1df434dd 100644 --- a/projects/web/build.gradle.kts +++ b/projects/web/build.gradle.kts @@ -94,7 +94,7 @@ val illuaminateDocs by tasks.registering(cc.tweaked.gradle.IlluaminateExecToDir: // Sources inputs.files(rootProject.fileTree("doc")).withPropertyName("docs") inputs.files(project(":core").fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom") - inputs.files(project(":forge").tasks.named("luaJavadoc")) + inputs.files(project(":common").tasks.named("luaJavadoc")) // Assets inputs.files(rollup) diff --git a/projects/web/src/main/java/dan200/computercraft/core/asm/StaticGenerator.java b/projects/web/src/main/java/dan200/computercraft/core/asm/StaticGenerator.java index 066ffc3ef..dddf9a7af 100644 --- a/projects/web/src/main/java/dan200/computercraft/core/asm/StaticGenerator.java +++ b/projects/web/src/main/java/dan200/computercraft/core/asm/StaticGenerator.java @@ -87,21 +87,16 @@ public final class StaticGenerator { var name = method.getDeclaringClass().getName() + "." + method.getName(); var modifiers = method.getModifiers(); - // Instance methods must be final - this prevents them being overridden and potentially exposed twice. - if (!Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) { + // Methods must be final - this prevents them being overridden and potentially exposed twice. + if (!Modifier.isFinal(modifiers) && !Modifier.isFinal(method.getDeclaringClass().getModifiers())) { System.err.printf("Lua Method %s should be final.\n", name); } - if (!Modifier.isPublic(modifiers)) { + if (!Modifier.isPublic(modifiers) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { System.err.printf("Lua Method %s should be a public method.\n", name); return Optional.empty(); } - if (!Modifier.isPublic(method.getDeclaringClass().getModifiers())) { - System.err.printf("Lua Method %s should be on a public class.\n", name); - return Optional.empty(); - } - var exceptions = method.getExceptionTypes(); for (var exception : exceptions) { if (exception != LuaException.class) { @@ -116,11 +111,8 @@ public final class StaticGenerator { return Optional.empty(); } - // We have some rather ugly handling of static methods in both here and the main generate function. Static methods - // only come from generic sources, so this should be safe. - var target = Modifier.isStatic(modifiers) ? method.getParameterTypes()[0] : method.getDeclaringClass(); - try { + var target = method.getDeclaringClass(); var bytes = generate(classPrefix + method.getDeclaringClass().getSimpleName() + "$" + method.getName(), target, method, annotation.unsafe()); if (bytes == null) return Optional.empty(); @@ -170,11 +162,9 @@ public final class StaticGenerator { var mw = cw.visitMethod(ACC_PUBLIC, METHOD_NAME, methodDesc, null, EXCEPTIONS); mw.visitCode(); - // If we're an instance method, load the target as the first argument. - if (!Modifier.isStatic(targetMethod.getModifiers())) { - mw.visitVarInsn(ALOAD, 1); - mw.visitTypeInsn(CHECKCAST, Type.getInternalName(target)); - } + // Load the target as the first argument. + mw.visitVarInsn(ALOAD, 1); + mw.visitTypeInsn(CHECKCAST, Type.getInternalName(target)); var argIndex = 0; for (var genericArg : targetMethod.getGenericParameterTypes()) { @@ -184,7 +174,7 @@ public final class StaticGenerator { } mw.visitMethodInsn( - Modifier.isStatic(targetMethod.getModifiers()) ? INVOKESTATIC : INVOKEVIRTUAL, + INVOKEVIRTUAL, Type.getInternalName(targetMethod.getDeclaringClass()), targetMethod.getName(), Type.getMethodDescriptor(targetMethod), false ); @@ -244,12 +234,10 @@ public final class StaticGenerator { if (klass == null) return null; if (klass == String.class) { - mw.visitTypeInsn(NEW, INTERNAL_COERCED); - mw.visitInsn(DUP); - mw.visitVarInsn(ALOAD, 2 + context.size()); - loadInt(mw, argIndex); - mw.visitMethodInsn(INVOKEINTERFACE, INTERNAL_ARGUMENTS, "getStringCoerced", "(I)Ljava/lang/String;", true); - mw.visitMethodInsn(INVOKESPECIAL, INTERNAL_COERCED, "", "(Ljava/lang/Object;)V", false); + loadCoerced(mw, argIndex, "getStringCoerced", "(I)Ljava/lang/String;"); + return true; + } else if (klass == ByteBuffer.class) { + loadCoerced(mw, argIndex, "getBytesCoerced", "(I)Ljava/nio/ByteBuffer;"); return true; } } @@ -324,6 +312,15 @@ public final class StaticGenerator { } } + private void loadCoerced(MethodVisitor mw, int argIndex, String getter, String getterType) { + mw.visitTypeInsn(NEW, INTERNAL_COERCED); + mw.visitInsn(DUP); + mw.visitVarInsn(ALOAD, 2 + context.size()); + loadInt(mw, argIndex); + mw.visitMethodInsn(INVOKEINTERFACE, INTERNAL_ARGUMENTS, getter, getterType, true); + mw.visitMethodInsn(INVOKESPECIAL, INTERNAL_COERCED, "", "(Ljava/lang/Object;)V", false); + } + @SuppressWarnings("Guava") static com.google.common.base.Function catching(Function function, U def) { return x -> {