1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00

Move the core API into a separate module

It should be possible to consume the ComputerCraft's core (i.e.
non-Minecraft code) in other projects, such as emulators.  While this
has been possible for years, it's somewhat tricky from a maintenance
perspective - it's very easy to accidentally add an MC dependency
somewhere!

By publishing a separate "core" jar, we can better distinguish the
boundaries between our Lua runtime and the Minecraft-specific code.

Ideally we could have one core project (rather than separate core and
core-api modules), and publish a separate "api" jar, like we do for the
main mod. However, this isn't really possible to express using Maven
dependencies, and so we must resort to this system.

Of course, this is kinda what the Java module system is meant to solve,
but unfortunately getting that working with Minecraft is infeasible.
This commit is contained in:
Jonathan Coates 2022-11-04 21:41:59 +00:00
parent e4e528e5bf
commit a17b001950
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
47 changed files with 307 additions and 127 deletions

3
.gitignore vendored
View File

@ -2,11 +2,12 @@
/classes
/logs
/build
/projects/*/build
/buildSrc/build
/out
/doc/out/
/node_modules
/.jqwik-database
.jqwik-database
# Runtime directories
/run

View File

@ -9,7 +9,6 @@ plugins {
alias(libs.plugins.librarian)
alias(libs.plugins.shadow)
// Publishing
`maven-publish`
alias(libs.plugins.curseForgeGradle)
alias(libs.plugins.githubRelease)
alias(libs.plugins.minotaur)
@ -19,6 +18,7 @@ plugins {
id("cc-tweaked.illuaminate")
id("cc-tweaked.node")
id("cc-tweaked.gametest")
id("cc-tweaked.publishing")
id("cc-tweaked")
}
@ -26,9 +26,10 @@ val isStable = true
val modVersion: String by extra
val mcVersion: String by extra
group = "org.squiddev"
version = modVersion
base.archivesName.set("cc-tweaked-$mcVersion")
val allProjects = listOf(":core-api").map { evaluationDependsOn(it) }
cct {
allProjects.forEach { externalSources(it) }
}
java.registerFeature("extraMods") { usingSourceSet(sourceSets.main.get()) }
@ -52,7 +53,11 @@ minecraft {
forceExit = false
mods.register("computercraft") { source(sourceSets.main.get()) }
mods.register("computercraft") {
cct.sourceDirectories.get().forEach {
if (it.classes) sources(it.sourceSet)
}
}
}
val client by registering {
@ -149,6 +154,7 @@ dependencies {
"extraModsRuntimeOnly"(fg.deobf("mezz.jei:jei-1.19.2-forge:11.3.0.262"))
"extraModsCompileOnly"(fg.deobf("maven.modrinth:oculus:1.2.5"))
implementation(project(":core-api"))
"shade"(libs.cobalt)
"shade"("io.netty:netty-codec-http:4.1.76.Final")
@ -170,7 +176,6 @@ illuaminate {
tasks.javadoc {
include("dan200/computercraft/api/**/*.java")
(options as StandardJavadocDocletOptions).links("https://docs.oracle.com/en/java/javase/17/docs/api/")
}
val apiJar by tasks.registering(Jar::class) {
@ -216,21 +221,10 @@ tasks.processResources {
}
tasks.jar {
isReproducibleFileOrder = true
isPreserveFileTimestamps = false
finalizedBy("reobfJar")
archiveClassifier.set("slim")
manifest {
attributes(
"Specification-Title" to "computercraft",
"Specification-Vendor" to "SquidDev",
"Specification-Version" to "1",
"Implementation-Title" to "cctweaked",
"Implementation-Version" to modVersion,
"Implementation-Vendor" to "SquidDev",
)
}
from(allProjects.map { zipTree(it.tasks.jar.get().archiveFile) })
}
tasks.shadowJar {
@ -374,7 +368,8 @@ val publishCurseForge by tasks.registering(TaskPublishCurseForge::class) {
val mainFile = upload("282001", tasks.shadowJar.get().archiveFile)
dependsOn(tasks.shadowJar) // Ughr.
mainFile.changelog = "Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
mainFile.changelog =
"Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
mainFile.changelogType = "markdown"
mainFile.releaseType = if (isStable) "release" else "alpha"
mainFile.gameVersions.add(mcVersion)
@ -420,41 +415,9 @@ tasks.publish { dependsOn(tasks.githubRelease) }
publishing {
publications {
register<MavenPublication>("maven") {
artifactId = base.archivesName.get()
from(components["java"])
named("maven", MavenPublication::class) {
artifact(apiJar)
fg.component(this)
pom {
name.set("CC: Tweaked")
description.set("CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.")
url.set("https://github.com/cc-tweaked/CC-Tweaked")
scm {
url.set("https://github.com/cc-tweaked/CC-Tweaked.git")
}
issueManagement {
system.set("github")
url.set("https://github.com/cc-tweaked/CC-Tweaked/issues")
}
licenses {
license {
name.set("ComputerCraft Public License, Version 1.0")
url.set("https://github.com/cc-tweaked/CC-Tweaked/blob/HEAD/LICENSE")
}
}
}
}
}
repositories {
maven("https://squiddev.cc/maven") {
name = "SquidDev"
credentials(PasswordCredentials::class)
}
}
}

View File

@ -11,6 +11,17 @@ plugins {
id("com.diffplug.spotless")
}
val modVersion: String by extra
val mcVersion: String by extra
group = "cc.tweaked"
version = modVersion
base.archivesName.convention(
// TODO: Remove this (and the one below) once we've no longer got a root project!
if (project.path == rootProject.path) "cc-tweaked-$mcVersion" else "cc-tweaked-$mcVersion-${project.name}",
)
java {
toolchain {
languageVersion.set(CCTweakedPlugin.JAVA_VERSION)
@ -53,6 +64,31 @@ tasks.withType(JavaCompile::class.java).configureEach {
options.encoding = "UTF-8"
}
tasks.jar {
isReproducibleFileOrder = true
isPreserveFileTimestamps = false
archiveClassifier.set("slim")
manifest {
attributes(
"Specification-Title" to "computercraft",
"Specification-Vendor" to "SquidDev",
"Specification-Version" to "1",
"Implementation-Title" to (if (project.path == rootProject.path) "cctweaked" else "cctweaked-${project.name}"),
"Implementation-Version" to modVersion,
"Implementation-Vendor" to "SquidDev",
)
}
}
tasks.javadoc {
options {
val stdOptions = this as StandardJavadocDocletOptions
stdOptions.addBooleanOption("Xdoclint:all,-missing", true)
stdOptions.links("https://docs.oracle.com/en/java/javase/17/docs/api/")
}
}
tasks.test {
finalizedBy("jacocoTestReport")
@ -78,8 +114,8 @@ spotless {
}
val licenser = LicenseHeader.create(
api = file("config/license/api.txt"),
main = file("config/license/main.txt"),
api = rootProject.file("config/license/api.txt"),
main = rootProject.file("config/license/main.txt"),
)
java {

View File

@ -0,0 +1,45 @@
import org.gradle.kotlin.dsl.`maven-publish`
plugins {
`java-library`
`maven-publish`
}
publishing {
publications {
register<MavenPublication>("maven") {
artifactId = base.archivesName.get()
from(components["java"])
pom {
name.set("CC: Tweaked")
description.set("CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.")
url.set("https://github.com/cc-tweaked/CC-Tweaked")
scm {
url.set("https://github.com/cc-tweaked/CC-Tweaked.git")
}
issueManagement {
system.set("github")
url.set("https://github.com/cc-tweaked/CC-Tweaked/issues")
}
licenses {
license {
name.set("ComputerCraft Public License, Version 1.0")
url.set("https://github.com/cc-tweaked/CC-Tweaked/blob/HEAD/LICENSE")
}
}
}
}
}
repositories {
maven("https://squiddev.cc/maven") {
name = "SquidDev"
credentials(PasswordCredentials::class)
}
}
}

View File

@ -5,6 +5,7 @@
import org.gradle.api.attributes.TestSuiteType
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.provider.Provider
import org.gradle.api.provider.SetProperty
import org.gradle.api.reporting.ReportingExtension
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.SourceSetContainer
@ -31,7 +32,8 @@ abstract class CCTweakedExtension(
/** Get the current git branch. */
val gitBranch: Provider<String> = gitProvider(project, "<no git branch>") {
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD").trim()
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD")
.trim()
}
/** Get a list of all contributors to the project. */
@ -64,6 +66,30 @@ abstract class CCTweakedExtension(
contributors.sortedWith(String.CASE_INSENSITIVE_ORDER)
}
/**
* References to other sources
*/
val sourceDirectories: SetProperty<SourceSetReference> =
project.objects.setProperty(SourceSetReference::class.java)
/** All source sets referenced by this project. */
val sourceSets = sourceDirectories.map { x -> x.map { it.sourceSet } }
init {
sourceDirectories.finalizeValueOnRead()
}
/**
* Mark this project as consuming another project. Its [sourceDirectories] are added, ensuring tasks are set up
* correctly.
*/
fun externalSources(project: Project) {
val otherCct = project.extensions.getByType(CCTweakedExtension::class.java)
for (sourceSet in otherCct.sourceSets.get()) {
sourceDirectories.add(SourceSetReference.external(sourceSet))
}
}
fun jacoco(task: NamedDomainObjectProvider<JavaExec>) {
val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
val reportTaskName = "jacoco${task.name.capitalized()}Report"

View File

@ -2,14 +2,28 @@
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.testing.jacoco.tasks.JacocoReport
/**
* Configures projects to match a shared configuration.
*/
class CCTweakedPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.extensions.create("cct", CCTweakedExtension::class.java)
val sourceSets = project.extensions.getByType(SourceSetContainer::class.java)
val cct = project.extensions.create("cct", CCTweakedExtension::class.java)
cct.sourceDirectories.add(SourceSetReference.internal(sourceSets.getByName("main")))
project.afterEvaluate {
cct.sourceDirectories.disallowChanges()
}
// Set up jacoco to read from /all/ our source directories.
project.tasks.named("jacocoTestReport", JacocoReport::class.java) {
for (ref in cct.sourceSets.get()) sourceDirectories.from(ref.allSource.sourceDirectories)
}
}
companion object {

View File

@ -0,0 +1,20 @@
package cc.tweaked.gradle
import org.gradle.api.tasks.SourceSet
data class SourceSetReference(
val sourceSet: SourceSet,
val classes: Boolean,
val external: Boolean,
) {
companion object {
/** A source set in the current project. */
fun internal(sourceSet: SourceSet) = SourceSetReference(sourceSet, classes = true, external = false)
/** A source set from another project. */
fun external(sourceSet: SourceSet) = SourceSetReference(sourceSet, classes = true, external = true)
/** A source set which is inlined into the current project. */
fun inline(sourceSet: SourceSet) = SourceSetReference(sourceSet, classes = false, external = false)
}
}

View File

@ -6,11 +6,20 @@ forge = "43.1.1"
parchment = "2022.10.16"
parchmentMc = "1.19.2"
asm = "9.3"
autoService = "1.0.1"
checkerFramework = "3.12.0"
cobalt = { strictly = "[0.5.8,0.6.0)", prefer = "0.5.8" }
fastutil = "8.5.6"
guava = "31.0.1-jre"
jetbrainsAnnotations = "23.0.0"
jsr305 = "3.0.2"
kotlin = "1.7.10"
kotlin-coroutines = "1.6.0"
logback = "1.2.11"
netty = { strictly = "[4.1.77.Final,5.0)", prefer = "4.1.77.Final" }
nightConfig = "3.6.5"
slf4j = "1.7.36"
# Testing
hamcrest = "2.2"
@ -32,11 +41,18 @@ spotless = "6.8.0"
taskTree = "2.1.0"
[libraries]
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
checkerFramework = { module = "org.checkerframework:checker-qual", version.ref = "checkerFramework" }
cobalt = { module = "org.squiddev:Cobalt", version.ref = "cobalt" }
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
guava = { module = "com.google.guava:guava", version.ref = "guava" }
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" }
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
netty-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
# Testing
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }

View File

@ -0,0 +1,27 @@
plugins {
id("cc-tweaked.java-convention")
id("cc-tweaked.publishing")
id("cc-tweaked")
}
java {
withJavadocJar()
}
// Due to the slightly circular nature of our API, add the main API jars to the javadoc classpath.
val docApi by configurations.registering {
isTransitive = false
}
dependencies {
compileOnly(project(":mc-stubs"))
compileOnlyApi(libs.jsr305)
compileOnlyApi(libs.checkerFramework)
"docApi"(project(":"))
}
tasks.javadoc {
// Depend on
classpath += docApi
}

View File

@ -8,6 +8,7 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.Serial;
import java.util.Objects;
/**
@ -16,6 +17,7 @@
* This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure.
*/
public class FileOperationException extends IOException {
@Serial
private static final long serialVersionUID = -8809108200853029849L;
private final String filename;

View File

@ -5,9 +5,7 @@
*/
package dan200.computercraft.api.filesystem;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.level.Level;
import javax.annotation.Nonnull;
import java.io.IOException;
@ -19,12 +17,9 @@
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using
* {@link IComputerAccess#mount(String, IMount)}.
* <p>
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)} or
* {@link ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
* Typically you will not need to implement this interface yourself, and can use the factory methods from the
* {@linkplain dan200.computercraft.api.ComputerCraftAPI the main ComputerCraft API}.
*
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see IComputerAccess#mount(String, IMount)
* @see IWritableMount
*/

View File

@ -5,9 +5,7 @@
*/
package dan200.computercraft.api.filesystem;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.level.Level;
import javax.annotation.Nonnull;
import java.io.IOException;
@ -19,10 +17,9 @@
* Represents a part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)}
* or {@link IComputerAccess#mountWritable(String, IWritableMount)}, that can also be written to.
* <p>
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)}, or you're free to implement it yourselves!
* Typically you will not need to implement this interface yourself, and can use the factory methods from the
* {@linkplain dan200.computercraft.api.ComputerCraftAPI the main ComputerCraft API}.
*
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
* @see IMount

View File

@ -5,31 +5,26 @@
*/
package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.ForgeComputerCraftAPI;
import dan200.computercraft.api.peripheral.GenericPeripheral;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.core.asm.LuaMethod;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
/**
* A generic source of {@link LuaMethod} functions.
* A generic source of {@link LuaFunction} functions.
* <p>
* Unlike normal objects ({@link IDynamicLuaObject} or {@link IPeripheral}), methods do not target this object but
* instead are defined as {@code static} and accept their target as the first parameter. This allows you to inject
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (for instance, a
* {@link Capability}).
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (for instance, a Forge
* capability or Fabric block lookup interface).
* <p>
* Currently the "generic peripheral" system is incompatible with normal peripherals. Normal {@link IPeripheralProvider}
* or {@link IPeripheral} implementations take priority. Tile entities which use this system are given a peripheral name
* determined by their id, rather than any peripheral provider. This will hopefully change in the future, once a suitable
* design has been established.
* Currently the "generic peripheral" system is incompatible with normal peripherals. Peripherals explicitly provided
* by capabilities/the block lookup API take priority. Block entities which use this system are given a peripheral name
* determined by their id, rather than any peripheral provider, though additional types may be provided by overriding
* {@link GenericPeripheral#getType()}.
* <p>
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link IItemHandler}s:
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@code IItemHandler}s:
*
* <pre>{@code
* public class InventoryMethods implements GenericSource {
@ -42,9 +37,10 @@
* }
* }</pre>
*
* @see ComputerCraftAPI#registerGenericSource(GenericSource)
* @see ForgeComputerCraftAPI#registerGenericCapability(Capability) New capabilities (those not built into Forge) must be
* explicitly given to the generic peripheral system, as there is no way to enumerate all capabilities.
* @see dan200.computercraft.api.ComputerCraftAPI#registerGenericSource(GenericSource)
* @see dan200.computercraft.api.ForgeComputerCraftAPI#registerGenericCapability New capabilities (those not
* built into Forge) must be explicitly given to the generic peripheral system, as there is no way to enumerate all
* capabilities.
*/
public interface GenericSource {
/**

View File

@ -11,8 +11,6 @@
import java.util.Map;
import java.util.Optional;
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
/**
* The arguments passed to a function.
*/
@ -102,7 +100,7 @@ default long getLong(int index) throws LuaException {
* @throws LuaException If the value is not finite.
*/
default double getFiniteDouble(int index) throws LuaException {
return checkFinite(index, getDouble(index));
return LuaValues.checkFinite(index, getDouble(index));
}
/**

View File

@ -5,8 +5,6 @@
*/
package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
/**
* Represents a Lua object which is stored as a global variable on computer startup. This must either provide
* {@link LuaFunction} annotated functions or implement {@link IDynamicLuaObject}.
@ -14,8 +12,7 @@
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
* to use peripherals to provide functionality to users.
*
* @see ILuaAPIFactory
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
* @see ILuaAPIFactory For providing custom APIs to computers.
*/
public interface ILuaAPI {
/**

View File

@ -5,8 +5,6 @@
*/
package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -14,7 +12,7 @@
* Construct an {@link ILuaAPI} for a specific computer.
*
* @see ILuaAPI
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
* @see dan200.computercraft.api.ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
*/
@FunctionalInterface
public interface ILuaAPIFactory {

View File

@ -6,11 +6,13 @@
package dan200.computercraft.api.lua;
import javax.annotation.Nullable;
import java.io.Serial;
/**
* An exception representing an error in Lua, like that raised by the {@code error()} function.
*/
public class LuaException extends Exception {
@Serial
private static final long serialVersionUID = -6136063076818512651L;
private final boolean hasLevel;
private final int level;

View File

@ -11,6 +11,13 @@
import static dan200.computercraft.api.lua.LuaValues.*;
/**
* A view of a Lua table, which may be able to access table elements in a more optimised manner than
* {@link IArguments#getTable(int)}.
*
* @param <K> The type of keys in a table, will typically be a wildcard.
* @param <V> The type of values in a table, will typically be a wildcard.
*/
public interface LuaTable<K, V> extends Map<K, V> {
/**
* Compute the length of the array part of this table.
@ -77,7 +84,6 @@ default int getInt(String key) throws LuaException {
return (int) getLong(key);
}
@Nullable
@Override
default V put(K o, V o2) {

View File

@ -11,6 +11,9 @@
import java.util.Map;
import java.util.Set;
/**
* An implementation of {@link LuaTable} based on a standard Java {@link Map}.
*/
public class ObjectLuaTable implements LuaTable<Object, Object> {
private final Map<Object, Object> map;

View File

@ -6,8 +6,6 @@
package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.lua.GenericSource;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
@ -15,14 +13,14 @@
* A {@link GenericSource} which provides methods for a peripheral.
* <p>
* Unlike a {@link GenericSource}, all methods <strong>should</strong> target the same type, for instance a
* {@link BlockEntity} subclass or a capability interface. This is not currently enforced.
* block entity subclass. This is not currently enforced.
*/
public interface GenericPeripheral extends GenericSource {
/**
* Get the type of the exposed peripheral.
* <p>
* 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 {@link BlockEntity} (for instance {@code minecraft:chest}).
* resulting peripheral uses the resource name of the wrapped block entity (for instance {@code minecraft:chest}).
* <p>
* However, in some cases it may be more appropriate to specify a more readable name. Overriding this method allows
* you to do so.
@ -31,7 +29,7 @@ public interface GenericPeripheral extends GenericSource {
* lexicographically smallest will be chosen. In order to avoid this conflict, this method should only be
* implemented when your peripheral targets a single tile entity <strong>AND</strong> it's likely that you're the
* only mod to do so. Similarly this should <strong>NOT</strong> be implemented when your methods target a
* capability or other interface (i.e. {@link IItemHandler}).
* capability or other interface (such as Forge's {@code IItemHandler}).
*
* @return The type of this peripheral or {@link PeripheralType#untyped()}.
* @see IPeripheral#getType()

View File

@ -5,14 +5,12 @@
*/
package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.ILuaCallback;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.MethodResult;
import net.minecraft.world.level.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -32,8 +30,6 @@ public interface IComputerAccess {
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount, String)
* @see #mountWritable(String, IWritableMount)
* @see #unmount(String)
@ -53,8 +49,6 @@ default String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) {
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount)
* @see #mountWritable(String, IWritableMount)
* @see #unmount(String)
@ -71,8 +65,6 @@ default String mount(@Nonnull String desiredLocation, @Nonnull IMount mount) {
* @return The location on the computer's file system where you the mount mounted, or null if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount)
* @see #unmount(String)
* @see IMount
@ -91,8 +83,6 @@ default String mountWritable(@Nonnull String desiredLocation, @Nonnull IWritable
* @return The location on the computer's file system where you the mount mounted, or null if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
* @see #mount(String, IMount)
* @see #unmount(String)
* @see IMount

View File

@ -6,7 +6,6 @@
package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.lua.LuaFunction;
import net.minecraftforge.common.capabilities.Capability;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -16,8 +15,8 @@
/**
* The interface that defines a peripheral.
* <p>
* In order to expose a peripheral for your block or tile entity, you may either attach a {@link Capability}, or
* register a {@link IPeripheralProvider}. This <em>cannot</em> be implemented {@link IPeripheral} directly on the tile.
* In order to expose a peripheral for your block or block entity, you should either attach a capability (Forge) or
* use the block lookup API (Fabric). This interface <em>cannot</em> be implemented directly on the block entity.
* <p>
* Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing
* {@link IDynamicPeripheral}.

View File

@ -5,11 +5,14 @@
*/
package dan200.computercraft.api.peripheral;
import java.io.Serial;
/**
* Thrown when performing operations on {@link IComputerAccess} when the current peripheral is no longer attached to
* the computer.
*/
public class NotAttachedException extends IllegalStateException {
@Serial
private static final long serialVersionUID = 1221244785535553536L;
public NotAttachedException() {

View File

@ -5,9 +5,6 @@
*/
package dan200.computercraft.api.peripheral;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
@ -29,8 +26,8 @@ public final class PeripheralType {
public PeripheralType(String type, Set<String> additionalTypes) {
this.type = type;
this.additionalTypes = additionalTypes;
if (additionalTypes.contains(null)) {
throw new IllegalArgumentException("All additional types must be non-null");
for (var item : additionalTypes) {
if (item == null) throw new NullPointerException("All additional types must be non-null");
}
}
@ -50,7 +47,7 @@ public static PeripheralType untyped() {
* @return The constructed peripheral type.
*/
public static PeripheralType ofType(@Nonnull String type) {
if (Strings.isNullOrEmpty(type)) throw new IllegalArgumentException("type cannot be null or empty");
checkTypeName("type cannot be null or empty");
return new PeripheralType(type, Collections.emptySet());
}
@ -62,8 +59,8 @@ public static PeripheralType ofType(@Nonnull String type) {
* @return The constructed peripheral type.
*/
public static PeripheralType ofType(@Nonnull String type, Collection<String> additionalTypes) {
if (Strings.isNullOrEmpty(type)) throw new IllegalArgumentException("type cannot be null or empty");
return new PeripheralType(type, ImmutableSet.copyOf(additionalTypes));
checkTypeName("type cannot be null or empty");
return new PeripheralType(type, getTypes(additionalTypes));
}
/**
@ -74,8 +71,8 @@ public static PeripheralType ofType(@Nonnull String type, Collection<String> add
* @return The constructed peripheral type.
*/
public static PeripheralType ofType(@Nonnull String type, @Nonnull String... additionalTypes) {
if (Strings.isNullOrEmpty(type)) throw new IllegalArgumentException("type cannot be null or empty");
return new PeripheralType(type, ImmutableSet.copyOf(additionalTypes));
checkTypeName(type);
return new PeripheralType(type, Set.of(additionalTypes));
}
/**
@ -85,7 +82,7 @@ public static PeripheralType ofType(@Nonnull String type, @Nonnull String... add
* @return The constructed peripheral type.
*/
public static PeripheralType ofAdditional(Collection<String> additionalTypes) {
return new PeripheralType(null, ImmutableSet.copyOf(additionalTypes));
return new PeripheralType(null, getTypes(additionalTypes));
}
/**
@ -95,7 +92,7 @@ public static PeripheralType ofAdditional(Collection<String> additionalTypes) {
* @return The constructed peripheral type.
*/
public static PeripheralType ofAdditional(@Nonnull String... additionalTypes) {
return new PeripheralType(null, ImmutableSet.copyOf(additionalTypes));
return new PeripheralType(null, Set.of(additionalTypes));
}
/**
@ -117,4 +114,14 @@ public String getPrimaryType() {
public Set<String> getAdditionalTypes() {
return additionalTypes;
}
private static void checkTypeName(@Nullable String type) {
if (type == null || type.isEmpty()) throw new IllegalArgumentException("type cannot be null or empty");
}
private static Set<String> getTypes(Collection<String> types) {
if (types.isEmpty()) return Collections.emptySet();
if (types.size() == 1) return Collections.singleton(types.iterator().next());
return Set.copyOf(types);
}
}

View File

@ -0,0 +1,8 @@
plugins {
id("cc-tweaked.java-convention")
}
// Skip checkstyle here, it's going to be deleted soon anyway!
tasks.checkstyleMain {
enabled = false
}

View File

@ -0,0 +1,14 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package net.minecraft.resources;
/**
* Placeholder class so we can preserve API compatibility for this release.
*/
public final class ResourceLocation {
private ResourceLocation() {
}
}

View File

@ -15,3 +15,10 @@ pluginManagement {
val mcVersion: String by settings
rootProject.name = "cc-tweaked-$mcVersion"
include(":mc-stubs")
include(":core-api")
for (project in rootProject.children) {
project.projectDir = file("projects/${project.name}")
}

View File

@ -8,11 +8,13 @@
import dan200.computercraft.api.lua.LuaException;
import javax.annotation.Nullable;
import java.io.Serial;
/**
* A Lua exception which does not contain its stack trace.
*/
public class FastLuaException extends LuaException {
@Serial
private static final long serialVersionUID = 5957864899303561143L;
public FastLuaException(@Nullable String message) {

View File

@ -5,7 +5,10 @@
*/
package dan200.computercraft.core.apis.http;
import java.io.Serial;
public class HTTPRequestException extends Exception {
@Serial
private static final long serialVersionUID = 7591208619422744652L;
public HTTPRequestException(String s) {

View File

@ -5,7 +5,10 @@
*/
package dan200.computercraft.core.filesystem;
import java.io.Serial;
public class FileSystemException extends Exception {
@Serial
private static final long serialVersionUID = -2500631644868104029L;
FileSystemException(String s) {

View File

@ -30,6 +30,7 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.InputStream;
import java.io.Serial;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.SynchronousQueue;
@ -444,6 +445,7 @@ private void handlePause(DebugState ds, DebugFrame di) throws LuaError, UnwindTh
}
private static final class HardAbortError extends Error {
@Serial
private static final long serialVersionUID = 7954092008586367501L;
static final HardAbortError INSTANCE = new HardAbortError();

View File

@ -8,6 +8,7 @@
import org.jetbrains.annotations.ApiStatus;
import javax.annotation.Nullable;
import java.io.Serial;
/**
* A ComputerCraft-related service failed to load.
@ -16,6 +17,7 @@
*/
@ApiStatus.Internal
class ServiceException extends RuntimeException {
@Serial
private static final long serialVersionUID = -8392300691666423882L;
ServiceException(String message, @Nullable Throwable cause) {