mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-11-04 17:16:20 +00:00
Move our public API into separate modules
This adds two new modules: common-api and forge-api, which contain the common and Forge-specific interfaces for CC's Minecraft-specific API. We add a new PlatformHelper interface, which abstracts over some of the loader-specific functionality, such as reading registries[^1] or calling Forge-specific methods. This interface is then implemented in the main mod, and loaded via ServiceLoaders. Some other notes on this: - We now split shared and client-specific source code into separate modules. This is to make it harder to reference client code on the server, thus crashing the game. Eventually we'll split the main mod up too into separate source sets - this is, of course, a much bigger problem! - There's currently some nastiness here due to wanting to preserve binary compatibility of the API. We'll hopefully be able to remove this when 1.19.3 releases. - In order to build a separate Forge-specific API jar, we compile the common sources twice: once for the common jar and once for the Forge jar. Getting this to play nicely with IDEs is a little tricky and so we provide a cct.inlineProject(...) helper to handle everything. [^1]: We /can/ do this with vanilla's APIs, but it gives a lot of deprecation warnings. It just ends up being nicer to abstract over it.
This commit is contained in:
parent
d8e2161f15
commit
76710eec9d
@ -6,9 +6,9 @@ import org.jetbrains.gradle.ext.settings
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
// Build
|
// Build
|
||||||
alias(libs.plugins.forgeGradle)
|
id("net.minecraftforge.gradle")
|
||||||
alias(libs.plugins.mixinGradle)
|
alias(libs.plugins.mixinGradle)
|
||||||
alias(libs.plugins.librarian)
|
id("org.parchmentmc.librarian.forgegradle")
|
||||||
alias(libs.plugins.shadow)
|
alias(libs.plugins.shadow)
|
||||||
// Publishing
|
// Publishing
|
||||||
alias(libs.plugins.curseForgeGradle)
|
alias(libs.plugins.curseForgeGradle)
|
||||||
@ -16,7 +16,7 @@ plugins {
|
|||||||
alias(libs.plugins.minotaur)
|
alias(libs.plugins.minotaur)
|
||||||
// Utility
|
// Utility
|
||||||
alias(libs.plugins.taskTree)
|
alias(libs.plugins.taskTree)
|
||||||
alias(libs.plugins.ideaExt)
|
id("org.jetbrains.gradle.plugin.idea-ext")
|
||||||
|
|
||||||
id("cc-tweaked.illuaminate")
|
id("cc-tweaked.illuaminate")
|
||||||
id("cc-tweaked.gametest")
|
id("cc-tweaked.gametest")
|
||||||
@ -28,17 +28,20 @@ val isStable = true
|
|||||||
val modVersion: String by extra
|
val modVersion: String by extra
|
||||||
val mcVersion: String by extra
|
val mcVersion: String by extra
|
||||||
|
|
||||||
val allProjects = listOf(":core-api", ":core").map { evaluationDependsOn(it) }
|
val allProjects = listOf(":core-api", ":core", ":forge-api").map { evaluationDependsOn(it) }
|
||||||
cct {
|
cct {
|
||||||
allProjects.forEach { externalSources(it) }
|
allProjects.forEach { externalSources(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withJavadocJar()
|
|
||||||
registerFeature("extraMods") { usingSourceSet(sourceSets.main.get()) }
|
registerFeature("extraMods") { usingSourceSet(sourceSets.main.get()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
// ForgeGradle adds a dep on the clientClasses task, despite forge-api coming from a separate project. Register an
|
||||||
|
// empty one.
|
||||||
|
register("client")
|
||||||
|
|
||||||
main {
|
main {
|
||||||
resources.srcDir("src/generated/resources")
|
resources.srcDir("src/generated/resources")
|
||||||
}
|
}
|
||||||
@ -160,6 +163,8 @@ dependencies {
|
|||||||
"extraModsCompileOnly"(fg.deobf("maven.modrinth:oculus:1.2.5"))
|
"extraModsCompileOnly"(fg.deobf("maven.modrinth:oculus:1.2.5"))
|
||||||
|
|
||||||
implementation(project(":core"))
|
implementation(project(":core"))
|
||||||
|
implementation(commonClasses(project(":forge-api")))
|
||||||
|
implementation(clientClasses(project(":forge-api")))
|
||||||
"shade"(libs.cobalt)
|
"shade"(libs.cobalt)
|
||||||
"shade"(libs.netty.http)
|
"shade"(libs.netty.http)
|
||||||
|
|
||||||
@ -182,19 +187,6 @@ illuaminate {
|
|||||||
|
|
||||||
// Compile tasks
|
// Compile tasks
|
||||||
|
|
||||||
tasks.javadoc {
|
|
||||||
include("dan200/computercraft/api/**/*.java")
|
|
||||||
}
|
|
||||||
|
|
||||||
val apiJar by tasks.registering(Jar::class) {
|
|
||||||
archiveClassifier.set("api")
|
|
||||||
from(sourceSets.main.get().output) {
|
|
||||||
include("dan200/computercraft/api/**/*")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.assemble { dependsOn(apiJar) }
|
|
||||||
|
|
||||||
val luaJavadoc by tasks.registering(Javadoc::class) {
|
val luaJavadoc by tasks.registering(Javadoc::class) {
|
||||||
description = "Generates documentation for Java-side Lua functions."
|
description = "Generates documentation for Java-side Lua functions."
|
||||||
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
||||||
@ -344,7 +336,6 @@ tasks.publish { dependsOn(tasks.githubRelease) }
|
|||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
named("maven", MavenPublication::class) {
|
named("maven", MavenPublication::class) {
|
||||||
artifact(apiJar)
|
|
||||||
fg.component(this)
|
fg.component(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,42 @@ repositories {
|
|||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Duplicated in settings.gradle.kts
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
|
||||||
|
maven("https://maven.minecraftforge.net") {
|
||||||
|
name = "Forge"
|
||||||
|
content {
|
||||||
|
includeGroup("net.minecraftforge")
|
||||||
|
includeGroup("net.minecraftforge.gradle")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maven("https://maven.parchmentmc.org") {
|
||||||
|
name = "Librarian"
|
||||||
|
content {
|
||||||
|
includeGroupByRegex("^org\\.parchmentmc.*")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maven("https://repo.spongepowered.org/repository/maven-public/") {
|
||||||
|
name = "Sponge"
|
||||||
|
content {
|
||||||
|
includeGroup("org.spongepowered")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.errorProne.plugin)
|
implementation(libs.errorProne.plugin)
|
||||||
implementation(libs.kotlin.plugin)
|
implementation(libs.kotlin.plugin)
|
||||||
implementation(libs.spotless)
|
implementation(libs.spotless)
|
||||||
|
|
||||||
|
implementation(libs.vanillaGradle)
|
||||||
|
implementation(libs.forgeGradle)
|
||||||
|
implementation(libs.librarian)
|
||||||
}
|
}
|
||||||
|
|
||||||
gradlePlugin {
|
gradlePlugin {
|
||||||
|
35
buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts
Normal file
35
buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/** Default configuration for Forge projects. */
|
||||||
|
|
||||||
|
import cc.tweaked.gradle.CCTweakedExtension
|
||||||
|
import cc.tweaked.gradle.CCTweakedPlugin
|
||||||
|
import cc.tweaked.gradle.IdeaRunConfigurations
|
||||||
|
import cc.tweaked.gradle.MinecraftConfigurations
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("cc-tweaked.java-convention")
|
||||||
|
id("net.minecraftforge.gradle")
|
||||||
|
id("org.parchmentmc.librarian.forgegradle")
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.apply(CCTweakedPlugin::class.java)
|
||||||
|
|
||||||
|
val mcVersion: String by extra
|
||||||
|
|
||||||
|
minecraft {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
mappings("parchment", "${libs.findVersion("parchmentMc").get()}-${libs.findVersion("parchment").get()}-$mcVersion")
|
||||||
|
|
||||||
|
accessTransformer(rootProject.file("src/main/resources/META-INF/accesstransformer.cfg"))
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftConfigurations.setup(project)
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
"minecraft"("net.minecraftforge:forge:$mcVersion-${libs.findVersion("forge").get()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.configureEach {
|
||||||
|
// genIntellijRuns isn't registered until much later, so we need this silly hijinks.
|
||||||
|
if (name == "genIntellijRuns") doLast { IdeaRunConfigurations(project).patch() }
|
||||||
|
}
|
27
buildSrc/src/main/kotlin/cc-tweaked.vanilla.gradle.kts
Normal file
27
buildSrc/src/main/kotlin/cc-tweaked.vanilla.gradle.kts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/** Default configuration for non-modloader-specific Minecraft projects. */
|
||||||
|
|
||||||
|
import cc.tweaked.gradle.CCTweakedExtension
|
||||||
|
import cc.tweaked.gradle.CCTweakedPlugin
|
||||||
|
import cc.tweaked.gradle.MinecraftConfigurations
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("cc-tweaked.java-convention")
|
||||||
|
id("org.spongepowered.gradle.vanilla")
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.apply(CCTweakedPlugin::class.java)
|
||||||
|
|
||||||
|
val mcVersion: String by extra
|
||||||
|
|
||||||
|
minecraft {
|
||||||
|
version(mcVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
|
||||||
|
// Depend on error prone annotations to silence a lot of compile warnings.
|
||||||
|
compileOnlyApi(libs.findLibrary("errorProne.annotations").get())
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftConfigurations.setup(project)
|
@ -1,21 +1,31 @@
|
|||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import net.ltgt.gradle.errorprone.CheckSeverity
|
||||||
|
import net.ltgt.gradle.errorprone.errorprone
|
||||||
import org.gradle.api.NamedDomainObjectProvider
|
import org.gradle.api.NamedDomainObjectProvider
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.attributes.TestSuiteType
|
import org.gradle.api.attributes.TestSuiteType
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.provider.SetProperty
|
import org.gradle.api.provider.SetProperty
|
||||||
import org.gradle.api.reporting.ReportingExtension
|
import org.gradle.api.reporting.ReportingExtension
|
||||||
import org.gradle.api.tasks.JavaExec
|
import org.gradle.api.tasks.JavaExec
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
import org.gradle.api.tasks.SourceSetContainer
|
import org.gradle.api.tasks.SourceSetContainer
|
||||||
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
|
import org.gradle.api.tasks.javadoc.Javadoc
|
||||||
import org.gradle.configurationcache.extensions.capitalized
|
import org.gradle.configurationcache.extensions.capitalized
|
||||||
import org.gradle.kotlin.dsl.get
|
import org.gradle.kotlin.dsl.get
|
||||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
|
import org.gradle.language.jvm.tasks.ProcessResources
|
||||||
import org.gradle.testing.jacoco.plugins.JacocoCoverageReport
|
import org.gradle.testing.jacoco.plugins.JacocoCoverageReport
|
||||||
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
|
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
|
||||||
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
|
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
|
||||||
import org.gradle.testing.jacoco.tasks.JacocoReport
|
import org.gradle.testing.jacoco.tasks.JacocoReport
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import java.io.BufferedWriter
|
import java.io.BufferedWriter
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.OutputStreamWriter
|
import java.io.OutputStreamWriter
|
||||||
@ -90,6 +100,61 @@ abstract class CCTweakedExtension(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a dependency on another project such that its sources and compiles are processed with this one.
|
||||||
|
*
|
||||||
|
* This is used when importing a common library into a loader-specific one, as we want to compile sources using
|
||||||
|
* the loader-specific sources.
|
||||||
|
*/
|
||||||
|
fun inlineProject(path: String) {
|
||||||
|
val otherProject = project.evaluationDependsOn(path)
|
||||||
|
val otherJava = otherProject.extensions.getByType(JavaPluginExtension::class.java)
|
||||||
|
val main = otherJava.sourceSets.getByName("main")
|
||||||
|
val client = otherJava.sourceSets.getByName("client")
|
||||||
|
val testMod = otherJava.sourceSets.findByName("testMod")
|
||||||
|
val testFixtures = otherJava.sourceSets.findByName("testFixtures")
|
||||||
|
|
||||||
|
// Pull in sources from the other project.
|
||||||
|
extendSourceSet(otherProject, main)
|
||||||
|
extendSourceSet(otherProject, client)
|
||||||
|
if (testMod != null) extendSourceSet(otherProject, testMod)
|
||||||
|
if (testFixtures != null) extendSourceSet(otherProject, testFixtures)
|
||||||
|
|
||||||
|
// The extra source-processing tasks should include these files too.
|
||||||
|
project.tasks.named(main.javadocTaskName, Javadoc::class.java) { source(main.allJava, client.allJava) }
|
||||||
|
project.tasks.named(main.sourcesJarTaskName, Jar::class.java) { from(main.allSource, client.allSource) }
|
||||||
|
sourceDirectories.addAll(SourceSetReference.inline(main), SourceSetReference.inline(client))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend a source set with files from another project.
|
||||||
|
*
|
||||||
|
* This actually extends the original compile tasks, as extending the source sets does not play well with IDEs.
|
||||||
|
*/
|
||||||
|
private fun extendSourceSet(otherProject: Project, sourceSet: SourceSet) {
|
||||||
|
project.tasks.named(sourceSet.compileJavaTaskName, JavaCompile::class.java) {
|
||||||
|
dependsOn(otherProject.tasks.named(sourceSet.compileJavaTaskName)) // Avoid duplicate compile errors
|
||||||
|
source(sourceSet.allJava)
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.named(sourceSet.processResourcesTaskName, ProcessResources::class.java) {
|
||||||
|
from(sourceSet.resources)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also try to depend on Kotlin if it exists
|
||||||
|
val kotlin = otherProject.extensions.findByType(KotlinProjectExtension::class.java)
|
||||||
|
if (kotlin != null) {
|
||||||
|
val compileKotlin = sourceSet.getCompileTaskName("kotlin")
|
||||||
|
project.tasks.named(compileKotlin, KotlinCompile::class.java) {
|
||||||
|
dependsOn(otherProject.tasks.named(compileKotlin))
|
||||||
|
source(kotlin.sourceSets.getByName(sourceSet.name).kotlin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're doing an IDE sync, add a fake dependency to ensure it's on the classpath.
|
||||||
|
if (isIdeSync) project.dependencies.add(sourceSet.apiConfigurationName, sourceSet.output)
|
||||||
|
}
|
||||||
|
|
||||||
fun jacoco(task: NamedDomainObjectProvider<JavaExec>) {
|
fun jacoco(task: NamedDomainObjectProvider<JavaExec>) {
|
||||||
val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
|
val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
|
||||||
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
||||||
@ -146,5 +211,8 @@ abstract class CCTweakedExtension(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val isIdeSync: Boolean
|
||||||
|
get() = java.lang.Boolean.parseBoolean(System.getProperty("idea.sync.active", "false"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,3 +18,14 @@ fun JavaExec.copyToFull(spec: JavaExec) {
|
|||||||
spec.javaLauncher.set(javaLauncher)
|
spec.javaLauncher.set(javaLauncher)
|
||||||
spec.args = args
|
spec.args = args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternative to [Nothing] with a more descriptive name. Use to enforce calling a function with named arguments:
|
||||||
|
*
|
||||||
|
* ```kotlin
|
||||||
|
* fun f(vararg unused: UseNamedArgs, arg1: Int, arg2: Int) {
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class UseNamedArgs private constructor()
|
||||||
|
@ -0,0 +1,170 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.logging.Logging
|
||||||
|
import org.w3c.dom.Attr
|
||||||
|
import org.w3c.dom.Document
|
||||||
|
import org.w3c.dom.Node
|
||||||
|
import org.xml.sax.InputSource
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
import javax.xml.transform.TransformerFactory
|
||||||
|
import javax.xml.transform.dom.DOMSource
|
||||||
|
import javax.xml.transform.stream.StreamResult
|
||||||
|
import javax.xml.xpath.XPathConstants
|
||||||
|
import javax.xml.xpath.XPathFactory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patches up run configurations from ForgeGradle and Loom.
|
||||||
|
*
|
||||||
|
* Would be good to PR some (or all) of these changes upstream at some point.
|
||||||
|
*
|
||||||
|
* @see net.fabricmc.loom.configuration.ide.idea.IdeaSyncTask
|
||||||
|
* @see net.minecraftforge.gradle.common.util.runs.IntellijRunGenerator
|
||||||
|
*/
|
||||||
|
internal class IdeaRunConfigurations(project: Project) {
|
||||||
|
private val rootProject = project.rootProject
|
||||||
|
|
||||||
|
private val documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||||
|
private val xpath = XPathFactory.newInstance().newXPath()
|
||||||
|
private val writer = TransformerFactory.newInstance().newTransformer()
|
||||||
|
|
||||||
|
private val ideaDir = rootProject.file(".idea/")
|
||||||
|
private val buildDir: Lazy<String?> = lazy {
|
||||||
|
val ideaMisc = ideaDir.resolve("misc.xml")
|
||||||
|
|
||||||
|
try {
|
||||||
|
val doc = Files.newBufferedReader(ideaMisc.toPath(), StandardCharsets.UTF_8).use {
|
||||||
|
documentBuilder.parse(InputSource(it))
|
||||||
|
}
|
||||||
|
val node =
|
||||||
|
xpath.evaluate("//component[@name=\"ProjectRootManager\"]/output", doc, XPathConstants.NODE) as Node
|
||||||
|
val attr = node.attributes.getNamedItem("url") as Attr
|
||||||
|
attr.value.removePrefix("file://")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LOGGER.error("Failed to find root directory", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun patch() = synchronized(LOCK) {
|
||||||
|
val runConfigDir = ideaDir.resolve("runConfigurations")
|
||||||
|
if (!runConfigDir.isDirectory) return
|
||||||
|
|
||||||
|
Files.list(runConfigDir.toPath()).use {
|
||||||
|
for (configuration in it) {
|
||||||
|
val filename = configuration.fileName.toString();
|
||||||
|
when {
|
||||||
|
filename.endsWith("_fabric.xml") -> patchFabric(configuration)
|
||||||
|
filename.startsWith("forge_") && filename.endsWith(".xml") -> patchForge(configuration)
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun patchFabric(path: Path) = withXml(path) {
|
||||||
|
setXml("//configuration", "folderName") { "Fabric" }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun patchForge(path: Path) = withXml(path) {
|
||||||
|
val configId = path.fileName.toString().removePrefix("forge_").removeSuffix(".xml")
|
||||||
|
val sourceSet = forgeConfigs[configId]
|
||||||
|
if (sourceSet == null) {
|
||||||
|
LOGGER.error("[{}] Cannot map run configuration to a known source set", path)
|
||||||
|
return@withXml
|
||||||
|
}
|
||||||
|
|
||||||
|
setXml("//configuration", "folderName") { "Forge" }
|
||||||
|
setXml("//configuration/module", "name") { "${rootProject.name}.forge.$sourceSet" }
|
||||||
|
|
||||||
|
if (buildDir.value == null) return@withXml
|
||||||
|
setXml("//configuration/envs/env[@name=\"MOD_CLASSES\"]", "value") { classpath ->
|
||||||
|
val classes = classpath!!.split(':')
|
||||||
|
val newClasses = mutableListOf<String>()
|
||||||
|
fun appendUnique(x: String) {
|
||||||
|
if (!newClasses.contains(x)) newClasses.add(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entry in classes) {
|
||||||
|
if (!entry.contains("/out/")) {
|
||||||
|
appendUnique(entry)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val match = CLASSPATH_ENTRY.matchEntire(entry)
|
||||||
|
if (match != null) {
|
||||||
|
val modId = match.groups["modId"]!!.value
|
||||||
|
val proj = match.groups["proj"]!!.value
|
||||||
|
var component = match.groups["component"]!!.value
|
||||||
|
if (component == "production") component = "main"
|
||||||
|
|
||||||
|
appendUnique(forgeModEntry(modId, proj, component))
|
||||||
|
} else {
|
||||||
|
LOGGER.warn("[{}] Unknown classpath entry {}", path, entry)
|
||||||
|
appendUnique(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure common code is on the classpath
|
||||||
|
for (proj in listOf("common", "common-api")) {
|
||||||
|
for (component in listOf("main", "client")) {
|
||||||
|
appendUnique(forgeModEntry("computercraft", proj, component))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newClasses.any { it.startsWith("cctest%%") }) {
|
||||||
|
appendUnique(forgeModEntry("cctest", "core", "testFixtures"))
|
||||||
|
appendUnique(forgeModEntry("cctest", "common", "testMod"))
|
||||||
|
}
|
||||||
|
|
||||||
|
newClasses.joinToString(":")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun forgeModEntry(mod: String, project: String, component: String) =
|
||||||
|
"$mod%%${buildDir.value}/production/${rootProject.name}.$project.$component"
|
||||||
|
|
||||||
|
private fun LocatedDocument.setXml(xpath: String, attribute: String, value: (String?) -> String) {
|
||||||
|
val node = this@IdeaRunConfigurations.xpath.evaluate(xpath, document, XPathConstants.NODE) as Node?
|
||||||
|
if (node == null) {
|
||||||
|
LOGGER.error("[{}] Cannot find {}", path.fileName, xpath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val attr = node.attributes.getNamedItem(attribute) as Attr? ?: document.createAttribute(attribute)
|
||||||
|
val oldValue = attr.value
|
||||||
|
attr.value = value(attr.value)
|
||||||
|
node.attributes.setNamedItem(attr)
|
||||||
|
|
||||||
|
if (oldValue != attr.value) {
|
||||||
|
LOGGER.info("[{}] Setting {}@{}:\n Old: {}\n New: {}", path.fileName, xpath, attribute, oldValue, attr.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun withXml(path: Path, run: LocatedDocument.() -> Unit) {
|
||||||
|
val doc = Files.newBufferedReader(path).use { documentBuilder.parse(InputSource(it)) }
|
||||||
|
run(LocatedDocument(path, doc))
|
||||||
|
Files.newBufferedWriter(path).use { writer.transform(DOMSource(doc), StreamResult(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LocatedDocument(val path: Path, val document: Document)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOGGER = Logging.getLogger(IdeaRunConfigurations::class.java)
|
||||||
|
private val LOCK = Any()
|
||||||
|
|
||||||
|
private val CLASSPATH_ENTRY =
|
||||||
|
Regex("(?<modId>[a-z]+)%%\\\$PROJECT_DIR\\\$/projects/(?<proj>[a-z-]+)/out/(?<component>\\w+)/(?<type>[a-z]+)\$")
|
||||||
|
|
||||||
|
private val forgeConfigs = mapOf(
|
||||||
|
"runClient" to "client",
|
||||||
|
"runData" to "main",
|
||||||
|
"runGameTestServer" to "testMod",
|
||||||
|
"runServer" to "main",
|
||||||
|
"runTestClient" to "testMod",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,189 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.artifacts.ModuleDependency
|
||||||
|
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||||
|
import org.gradle.api.attributes.Bundling
|
||||||
|
import org.gradle.api.attributes.Category
|
||||||
|
import org.gradle.api.attributes.LibraryElements
|
||||||
|
import org.gradle.api.attributes.Usage
|
||||||
|
import org.gradle.api.attributes.java.TargetJvmVersion
|
||||||
|
import org.gradle.api.capabilities.Capability
|
||||||
|
import org.gradle.api.plugins.BasePlugin
|
||||||
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
|
import org.gradle.api.tasks.javadoc.Javadoc
|
||||||
|
import org.gradle.kotlin.dsl.get
|
||||||
|
import org.gradle.kotlin.dsl.named
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This sets up a separate client-only source set, and extends that and the main/common source set with additional
|
||||||
|
* metadata, to make it easier to consume jars downstream.
|
||||||
|
*/
|
||||||
|
class MinecraftConfigurations private constructor(private val project: Project) {
|
||||||
|
private val java = project.extensions.getByType(JavaPluginExtension::class.java)
|
||||||
|
private val sourceSets = java.sourceSets
|
||||||
|
private val configurations = project.configurations
|
||||||
|
private val objects = project.objects
|
||||||
|
|
||||||
|
private val main = sourceSets[SourceSet.MAIN_SOURCE_SET_NAME]
|
||||||
|
private val test = sourceSets[SourceSet.TEST_SOURCE_SET_NAME]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the initial setup of our configurations.
|
||||||
|
*/
|
||||||
|
private fun setup() {
|
||||||
|
// Define a client source set.
|
||||||
|
val client = sourceSets.maybeCreate("client")
|
||||||
|
|
||||||
|
// Ensure the client classpaths behave the same as the main ones.
|
||||||
|
configurations.named(client.compileClasspathConfigurationName) {
|
||||||
|
shouldResolveConsistentlyWith(configurations[main.compileClasspathConfigurationName])
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.named(client.runtimeClasspathConfigurationName) {
|
||||||
|
shouldResolveConsistentlyWith(configurations[main.runtimeClasspathConfigurationName])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up an API configuration for clients (to ensure it's consistent with the main source set).
|
||||||
|
val clientApi = configurations.maybeCreate(client.apiConfigurationName).apply {
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
}
|
||||||
|
configurations.named(client.implementationConfigurationName) { extendsFrom(clientApi) }
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now add outgoing variants for the main and common source sets that we can consume downstream. This is possibly
|
||||||
|
the worst way to do things, but unfortunately the alternatives don't actually work very well:
|
||||||
|
|
||||||
|
- Just using source set outputs: This means dependencies don't propagate, which means when :fabric depends
|
||||||
|
on :fabric-api, we don't inherit the fake :common-api in IDEA.
|
||||||
|
|
||||||
|
- Having separate common/main jars: Nice in principle, but unfortunately Forge needs a separate deobf jar
|
||||||
|
task (as the original jar is obfuscated), and IDEA is not able to map its output back to a source set.
|
||||||
|
|
||||||
|
This works for now, but is incredibly brittle. It's part of the reason we can't use testFixtures inside our
|
||||||
|
MC projects, as that adds a project(self) -> test dependency, which would pull in the jar instead.
|
||||||
|
|
||||||
|
Note we register a fake client jar here. It's not actually needed, but is there to make sure IDEA has
|
||||||
|
a way to tell that client classes are needed at runtime.
|
||||||
|
|
||||||
|
I'm so sorry, deeply aware how cursed this is.
|
||||||
|
*/
|
||||||
|
setupOutgoing(main, "CommonOnly")
|
||||||
|
project.tasks.register(client.jarTaskName, Jar::class.java) {
|
||||||
|
description = "An empty jar standing in for the client classes."
|
||||||
|
group = BasePlugin.BUILD_GROUP
|
||||||
|
archiveClassifier.set("client")
|
||||||
|
}
|
||||||
|
setupOutgoing(client)
|
||||||
|
|
||||||
|
// Reset the client classpath (Loom configures it slightly differently to this) and add a main -> client
|
||||||
|
// dependency. Here we /can/ use source set outputs as we add transitive deps by patching the classpath. Nasty,
|
||||||
|
// but avoids accidentally pulling in Forge's obfuscated jar.
|
||||||
|
client.compileClasspath = client.compileClasspath + main.compileClasspath
|
||||||
|
client.runtimeClasspath = client.runtimeClasspath + main.runtimeClasspath
|
||||||
|
project.dependencies.add(client.apiConfigurationName, main.output)
|
||||||
|
|
||||||
|
// Also add client classes to the test classpath. We do the same nasty tricks as needed for main -> client.
|
||||||
|
test.compileClasspath += client.compileClasspath
|
||||||
|
test.runtimeClasspath += client.runtimeClasspath
|
||||||
|
project.dependencies.add(test.implementationConfigurationName, client.output)
|
||||||
|
|
||||||
|
// Configure some tasks to include our additional files.
|
||||||
|
project.tasks.named("javadoc", Javadoc::class.java) {
|
||||||
|
source += client.allJava
|
||||||
|
classpath = main.compileClasspath + main.output + client.compileClasspath + client.output
|
||||||
|
}
|
||||||
|
// This are already done by Fabric, but we need it for Forge and vanilla. It shouldn't conflict at all.
|
||||||
|
project.tasks.named("jar", Jar::class.java) { from(client.output) }
|
||||||
|
project.tasks.named("sourcesJar", Jar::class.java) { from(client.allSource) }
|
||||||
|
|
||||||
|
project.extensions.configure(CCTweakedExtension::class.java) {
|
||||||
|
sourceDirectories.add(SourceSetReference.internal(client))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupOutgoing(sourceSet: SourceSet, suffix: String = "") {
|
||||||
|
setupOutgoing("${sourceSet.apiElementsConfigurationName}$suffix", sourceSet, objects.named(Usage.JAVA_API)) {
|
||||||
|
description = "API elements for ${sourceSet.name}"
|
||||||
|
extendsFrom(configurations[sourceSet.apiConfigurationName])
|
||||||
|
}
|
||||||
|
|
||||||
|
setupOutgoing("${sourceSet.runtimeElementsConfigurationName}$suffix", sourceSet, objects.named(Usage.JAVA_RUNTIME)) {
|
||||||
|
description = "Runtime elements for ${sourceSet.name}"
|
||||||
|
extendsFrom(configurations[sourceSet.implementationConfigurationName], configurations[sourceSet.runtimeOnlyConfigurationName])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up an outgoing configuration for a specific source set. We set an additional "main" or "client" capability
|
||||||
|
* (depending on the source set name) which allows downstream projects to consume them separately (see
|
||||||
|
* [DependencyHandler.commonClasses] and [DependencyHandler.clientClasses]).
|
||||||
|
*/
|
||||||
|
private fun setupOutgoing(name: String, sourceSet: SourceSet, usage: Usage, configure: Configuration.() -> Unit) {
|
||||||
|
configurations.register(name) {
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = true
|
||||||
|
isCanBeResolved = false
|
||||||
|
|
||||||
|
configure(this)
|
||||||
|
|
||||||
|
attributes {
|
||||||
|
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
|
||||||
|
attribute(Usage.USAGE_ATTRIBUTE, usage)
|
||||||
|
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
|
||||||
|
attributeProvider(
|
||||||
|
TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE,
|
||||||
|
java.toolchain.languageVersion.map { it.asInt() },
|
||||||
|
)
|
||||||
|
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||||
|
}
|
||||||
|
|
||||||
|
outgoing {
|
||||||
|
capability(BasicOutgoingCapability(project, sourceSet.name))
|
||||||
|
|
||||||
|
// We have two outgoing variants here: the original jar and the classes.
|
||||||
|
artifact(project.tasks.named(sourceSet.jarTaskName))
|
||||||
|
|
||||||
|
variants.create("classes") {
|
||||||
|
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.CLASSES))
|
||||||
|
sourceSet.output.classesDirs.forEach { artifact(it) { builtBy(sourceSet.output) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun setup(project: Project) {
|
||||||
|
MinecraftConfigurations(project).setup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BasicIncomingCapability(private val module: ModuleDependency, private val name: String) : Capability {
|
||||||
|
override fun getGroup(): String = module.group!!
|
||||||
|
override fun getName(): String = "${module.name}-$name"
|
||||||
|
override fun getVersion(): String? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BasicOutgoingCapability(private val project: Project, private val name: String) : Capability {
|
||||||
|
override fun getGroup(): String = project.group.toString()
|
||||||
|
override fun getName(): String = "${project.name}-$name"
|
||||||
|
override fun getVersion(): String = project.version.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DependencyHandler.clientClasses(notation: Any): ModuleDependency {
|
||||||
|
val dep = create(notation) as ModuleDependency
|
||||||
|
dep.capabilities { requireCapability(BasicIncomingCapability(dep, "client")) }
|
||||||
|
return dep
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DependencyHandler.commonClasses(notation: Any): ModuleDependency {
|
||||||
|
val dep = create(notation) as ModuleDependency
|
||||||
|
dep.capabilities { requireCapability(BasicIncomingCapability(dep, "main")) }
|
||||||
|
return dep
|
||||||
|
}
|
@ -43,6 +43,7 @@ nullAway = "0.9.9"
|
|||||||
shadow = "7.1.2"
|
shadow = "7.1.2"
|
||||||
spotless = "6.8.0"
|
spotless = "6.8.0"
|
||||||
taskTree = "2.1.0"
|
taskTree = "2.1.0"
|
||||||
|
vanillaGradle = "0.2.1-SNAPSHOT"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
|
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
|
||||||
@ -74,9 +75,12 @@ errorProne-api = { module = "com.google.errorprone:error_prone_check_api", versi
|
|||||||
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
|
errorProne-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorProne-core" }
|
||||||
errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne-plugin" }
|
errorProne-plugin = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorProne-plugin" }
|
||||||
errorProne-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
|
errorProne-testHelpers = { module = "com.google.errorprone:error_prone_test_helpers", version.ref = "errorProne-core" }
|
||||||
|
forgeGradle = { module = "net.minecraftforge.gradle:ForgeGradle", version.ref = "forgeGradle" }
|
||||||
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
|
librarian = { module = "org.parchmentmc:librarian", version.ref = "librarian" }
|
||||||
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
nullAway = { module = "com.uber.nullaway:nullaway", version.ref = "nullAway" }
|
||||||
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
||||||
|
vanillaGradle = { module = "org.spongepowered:vanillagradle", version.ref = "vanillaGradle" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
curseForgeGradle = { id = "net.darkhax.curseforgegradle", version.ref = "curseForgeGradle" }
|
curseForgeGradle = { id = "net.darkhax.curseforgegradle", version.ref = "curseForgeGradle" }
|
||||||
|
18
projects/common-api/build.gradle.kts
Normal file
18
projects/common-api/build.gradle.kts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
plugins {
|
||||||
|
id("cc-tweaked.java-convention")
|
||||||
|
id("cc-tweaked.publishing")
|
||||||
|
id("cc-tweaked.vanilla")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":core-api"))
|
||||||
|
compileOnly(project(":forge-stubs"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.javadoc {
|
||||||
|
include("dan200/computercraft/api/**/*.java")
|
||||||
|
}
|
@ -9,7 +9,6 @@ import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
@ -20,7 +19,8 @@ public final class ComputerCraftAPIClient {
|
|||||||
/**
|
/**
|
||||||
* Register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
* Register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
||||||
* <p>
|
* <p>
|
||||||
* This may be called at any point after registry creation, though it is recommended to call it within {@link FMLClientSetupEvent}.
|
* This may be called at any point after registry creation, though it is recommended to call it within your client
|
||||||
|
* setup step.
|
||||||
*
|
*
|
||||||
* @param serialiser The turtle upgrade serialiser.
|
* @param serialiser The turtle upgrade serialiser.
|
||||||
* @param modeller The upgrade modeller.
|
* @param modeller The upgrade modeller.
|
@ -6,6 +6,7 @@
|
|||||||
package dan200.computercraft.api.client;
|
package dan200.computercraft.api.client;
|
||||||
|
|
||||||
import com.mojang.math.Transformation;
|
import com.mojang.math.Transformation;
|
||||||
|
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
@ -39,7 +40,7 @@ public final class TransformedModel {
|
|||||||
|
|
||||||
public static TransformedModel of(@Nonnull ResourceLocation location) {
|
public static TransformedModel of(@Nonnull ResourceLocation location) {
|
||||||
var modelManager = Minecraft.getInstance().getModelManager();
|
var modelManager = Minecraft.getInstance().getModelManager();
|
||||||
return new TransformedModel(modelManager.getModel(location));
|
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransformedModel of(@Nonnull ItemStack item, @Nonnull Transformation transform) {
|
public static TransformedModel of(@Nonnull ItemStack item, @Nonnull Transformation transform) {
|
@ -11,17 +11,22 @@ import dan200.computercraft.api.client.TransformedModel;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
class TurtleUpgradeModellers {
|
class TurtleUpgradeModellers {
|
||||||
private static final Transformation leftTransform = getMatrixFor(-0.40625f);
|
private static final Transformation leftTransform = getMatrixFor(-0.40625f);
|
||||||
private static final Transformation rightTransform = getMatrixFor(0.40625f);
|
private static final Transformation rightTransform = getMatrixFor(0.40625f);
|
||||||
|
|
||||||
private static Transformation getMatrixFor(float offset) {
|
private static Transformation getMatrixFor(float offset) {
|
||||||
return new Transformation(new Matrix4f(new float[]{
|
var matrix = new Matrix4f();
|
||||||
|
matrix.load(FloatBuffer.wrap(new float[]{
|
||||||
0.0f, 0.0f, -1.0f, 1.0f + offset,
|
0.0f, 0.0f, -1.0f, 1.0f + offset,
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
0.0f, -1.0f, 0.0f, 1.0f,
|
0.0f, -1.0f, 0.0f, 1.0f,
|
||||||
0.0f, 0.0f, 0.0f, 1.0f,
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
}));
|
}));
|
||||||
|
matrix.transpose();
|
||||||
|
return new Transformation(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final TurtleUpgradeModeller<ITurtleUpgrade> FLAT_ITEM = (upgrade, turtle, side) ->
|
static final TurtleUpgradeModeller<ITurtleUpgrade> FLAT_ITEM = (upgrade, turtle, side) ->
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 dan200.computercraft.impl.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.impl.Services;
|
||||||
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public interface ClientPlatformHelper {
|
||||||
|
/**
|
||||||
|
* Equivalent to {@link ModelManager#getModel(ModelResourceLocation)} but for arbitrary {@link ResourceLocation}s.
|
||||||
|
*
|
||||||
|
* @param manager The model manager.
|
||||||
|
* @param location The model location.
|
||||||
|
* @return The baked model.
|
||||||
|
*/
|
||||||
|
BakedModel getModel(ModelManager manager, ResourceLocation location);
|
||||||
|
|
||||||
|
static ClientPlatformHelper get() {
|
||||||
|
var instance = Instance.INSTANCE;
|
||||||
|
return instance == null ? Services.raise(ClientPlatformHelper.class, Instance.ERROR) : instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Instance {
|
||||||
|
static final @Nullable ClientPlatformHelper INSTANCE;
|
||||||
|
static final @Nullable Throwable ERROR;
|
||||||
|
|
||||||
|
static {
|
||||||
|
var helper = Services.tryLoad(ClientPlatformHelper.class);
|
||||||
|
INSTANCE = helper.instance();
|
||||||
|
ERROR = helper.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Instance() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,7 +30,6 @@ import net.minecraft.world.level.BlockGetter;
|
|||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
import net.minecraftforge.fluids.FluidStack;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -118,7 +117,7 @@ public final class ComputerCraftAPI {
|
|||||||
* @param provider The peripheral provider to register.
|
* @param provider The peripheral provider to register.
|
||||||
* @see IPeripheral
|
* @see IPeripheral
|
||||||
* @see IPeripheralProvider
|
* @see IPeripheralProvider
|
||||||
* @deprecated Use {@link ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)} instead.
|
* @deprecated Use {@code dan200.computercraft.api.ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
public static void registerPeripheralProvider(@Nonnull IPeripheralProvider provider) {
|
public static void registerPeripheralProvider(@Nonnull IPeripheralProvider provider) {
|
||||||
@ -140,7 +139,7 @@ public final class ComputerCraftAPI {
|
|||||||
*
|
*
|
||||||
* @param capability The capability to register.
|
* @param capability The capability to register.
|
||||||
* @see GenericSource
|
* @see GenericSource
|
||||||
* @deprecated Use {@link ForgeComputerCraftAPI} instead.
|
* @deprecated Use {@code dan200.computercraft.api.ForgeComputerCraftAPI} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
public static void registerGenericCapability(@Nonnull Capability<?> capability) {
|
public static void registerGenericCapability(@Nonnull Capability<?> capability) {
|
||||||
@ -199,7 +198,7 @@ public final class ComputerCraftAPI {
|
|||||||
* such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}.
|
* such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}.
|
||||||
*
|
*
|
||||||
* @param type The type of object that this provider can provide details for. Should be {@link BlockReference},
|
* @param type The type of object that this provider can provide details for. Should be {@link BlockReference},
|
||||||
* {@link FluidStack} or {@link ItemStack}.
|
* {@code net.minecraftforge.fluids.FluidStack} or {@link ItemStack}.
|
||||||
* @param provider The detail provider to register.
|
* @param provider The detail provider to register.
|
||||||
* @param <T> The type of object that this provider can provide details for.
|
* @param <T> The type of object that this provider can provide details for.
|
||||||
* @deprecated Use {@link DetailRegistry#addProvider(IDetailProvider)} to register your provider.
|
* @deprecated Use {@link DetailRegistry#addProvider(IDetailProvider)} to register your provider.
|
||||||
@ -229,7 +228,7 @@ public final class ComputerCraftAPI {
|
|||||||
* @param side The side to extract the network element from
|
* @param side The side to extract the network element from
|
||||||
* @return The element's node
|
* @return The element's node
|
||||||
* @see IWiredElement#getNode()
|
* @see IWiredElement#getNode()
|
||||||
* @deprecated Use {@link ForgeComputerCraftAPI#getWiredElementAt(BlockGetter, BlockPos, Direction)}
|
* @deprecated Use {@code dan200.computercraft.api.ForgeComputerCraftAPI#getWiredElementAt(BlockGetter, BlockPos, Direction)}
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
@ -5,10 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.api;
|
package dan200.computercraft.api;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.BlockTags;
|
|
||||||
import net.minecraft.tags.ItemTags;
|
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
@ -24,7 +22,7 @@ public class ComputerCraftTags {
|
|||||||
public static final TagKey<Item> MONITOR = make("monitor");
|
public static final TagKey<Item> MONITOR = make("monitor");
|
||||||
|
|
||||||
private static TagKey<Item> make(String name) {
|
private static TagKey<Item> make(String name) {
|
||||||
return ItemTags.create(new ResourceLocation(ComputerCraft.MOD_ID, name));
|
return TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +53,7 @@ public class ComputerCraftTags {
|
|||||||
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable");
|
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable");
|
||||||
|
|
||||||
private static TagKey<Block> make(String name) {
|
private static TagKey<Block> make(String name) {
|
||||||
return BlockTags.create(new ResourceLocation(ComputerCraft.MOD_ID, name));
|
return TagKey.create(Registry.BLOCK_REGISTRY, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.api.peripheral;
|
package dan200.computercraft.api.peripheral;
|
||||||
|
|
||||||
import dan200.computercraft.api.ForgeComputerCraftAPI;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
@ -19,11 +18,14 @@ import javax.annotation.Nonnull;
|
|||||||
* <p>
|
* <p>
|
||||||
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively expose the {@link IPeripheral}
|
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively expose the {@link IPeripheral}
|
||||||
* capability.
|
* capability.
|
||||||
*
|
* <p>
|
||||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
|
* {@code dan200.computercraft.api.ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)} should be used
|
||||||
|
* to register a peripheral provider.
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface IPeripheralProvider {
|
public interface IPeripheralProvider {
|
||||||
|
// TODO(1.19.3): Move to Forge and fix link above.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce an peripheral implementation from a block location.
|
* Produce an peripheral implementation from a block location.
|
||||||
*
|
*
|
||||||
@ -31,7 +33,6 @@ public interface IPeripheralProvider {
|
|||||||
* @param pos The position the block is at.
|
* @param pos The position the block is at.
|
||||||
* @param side The side to get the peripheral from.
|
* @param side The side to get the peripheral from.
|
||||||
* @return A peripheral, or {@link LazyOptional#empty()} if there is not a peripheral here you'd like to handle.
|
* @return A peripheral, or {@link LazyOptional#empty()} if there is not a peripheral here you'd like to handle.
|
||||||
* @see ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
|
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
LazyOptional<IPeripheral> getPeripheral(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
LazyOptional<IPeripheral> getPeripheral(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
@ -7,7 +7,6 @@ package dan200.computercraft.api.pocket;
|
|||||||
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||||
import net.minecraft.data.DataGenerator;
|
import net.minecraft.data.DataGenerator;
|
||||||
import net.minecraftforge.data.event.GatherDataEvent;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -18,7 +17,6 @@ import java.util.function.Consumer;
|
|||||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||||
*
|
*
|
||||||
* @see GatherDataEvent To register your data provider
|
|
||||||
* @see PocketUpgradeSerialiser
|
* @see PocketUpgradeSerialiser
|
||||||
*/
|
*/
|
||||||
public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPocketUpgrade, PocketUpgradeSerialiser<?>> {
|
public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPocketUpgrade, PocketUpgradeSerialiser<?>> {
|
@ -5,17 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem;
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
import dan200.computercraft.internal.upgrades.SimpleSerialiser;
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
||||||
import net.minecraftforge.registries.DeferredRegister;
|
|
||||||
import net.minecraftforge.registries.IForgeRegistry;
|
import net.minecraftforge.registries.IForgeRegistry;
|
||||||
import net.minecraftforge.registries.RegistryManager;
|
import net.minecraftforge.registries.RegistryManager;
|
||||||
|
|
||||||
@ -36,11 +35,8 @@ import java.util.function.Function;
|
|||||||
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T> {
|
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T> {
|
||||||
/**
|
/**
|
||||||
* The ID for the associated registry.
|
* The ID for the associated registry.
|
||||||
* <p>
|
|
||||||
* This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and
|
|
||||||
* {@link RegistryManager#getRegistry(ResourceKey)}.
|
|
||||||
*/
|
*/
|
||||||
ResourceKey<Registry<PocketUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraft.MOD_ID, "pocket_upgrade_serialiser"));
|
ResourceKey<Registry<PocketUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade_serialiser"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated registry.
|
* The associated registry.
|
@ -8,8 +8,6 @@ package dan200.computercraft.api.turtle;
|
|||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraftforge.event.entity.player.AttackEntityEvent;
|
|
||||||
import net.minecraftforge.event.level.BlockEvent;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -58,8 +56,8 @@ public interface ITurtleUpgrade extends IUpgradeBase {
|
|||||||
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
|
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
|
||||||
* by the turtle, and the tool is required to do some work.
|
* by the turtle, and the tool is required to do some work.
|
||||||
* <p>
|
* <p>
|
||||||
* Conforming implementations should fire {@link BlockEvent.BreakEvent} for digging {@link AttackEntityEvent}
|
* Conforming implementations should fire loader-specific events when using the tool, for instance Forge's
|
||||||
* for attacking.
|
* {@code AttackEntityEvent}.
|
||||||
*
|
*
|
||||||
* @param turtle Access to the turtle that the tool resides on.
|
* @param turtle Access to the turtle that the tool resides on.
|
||||||
* @param side Which side of the turtle (left or right) the tool resides on.
|
* @param side Which side of the turtle (left or right) the tool resides on.
|
@ -8,14 +8,14 @@ package dan200.computercraft.api.turtle;
|
|||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.ComputerCraftTags;
|
import dan200.computercraft.api.ComputerCraftTags;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||||
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.data.DataGenerator;
|
import net.minecraft.data.DataGenerator;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraftforge.data.event.GatherDataEvent;
|
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -26,7 +26,6 @@ import java.util.function.Consumer;
|
|||||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||||
*
|
*
|
||||||
* @see GatherDataEvent To register your data provider
|
|
||||||
* @see TurtleUpgradeSerialiser
|
* @see TurtleUpgradeSerialiser
|
||||||
*/
|
*/
|
||||||
public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITurtleUpgrade, TurtleUpgradeSerialiser<?>> {
|
public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITurtleUpgrade, TurtleUpgradeSerialiser<?>> {
|
||||||
@ -128,10 +127,10 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
|||||||
*/
|
*/
|
||||||
public void add(@Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> add) {
|
public void add(@Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> add) {
|
||||||
add.accept(new Upgrade<>(id, serialiser, s -> {
|
add.accept(new Upgrade<>(id, serialiser, s -> {
|
||||||
s.addProperty("item", ForgeRegistries.ITEMS.getKey(toolItem).toString());
|
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registry.ITEM_REGISTRY, toolItem).toString());
|
||||||
if (adjective != null) s.addProperty("adjective", adjective);
|
if (adjective != null) s.addProperty("adjective", adjective);
|
||||||
if (craftingItem != null) {
|
if (craftingItem != null) {
|
||||||
s.addProperty("craftItem", ForgeRegistries.ITEMS.getKey(craftingItem).toString());
|
s.addProperty("craftItem", PlatformHelper.get().getRegistryKey(Registry.ITEM_REGISTRY, craftingItem).toString());
|
||||||
}
|
}
|
||||||
if (damageMultiplier != null) s.addProperty("damageMultiplier", damageMultiplier);
|
if (damageMultiplier != null) s.addProperty("damageMultiplier", damageMultiplier);
|
||||||
if (breakable != null) s.addProperty("breakable", breakable.location().toString());
|
if (breakable != null) s.addProperty("breakable", breakable.location().toString());
|
@ -5,20 +5,17 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.api.turtle;
|
package dan200.computercraft.api.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
|
||||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
|
||||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem;
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
import dan200.computercraft.internal.upgrades.SimpleSerialiser;
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||||
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
||||||
import net.minecraftforge.registries.DeferredRegister;
|
|
||||||
import net.minecraftforge.registries.IForgeRegistry;
|
import net.minecraftforge.registries.IForgeRegistry;
|
||||||
import net.minecraftforge.registries.RegistryManager;
|
import net.minecraftforge.registries.RegistryManager;
|
||||||
|
|
||||||
@ -29,13 +26,12 @@ import java.util.function.Function;
|
|||||||
/**
|
/**
|
||||||
* Reads a {@link ITurtleUpgrade} from disk and reads/writes it to a network packet.
|
* Reads a {@link ITurtleUpgrade} from disk and reads/writes it to a network packet.
|
||||||
* <p>
|
* <p>
|
||||||
* These should be registered in a {@link IForgeRegistry} while the game is loading, much like {@link RecipeSerializer}s.
|
* These should be registered in a {@link Registry} while the game is loading, much like {@link RecipeSerializer}s.
|
||||||
* It is suggested you use a {@link DeferredRegister}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* If your turtle upgrade doesn't have any associated configurable parameters (like most upgrades), you can use
|
* If your turtle upgrade doesn't have any associated configurable parameters (like most upgrades), you can use
|
||||||
* {@link #simple(Function)} or {@link #simpleWithCustomItem(BiFunction)} to create a basic upgrade serialiser.
|
* {@link #simple(Function)} or {@link #simpleWithCustomItem(BiFunction)} to create a basic upgrade serialiser.
|
||||||
*
|
*
|
||||||
* <h2>Example</h2>
|
* <h2>Example (Forge)</h2>
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
|
* static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
|
||||||
*
|
*
|
||||||
@ -57,7 +53,7 @@ import java.util.function.Function;
|
|||||||
* }</pre>
|
* }</pre>
|
||||||
* <p>
|
* <p>
|
||||||
* Finally, we need to register a model for our upgrade. This is done with
|
* Finally, we need to register a model for our upgrade. This is done with
|
||||||
* {@link ComputerCraftAPIClient#registerTurtleUpgradeModeller(TurtleUpgradeSerialiser, TurtleUpgradeModeller)}:
|
* {@link dan200.computercraft.api.client.ComputerCraftAPIClient#registerTurtleUpgradeModeller}:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* // Register our model inside FMLClientSetupEvent
|
* // Register our model inside FMLClientSetupEvent
|
||||||
@ -69,16 +65,13 @@ import java.util.function.Function;
|
|||||||
* @param <T> The type of turtle upgrade this is responsible for serialising.
|
* @param <T> The type of turtle upgrade this is responsible for serialising.
|
||||||
* @see ITurtleUpgrade
|
* @see ITurtleUpgrade
|
||||||
* @see TurtleUpgradeDataProvider
|
* @see TurtleUpgradeDataProvider
|
||||||
* @see TurtleUpgradeModeller
|
* @see dan200.computercraft.api.client.turtle.TurtleUpgradeModeller
|
||||||
*/
|
*/
|
||||||
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T> {
|
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T> {
|
||||||
/**
|
/**
|
||||||
* The ID for the associated registry.
|
* The ID for the associated registry.
|
||||||
* <p>
|
|
||||||
* This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and
|
|
||||||
* {@link RegistryManager#getRegistry(ResourceKey)}.
|
|
||||||
*/
|
*/
|
||||||
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraft.MOD_ID, "turtle_upgrade_serialiser"));
|
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade_serialiser"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated registry.
|
* The associated registry.
|
@ -7,6 +7,7 @@ package dan200.computercraft.api.upgrades;
|
|||||||
|
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
@ -62,20 +63,20 @@ public interface IUpgradeBase {
|
|||||||
* <p>
|
* <p>
|
||||||
* The default check requires that any non-capability NBT is exactly the same as the
|
* The default check requires that any non-capability NBT is exactly the same as the
|
||||||
* crafting item, but this may be relaxed for your upgrade.
|
* crafting item, but this may be relaxed for your upgrade.
|
||||||
|
* <p>
|
||||||
|
* This is based on {@code net.minecraftforge.common.crafting.StrictNBTIngredient}'s check.
|
||||||
*
|
*
|
||||||
* @param stack The stack to check. This is guaranteed to be non-empty and have the same item as
|
* @param stack The stack to check. This is guaranteed to be non-empty and have the same item as
|
||||||
* {@link #getCraftingItem()}.
|
* {@link #getCraftingItem()}.
|
||||||
* @return If this stack may be used to equip this upgrade.
|
* @return If this stack may be used to equip this upgrade.
|
||||||
* @see net.minecraftforge.common.crafting.StrictNBTIngredient#test(ItemStack) For the implementation of the default
|
|
||||||
* check.
|
|
||||||
*/
|
*/
|
||||||
default boolean isItemSuitable(@Nonnull ItemStack stack) {
|
default boolean isItemSuitable(@Nonnull ItemStack stack) {
|
||||||
var crafting = getCraftingItem();
|
var crafting = getCraftingItem();
|
||||||
|
|
||||||
// A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a
|
// A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a
|
||||||
// null one.
|
// null one.
|
||||||
var shareTag = stack.getItem().getShareTag(stack);
|
var shareTag = PlatformHelper.get().getShareTag(stack);
|
||||||
var craftingShareTag = crafting.getItem().getShareTag(crafting);
|
var craftingShareTag = PlatformHelper.get().getShareTag(crafting);
|
||||||
if (shareTag == craftingShareTag) return true;
|
if (shareTag == craftingShareTag) return true;
|
||||||
if (shareTag == null) return craftingShareTag.isEmpty();
|
if (shareTag == null) return craftingShareTag.isEmpty();
|
||||||
if (craftingShareTag == null) return shareTag.isEmpty();
|
if (craftingShareTag == null) return shareTag.isEmpty();
|
@ -8,8 +8,9 @@ package dan200.computercraft.api.upgrades;
|
|||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem;
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
import dan200.computercraft.internal.upgrades.SimpleSerialiser;
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.data.CachedOutput;
|
import net.minecraft.data.CachedOutput;
|
||||||
import net.minecraft.data.DataGenerator;
|
import net.minecraft.data.DataGenerator;
|
||||||
@ -17,14 +18,15 @@ import net.minecraft.data.DataProvider;
|
|||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
|
||||||
import net.minecraftforge.registries.RegistryManager;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@ -84,7 +86,7 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Upgrade<>(id, serialiser, s ->
|
return new Upgrade<>(id, serialiser, s ->
|
||||||
s.addProperty("item", Objects.requireNonNull(ForgeRegistries.ITEMS.getKey(item), "Item is not registered").toString())
|
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registry.ITEM_REGISTRY, item).toString())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +106,6 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void run(@Nonnull CachedOutput cache) throws IOException {
|
public final void run(@Nonnull CachedOutput cache) throws IOException {
|
||||||
var registry = RegistryManager.ACTIVE.getRegistry(this.registry);
|
|
||||||
var base = generator.getOutputFolder().resolve("data");
|
var base = generator.getOutputFolder().resolve("data");
|
||||||
|
|
||||||
Set<ResourceLocation> seen = new HashSet<>();
|
Set<ResourceLocation> seen = new HashSet<>();
|
||||||
@ -113,7 +114,7 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
|
|||||||
if (!seen.add(upgrade.id())) throw new IllegalStateException("Duplicate upgrade " + upgrade.id());
|
if (!seen.add(upgrade.id())) throw new IllegalStateException("Duplicate upgrade " + upgrade.id());
|
||||||
|
|
||||||
var json = new JsonObject();
|
var json = new JsonObject();
|
||||||
json.addProperty("type", Objects.requireNonNull(registry.getKey(upgrade.serialiser()), "Serialiser has not been registered").toString());
|
json.addProperty("type", PlatformHelper.get().getRegistryKey(registry, upgrade.serialiser()).toString());
|
||||||
upgrade.serialise().accept(json);
|
upgrade.serialise().accept(json);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -141,7 +142,7 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public final R existingSerialiser(@Nonnull ResourceLocation id) {
|
public final R existingSerialiser(@Nonnull ResourceLocation id) {
|
||||||
var result = RegistryManager.ACTIVE.getRegistry(registry).getValue(id);
|
var result = PlatformHelper.get().getRegistryObject(registry, id);
|
||||||
if (result == null) throw new IllegalArgumentException("No such serialiser " + registry);
|
if (result == null) throw new IllegalArgumentException("No such serialiser " + registry);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
@ -27,7 +27,6 @@ import net.minecraft.world.level.BlockGetter;
|
|||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
import net.minecraftforge.fluids.FluidStack;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -56,10 +55,12 @@ public interface ComputerCraftAPIService {
|
|||||||
@Nullable
|
@Nullable
|
||||||
IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath);
|
IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
void registerPeripheralProvider(@Nonnull IPeripheralProvider provider);
|
void registerPeripheralProvider(@Nonnull IPeripheralProvider provider);
|
||||||
|
|
||||||
void registerGenericSource(@Nonnull GenericSource source);
|
void registerGenericSource(@Nonnull GenericSource source);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
void registerGenericCapability(@Nonnull Capability<?> capability);
|
void registerGenericCapability(@Nonnull Capability<?> capability);
|
||||||
|
|
||||||
void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider);
|
void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider);
|
||||||
@ -88,8 +89,6 @@ public interface ComputerCraftAPIService {
|
|||||||
|
|
||||||
DetailRegistry<BlockReference> getBlockInWorldDetailRegistry();
|
DetailRegistry<BlockReference> getBlockInWorldDetailRegistry();
|
||||||
|
|
||||||
DetailRegistry<FluidStack> getFluidStackDetailRegistry();
|
|
||||||
|
|
||||||
final class Instance {
|
final class Instance {
|
||||||
static final @Nullable ComputerCraftAPIService INSTANCE;
|
static final @Nullable ComputerCraftAPIService INSTANCE;
|
||||||
static final @Nullable Throwable ERROR;
|
static final @Nullable Throwable ERROR;
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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 dan200.computercraft.impl;
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction layer for Forge and Fabric. See implementations for more details.
|
||||||
|
* <p>
|
||||||
|
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public interface PlatformHelper {
|
||||||
|
/**
|
||||||
|
* Get the current {@link PlatformHelper} instance.
|
||||||
|
*
|
||||||
|
* @return The current instance.
|
||||||
|
*/
|
||||||
|
static PlatformHelper get() {
|
||||||
|
var instance = Instance.INSTANCE;
|
||||||
|
return instance == null ? Services.raise(PlatformHelper.class, Instance.ERROR) : instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the unique ID for a registered object.
|
||||||
|
*
|
||||||
|
* @param registry The registry to look up this object in.
|
||||||
|
* @param object The object to look up.
|
||||||
|
* @param <T> The type of object the registry stores.
|
||||||
|
* @return The registered object's ID.
|
||||||
|
* @throws IllegalArgumentException If the registry or object are not registered.
|
||||||
|
*/
|
||||||
|
<T> ResourceLocation getRegistryKey(ResourceKey<Registry<T>> registry, T object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up an ID in a registry, returning the registered object.
|
||||||
|
*
|
||||||
|
* @param registry The registry to look up this object in.
|
||||||
|
* @param id The ID to look up.
|
||||||
|
* @param <T> The type of object the registry stores.
|
||||||
|
* @return The resolved registry object.
|
||||||
|
* @throws IllegalArgumentException If the registry or object are not registered.
|
||||||
|
*/
|
||||||
|
<T> T getRegistryObject(ResourceKey<Registry<T>> registry, ResourceLocation id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the subset of an {@link ItemStack}'s {@linkplain ItemStack#getTag() tag} which is synced to the client.
|
||||||
|
*
|
||||||
|
* @param item The stack.
|
||||||
|
* @return The item's tag.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default CompoundTag getShareTag(ItemStack item) {
|
||||||
|
return item.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Instance {
|
||||||
|
static final @Nullable PlatformHelper INSTANCE;
|
||||||
|
static final @Nullable Throwable ERROR;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// We don't want class initialisation to fail here (as that results in confusing errors). Instead, capture
|
||||||
|
// the error and rethrow it when accessing. This should be JITted away in the common case.
|
||||||
|
var helper = Services.tryLoad(PlatformHelper.class);
|
||||||
|
INSTANCE = helper.instance();
|
||||||
|
ERROR = helper.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Instance() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
package dan200.computercraft.internal.upgrades;
|
package dan200.computercraft.impl.upgrades;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
@ -12,6 +12,7 @@ import net.minecraft.network.FriendlyByteBuf;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.GsonHelper;
|
import net.minecraft.util.GsonHelper;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
@ -23,6 +24,7 @@ import java.util.function.BiFunction;
|
|||||||
*
|
*
|
||||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||||
*/
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
public abstract class SerialiserWithCraftingItem<T extends IUpgradeBase> implements UpgradeSerialiser<T> {
|
public abstract class SerialiserWithCraftingItem<T extends IUpgradeBase> implements UpgradeSerialiser<T> {
|
||||||
private final BiFunction<ResourceLocation, ItemStack, T> factory;
|
private final BiFunction<ResourceLocation, ItemStack, T> factory;
|
||||||
|
|
@ -3,13 +3,14 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
package dan200.computercraft.internal.upgrades;
|
package dan200.computercraft.impl.upgrades;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -21,6 +22,7 @@ import java.util.function.Function;
|
|||||||
*
|
*
|
||||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||||
*/
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
public abstract class SimpleSerialiser<T extends IUpgradeBase> implements UpgradeSerialiser<T> {
|
public abstract class SimpleSerialiser<T extends IUpgradeBase> implements UpgradeSerialiser<T> {
|
||||||
private final Function<ResourceLocation, T> constructor;
|
private final Function<ResourceLocation, T> constructor;
|
||||||
|
|
18
projects/forge-api/build.gradle.kts
Normal file
18
projects/forge-api/build.gradle.kts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
plugins {
|
||||||
|
id("cc-tweaked.forge")
|
||||||
|
id("cc-tweaked.publishing")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
cct.inlineProject(":common-api")
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":core-api"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.javadoc {
|
||||||
|
include("dan200/computercraft/api/**/*.java")
|
||||||
|
}
|
@ -9,7 +9,7 @@ import dan200.computercraft.api.lua.GenericSource;
|
|||||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
import dan200.computercraft.impl.ComputerCraftAPIForgeService;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
@ -22,6 +22,8 @@ import javax.annotation.Nonnull;
|
|||||||
* The forge-specific entrypoint for ComputerCraft's API.
|
* The forge-specific entrypoint for ComputerCraft's API.
|
||||||
*/
|
*/
|
||||||
public final class ForgeComputerCraftAPI {
|
public final class ForgeComputerCraftAPI {
|
||||||
|
// TODO(1.19.3): Rename me to ComputerCraftAPIForge
|
||||||
|
|
||||||
private ForgeComputerCraftAPI() {
|
private ForgeComputerCraftAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ public final class ForgeComputerCraftAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private static ComputerCraftAPIService getInstance() {
|
private static ComputerCraftAPIForgeService getInstance() {
|
||||||
return ComputerCraftAPIService.get();
|
return ComputerCraftAPIForgeService.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.api.detail;
|
package dan200.computercraft.api.detail;
|
||||||
|
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
import dan200.computercraft.impl.ComputerCraftAPIForgeService;
|
||||||
import net.minecraftforge.fluids.FluidStack;
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,5 +15,5 @@ public class ForgeDetailRegistries {
|
|||||||
/**
|
/**
|
||||||
* Provides details for {@link FluidStack}.
|
* Provides details for {@link FluidStack}.
|
||||||
*/
|
*/
|
||||||
public static final DetailRegistry<FluidStack> FLUID_STACK = ComputerCraftAPIService.get().getFluidStackDetailRegistry();
|
public static final DetailRegistry<FluidStack> FLUID_STACK = ComputerCraftAPIForgeService.get().getFluidStackDetailRegistry();
|
||||||
}
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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 dan200.computercraft.impl;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.ForgeComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.detail.DetailRegistry;
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Forge-specific version of {@link ComputerCraftAPIService}.
|
||||||
|
* <p>
|
||||||
|
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||||
|
*
|
||||||
|
* @see ForgeComputerCraftAPI
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public interface ComputerCraftAPIForgeService extends ComputerCraftAPIService {
|
||||||
|
static ComputerCraftAPIForgeService get() {
|
||||||
|
return (ComputerCraftAPIForgeService) ComputerCraftAPIService.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void registerPeripheralProvider(IPeripheralProvider provider);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void registerGenericCapability(Capability<?> capability);
|
||||||
|
|
||||||
|
DetailRegistry<FluidStack> getFluidStackDetailRegistry();
|
||||||
|
}
|
8
projects/forge-stubs/build.gradle.kts
Normal file
8
projects/forge-stubs/build.gradle.kts
Normal 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
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 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.minecraftforge.common.capabilities;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public class Capability<T> {
|
||||||
|
private Capability() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* 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.minecraftforge.common.util;
|
||||||
|
|
||||||
|
public final class LazyOptional<T> {
|
||||||
|
private LazyOptional() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> LazyOptional<T> empty() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* 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.minecraftforge.items;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public interface IItemHandlerModifiable {
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* 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.minecraftforge.registries;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public interface IForgeRegistry<T> {
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* 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.minecraftforge.registries;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public class RegistryManager {
|
||||||
|
public static final RegistryManager ACTIVE = new RegistryManager();
|
||||||
|
|
||||||
|
private RegistryManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> IForgeRegistry<T> getRegistry(Object object) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
@ -16,9 +16,14 @@ pluginManagement {
|
|||||||
val mcVersion: String by settings
|
val mcVersion: String by settings
|
||||||
rootProject.name = "cc-tweaked-$mcVersion"
|
rootProject.name = "cc-tweaked-$mcVersion"
|
||||||
|
|
||||||
include(":mc-stubs")
|
|
||||||
include(":core-api")
|
include(":core-api")
|
||||||
include(":core")
|
include(":core")
|
||||||
|
|
||||||
|
include(":mc-stubs")
|
||||||
|
include(":forge-stubs")
|
||||||
|
include(":common-api")
|
||||||
|
include(":forge-api")
|
||||||
|
|
||||||
include(":web")
|
include(":web")
|
||||||
|
|
||||||
for (project in rootProject.children) {
|
for (project in rootProject.children) {
|
||||||
|
@ -23,6 +23,7 @@ import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
|||||||
import dan200.computercraft.core.apis.ApiFactories;
|
import dan200.computercraft.core.apis.ApiFactories;
|
||||||
import dan200.computercraft.core.asm.GenericMethod;
|
import dan200.computercraft.core.asm.GenericMethod;
|
||||||
import dan200.computercraft.core.filesystem.FileMount;
|
import dan200.computercraft.core.filesystem.FileMount;
|
||||||
|
import dan200.computercraft.impl.ComputerCraftAPIForgeService;
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
import dan200.computercraft.impl.TurtleRefuelHandlers;
|
import dan200.computercraft.impl.TurtleRefuelHandlers;
|
||||||
import dan200.computercraft.impl.detail.DetailRegistryImpl;
|
import dan200.computercraft.impl.detail.DetailRegistryImpl;
|
||||||
@ -58,7 +59,7 @@ import java.io.InputStream;
|
|||||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
|
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
|
||||||
|
|
||||||
@AutoService(ComputerCraftAPIService.class)
|
@AutoService(ComputerCraftAPIService.class)
|
||||||
public final class ComputerCraftAPIImpl implements ComputerCraftAPIService {
|
public final class ComputerCraftAPIImpl implements ComputerCraftAPIForgeService {
|
||||||
private final DetailRegistry<ItemStack> itemStackDetails = new DetailRegistryImpl<>(ItemData::fillBasic);
|
private final DetailRegistry<ItemStack> itemStackDetails = new DetailRegistryImpl<>(ItemData::fillBasic);
|
||||||
private final DetailRegistry<BlockReference> blockDetails = new DetailRegistryImpl<>(BlockData::fillBasic);
|
private final DetailRegistry<BlockReference> blockDetails = new DetailRegistryImpl<>(BlockData::fillBasic);
|
||||||
private final DetailRegistry<FluidStack> fluidStackDetails = new DetailRegistryImpl<>(FluidData::fillBasic);
|
private final DetailRegistry<FluidStack> fluidStackDetails = new DetailRegistryImpl<>(FluidData::fillBasic);
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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 dan200.computercraft.client.platform;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||||
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
@AutoService(ClientPlatformHelper.class)
|
||||||
|
public class ClientPlatformHelperImpl implements ClientPlatformHelper {
|
||||||
|
@Override
|
||||||
|
public BakedModel getModel(ModelManager manager, ResourceLocation location) {
|
||||||
|
return manager.getModel(location);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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 dan200.computercraft.shared.platform;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.registries.RegistryManager;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@AutoService(PlatformHelper.class)
|
||||||
|
public class PlatformHelperImpl implements PlatformHelper {
|
||||||
|
@Override
|
||||||
|
public <T> ResourceLocation getRegistryKey(ResourceKey<Registry<T>> registry, T object) {
|
||||||
|
var key = RegistryManager.ACTIVE.getRegistry(registry).getKey(object);
|
||||||
|
if (key == null) throw new IllegalArgumentException(object + " was not registered in " + registry);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getRegistryObject(ResourceKey<Registry<T>> registry, ResourceLocation id) {
|
||||||
|
var value = RegistryManager.ACTIVE.getRegistry(registry).getValue(id);
|
||||||
|
if (value == null) throw new IllegalArgumentException(id + " was not registered in " + registry);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public CompoundTag getShareTag(ItemStack item) {
|
||||||
|
return item.getShareTag();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user