mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-11-10 20:09:58 +00:00
Update to 1.20.4
This commit is contained in:
parent
f26e443e81
commit
fc834cd97f
@ -51,9 +51,8 @@ dependencies {
|
|||||||
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-common-api:$cctVersion")
|
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-common-api:$cctVersion")
|
||||||
|
|
||||||
// Forge Gradle
|
// Forge Gradle
|
||||||
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-core-api:$cctVersion")
|
compileOnly("cc.tweaked:cc-tweaked-$mcVersion-forge-api:$cctVersion")
|
||||||
compileOnly(fg.deobf("cc.tweaked:cc-tweaked-$mcVersion-forge-api:$cctVersion"))
|
runtimeOnly("cc.tweaked:cc-tweaked-$mcVersion-forge:$cctVersion")
|
||||||
runtimeOnly(fg.deobf("cc.tweaked:cc-tweaked-$mcVersion-forge:$cctVersion"))
|
|
||||||
|
|
||||||
// Fabric Loom
|
// Fabric Loom
|
||||||
modCompileOnly("cc.tweaked:cc-tweaked-$mcVersion-fabric-api:$cctVersion")
|
modCompileOnly("cc.tweaked:cc-tweaked-$mcVersion-fabric-api:$cctVersion")
|
||||||
|
@ -14,18 +14,14 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
|
|
||||||
maven("https://maven.minecraftforge.net") {
|
maven("https://maven.neoforged.net/releases") {
|
||||||
name = "Forge"
|
name = "NeoForge"
|
||||||
content {
|
content {
|
||||||
includeGroup("net.minecraftforge")
|
includeGroup("net.minecraftforge")
|
||||||
includeGroup("net.minecraftforge.gradle")
|
includeGroup("net.neoforged")
|
||||||
}
|
includeGroup("net.neoforged.gradle")
|
||||||
}
|
includeModule("codechicken", "DiffPatch")
|
||||||
|
includeModule("net.covers1624", "Quack")
|
||||||
maven("https://maven.parchmentmc.org") {
|
|
||||||
name = "Librarian"
|
|
||||||
content {
|
|
||||||
includeGroupByRegex("^org\\.parchmentmc.*")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,10 +47,9 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.curseForgeGradle)
|
implementation(libs.curseForgeGradle)
|
||||||
implementation(libs.fabric.loom)
|
implementation(libs.fabric.loom)
|
||||||
implementation(libs.forgeGradle)
|
|
||||||
implementation(libs.ideaExt)
|
implementation(libs.ideaExt)
|
||||||
implementation(libs.librarian)
|
|
||||||
implementation(libs.minotaur)
|
implementation(libs.minotaur)
|
||||||
|
implementation(libs.neoGradle.userdev)
|
||||||
implementation(libs.vanillaExtract)
|
implementation(libs.vanillaExtract)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,8 @@ import cc.tweaked.gradle.IdeaRunConfigurations
|
|||||||
import cc.tweaked.gradle.MinecraftConfigurations
|
import cc.tweaked.gradle.MinecraftConfigurations
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("net.minecraftforge.gradle")
|
|
||||||
// We must apply java-convention after Forge, as we need the fg extension to be present.
|
|
||||||
id("cc-tweaked.java-convention")
|
id("cc-tweaked.java-convention")
|
||||||
id("org.parchmentmc.librarian.forgegradle")
|
id("net.neoforged.gradle.userdev")
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.apply(CCTweakedPlugin::class.java)
|
plugins.apply(CCTweakedPlugin::class.java)
|
||||||
@ -21,10 +19,20 @@ plugins.apply(CCTweakedPlugin::class.java)
|
|||||||
val mcVersion: String by extra
|
val mcVersion: String by extra
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
modIdentifier("computercraft")
|
||||||
mappings("parchment", "${libs.findVersion("parchmentMc").get()}-${libs.findVersion("parchment").get()}-$mcVersion")
|
}
|
||||||
|
|
||||||
accessTransformer(project(":forge").file("src/main/resources/META-INF/accesstransformer.cfg"))
|
subsystems {
|
||||||
|
parchment {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
minecraftVersion = libs.findVersion("parchmentMc").get().toString()
|
||||||
|
mappingsVersion = libs.findVersion("parchment").get().toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
implementation("net.neoforged:neoforge:${libs.findVersion("neoForge").get()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConfigurations.setup(project)
|
MinecraftConfigurations.setup(project)
|
||||||
@ -32,13 +40,3 @@ MinecraftConfigurations.setup(project)
|
|||||||
extensions.configure(CCTweakedExtension::class.java) {
|
extensions.configure(CCTweakedExtension::class.java) {
|
||||||
linters(minecraft = true, loader = "forge")
|
linters(minecraft = true, loader = "forge")
|
||||||
}
|
}
|
||||||
|
|
||||||
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() }
|
|
||||||
}
|
|
||||||
|
@ -40,21 +40,10 @@ repositories {
|
|||||||
|
|
||||||
val mainMaven = maven("https://squiddev.cc/maven") {
|
val mainMaven = maven("https://squiddev.cc/maven") {
|
||||||
name = "SquidDev"
|
name = "SquidDev"
|
||||||
content {
|
|
||||||
// Until https://github.com/SpongePowered/Mixin/pull/593 is merged
|
|
||||||
includeModule("org.spongepowered", "mixin")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exclusiveContent {
|
exclusiveContent {
|
||||||
forRepositories(mainMaven)
|
forRepositories(mainMaven)
|
||||||
|
|
||||||
// Include the ForgeGradle repository if present. This requires that ForgeGradle is already present, which we
|
|
||||||
// enforce in our Forge overlay.
|
|
||||||
val fg =
|
|
||||||
project.extensions.findByType(net.minecraftforge.gradle.userdev.DependencyManagementExtension::class.java)
|
|
||||||
if (fg != null) forRepositories(fg.repository)
|
|
||||||
|
|
||||||
filter {
|
filter {
|
||||||
includeGroup("cc.tweaked")
|
includeGroup("cc.tweaked")
|
||||||
// Things we mirror
|
// Things we mirror
|
||||||
|
@ -4,23 +4,59 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import net.minecraftforge.gradle.common.util.RunConfig
|
import net.neoforged.gradle.common.runs.run.RunImpl
|
||||||
import net.minecraftforge.gradle.common.util.runs.setRunConfigInternal
|
import net.neoforged.gradle.common.runs.tasks.RunExec
|
||||||
|
import net.neoforged.gradle.dsl.common.extensions.RunnableSourceSet
|
||||||
|
import net.neoforged.gradle.dsl.common.runs.run.Run
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.api.tasks.JavaExec
|
import org.gradle.api.tasks.JavaExec
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||||
|
import org.gradle.kotlin.dsl.assign
|
||||||
|
import org.gradle.kotlin.dsl.create
|
||||||
|
import org.gradle.kotlin.dsl.findByType
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set [JavaExec] task to run a given [RunConfig].
|
* Set [JavaExec] task to run a given [RunConfig].
|
||||||
|
*
|
||||||
|
* See also [RunExec].
|
||||||
*/
|
*/
|
||||||
fun JavaExec.setRunConfig(config: RunConfig) {
|
fun JavaExec.setRunConfig(config: Run) {
|
||||||
dependsOn("prepareRuns")
|
mainClass.set(config.mainClass)
|
||||||
setRunConfigInternal(project, this, config)
|
workingDir = config.workingDirectory.get().asFile
|
||||||
doFirst("Create working directory") { Files.createDirectories(workingDir.toPath()) }
|
argumentProviders.add { config.programArguments.get() }
|
||||||
|
jvmArgumentProviders.add { config.jvmArguments.get() }
|
||||||
|
|
||||||
|
environment(config.environmentVariables.get())
|
||||||
|
systemProperties(config.systemProperties.get())
|
||||||
|
|
||||||
|
config.modSources.get().forEach { classpath(it.runtimeClasspath) }
|
||||||
|
classpath(config.classpath)
|
||||||
|
classpath(config.dependencies.get().configuration)
|
||||||
|
|
||||||
|
(config as RunImpl).taskDependencies.forEach { dependsOn(it) }
|
||||||
|
|
||||||
javaLauncher.set(
|
javaLauncher.set(
|
||||||
project.extensions.getByType(JavaToolchainService::class.java)
|
project.extensions.getByType(JavaToolchainService::class.java)
|
||||||
.launcherFor(project.extensions.getByType(JavaPluginExtension::class.java).toolchain),
|
.launcherFor(project.extensions.getByType(JavaPluginExtension::class.java).toolchain),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
doFirst("Create working directory") { Files.createDirectories(workingDir.toPath()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new [Run.modSource] with a specific mod id.
|
||||||
|
*/
|
||||||
|
fun Run.modSourceAs(sourceSet: SourceSet, mod: String) {
|
||||||
|
// NeoGradle requires a RunnableSourceSet to be present, so we inject it into other project's source sets.
|
||||||
|
val runnable = sourceSet.extensions.findByType<RunnableSourceSet>() ?: run {
|
||||||
|
val extension = sourceSet.extensions.create<RunnableSourceSet>(RunnableSourceSet.NAME, project)
|
||||||
|
extension.modIdentifier = mod
|
||||||
|
extension.modIdentifier.finalizeValueOnRead()
|
||||||
|
extension
|
||||||
|
}
|
||||||
|
if (runnable.modIdentifier.get() != mod) throw IllegalArgumentException("Multiple mod identifiers")
|
||||||
|
|
||||||
|
modSource(sourceSet)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package cc.tweaked.gradle
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
import net.minecraftforge.gradle.common.util.RunConfig
|
|
||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
@ -65,14 +64,6 @@ abstract class ClientJavaExec : JavaExec() {
|
|||||||
setTestProperties()
|
setTestProperties()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set this task to run a given [RunConfig].
|
|
||||||
*/
|
|
||||||
fun setRunConfig(config: RunConfig) {
|
|
||||||
(this as JavaExec).setRunConfig(config)
|
|
||||||
setTestProperties() // setRunConfig may clobber some properties, ensure everything is set.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy configuration from a task with the given name.
|
* Copy configuration from a task with the given name.
|
||||||
*/
|
*/
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package net.minecraftforge.gradle.common.util.runs
|
|
||||||
|
|
||||||
import net.minecraftforge.gradle.common.util.RunConfig
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.process.CommandLineArgumentProvider
|
|
||||||
import org.gradle.process.JavaExecSpec
|
|
||||||
import java.io.File
|
|
||||||
import java.util.function.Supplier
|
|
||||||
import java.util.stream.Collectors
|
|
||||||
import java.util.stream.Stream
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up a [JavaExecSpec] to execute a [RunConfig].
|
|
||||||
*
|
|
||||||
* [MinecraftRunTask] sets up all its properties when the task is executed, rather than when configured. As such, it's
|
|
||||||
* not possible to use [cc.tweaked.gradle.copyToFull] like we do for Fabric. Instead, we set up the task manually.
|
|
||||||
*
|
|
||||||
* Unfortunately most of the functionality we need is package-private, and so we have to put our code into the package.
|
|
||||||
*/
|
|
||||||
internal fun setRunConfigInternal(project: Project, spec: JavaExecSpec, config: RunConfig) {
|
|
||||||
spec.workingDir = File(config.workingDirectory)
|
|
||||||
|
|
||||||
spec.mainClass.set(config.main)
|
|
||||||
for (source in config.allSources) spec.classpath(source.runtimeClasspath)
|
|
||||||
|
|
||||||
val originalTask = project.tasks.named(config.taskName, MinecraftRunTask::class.java)
|
|
||||||
|
|
||||||
// Add argument and JVM argument via providers, to be as lazy as possible with fetching artifacts.
|
|
||||||
val lazyTokens = RunConfigGenerator.configureTokensLazy(
|
|
||||||
project, config, RunConfigGenerator.mapModClassesToGradle(project, config),
|
|
||||||
originalTask.get().minecraftArtifacts,
|
|
||||||
originalTask.get().runtimeClasspathArtifacts,
|
|
||||||
)
|
|
||||||
spec.argumentProviders.add(
|
|
||||||
CommandLineArgumentProvider {
|
|
||||||
RunConfigGenerator.getArgsStream(config, lazyTokens, false).toList()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
spec.jvmArgumentProviders.add(
|
|
||||||
CommandLineArgumentProvider {
|
|
||||||
(if (config.isClient) config.jvmArgs + originalTask.get().additionalClientArgs.get() else config.jvmArgs).map { config.replace(lazyTokens, it) } +
|
|
||||||
config.properties.map { (k, v) -> "-D${k}=${config.replace(lazyTokens, v)}" }
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
for ((key, value) in config.environment) spec.environment(key, config.replace(lazyTokens, value))
|
|
||||||
}
|
|
@ -9,8 +9,8 @@ kotlin.stdlib.default.dependency=false
|
|||||||
kotlin.jvm.target.validation.mode=error
|
kotlin.jvm.target.validation.mode=error
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
isUnstable=false
|
isUnstable=true
|
||||||
modVersion=1.109.5
|
modVersion=1.109.5
|
||||||
|
|
||||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||||
mcVersion=1.20.1
|
mcVersion=1.20.4
|
||||||
|
@ -7,20 +7,20 @@
|
|||||||
# Minecraft
|
# Minecraft
|
||||||
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
||||||
# Remember to update corresponding versions in fabric.mod.json/mods.toml
|
# Remember to update corresponding versions in fabric.mod.json/mods.toml
|
||||||
fabric-api = "0.86.1+1.20.1"
|
fabric-api = "0.93.1+1.20.4"
|
||||||
fabric-loader = "0.14.21"
|
fabric-loader = "0.15.3"
|
||||||
forge = "47.1.0"
|
neoForge = "20.4.142-beta"
|
||||||
forgeSpi = "7.0.1"
|
neoForgeSpi = "8.0.1"
|
||||||
mixin = "0.8.5"
|
mixin = "0.8.5"
|
||||||
parchment = "2023.08.20"
|
parchment = "2023.12.31"
|
||||||
parchmentMc = "1.20.1"
|
parchmentMc = "1.20.3"
|
||||||
yarn = "1.20.1+build.10"
|
yarn = "1.20.4+build.3"
|
||||||
|
|
||||||
# Core dependencies (these versions are tied to the version Minecraft uses)
|
# Core dependencies (these versions are tied to the version Minecraft uses)
|
||||||
fastutil = "8.5.9"
|
fastutil = "8.5.12"
|
||||||
guava = "31.1-jre"
|
guava = "32.1.2-jre"
|
||||||
netty = "4.1.82.Final"
|
netty = "4.1.97.Final"
|
||||||
slf4j = "2.0.1"
|
slf4j = "2.0.7"
|
||||||
|
|
||||||
# Core dependencies (independent of Minecraft)
|
# Core dependencies (independent of Minecraft)
|
||||||
asm = "9.6"
|
asm = "9.6"
|
||||||
@ -36,14 +36,14 @@ kotlin-coroutines = "1.7.3"
|
|||||||
nightConfig = "3.6.7"
|
nightConfig = "3.6.7"
|
||||||
|
|
||||||
# Minecraft mods
|
# Minecraft mods
|
||||||
emi = "1.0.8+1.20.1"
|
emi = "1.0.30+1.20.4"
|
||||||
fabricPermissions = "0.3.20230723"
|
fabricPermissions = "0.3.20230723"
|
||||||
iris = "1.6.4+1.20"
|
iris = "1.6.14+1.20.4"
|
||||||
jei = "15.2.0.22"
|
jei = "16.0.0.28"
|
||||||
modmenu = "7.1.0"
|
modmenu = "9.0.0"
|
||||||
moreRed = "4.0.0.4"
|
moreRed = "4.0.0.4"
|
||||||
oculus = "1.2.5"
|
oculus = "1.2.5"
|
||||||
rei = "12.0.626"
|
rei = "14.0.688"
|
||||||
rubidium = "0.6.1"
|
rubidium = "0.6.1"
|
||||||
sodium = "mc1.20-0.4.10"
|
sodium = "mc1.20-0.4.10"
|
||||||
|
|
||||||
@ -55,19 +55,17 @@ junit = "5.10.1"
|
|||||||
# Build tools
|
# Build tools
|
||||||
cctJavadoc = "1.8.2"
|
cctJavadoc = "1.8.2"
|
||||||
checkstyle = "10.12.6"
|
checkstyle = "10.12.6"
|
||||||
curseForgeGradle = "1.0.14"
|
curseForgeGradle = "1.1.18"
|
||||||
errorProne-core = "2.23.0"
|
errorProne-core = "2.23.0"
|
||||||
errorProne-plugin = "3.1.0"
|
errorProne-plugin = "3.1.0"
|
||||||
fabric-loom = "1.5.7"
|
fabric-loom = "1.5.7"
|
||||||
forgeGradle = "6.0.20"
|
|
||||||
githubRelease = "2.5.2"
|
githubRelease = "2.5.2"
|
||||||
gradleVersions = "0.50.0"
|
gradleVersions = "0.50.0"
|
||||||
ideaExt = "1.1.7"
|
ideaExt = "1.1.7"
|
||||||
illuaminate = "0.1.0-44-g9ee0055"
|
illuaminate = "0.1.0-44-g9ee0055"
|
||||||
librarian = "1.+"
|
|
||||||
lwjgl = "3.3.3"
|
lwjgl = "3.3.3"
|
||||||
minotaur = "2.+"
|
minotaur = "2.8.7"
|
||||||
mixinGradle = "0.7.38"
|
neoGradle = "7.0.85"
|
||||||
nullAway = "0.9.9"
|
nullAway = "0.9.9"
|
||||||
spotless = "6.23.3"
|
spotless = "6.23.3"
|
||||||
taskTree = "2.1.1"
|
taskTree = "2.1.1"
|
||||||
@ -84,7 +82,7 @@ checkerFramework = { module = "org.checkerframework:checker-qual", version.ref =
|
|||||||
cobalt = { module = "cc.tweaked:cobalt", version.ref = "cobalt" }
|
cobalt = { module = "cc.tweaked:cobalt", version.ref = "cobalt" }
|
||||||
commonsCli = { module = "commons-cli:commons-cli", version.ref = "commonsCli" }
|
commonsCli = { module = "commons-cli:commons-cli", version.ref = "commonsCli" }
|
||||||
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
|
fastutil = { module = "it.unimi.dsi:fastutil", version.ref = "fastutil" }
|
||||||
forgeSpi = { module = "net.minecraftforge:forgespi", version.ref = "forgeSpi" }
|
neoForgeSpi = { module = "net.neoforged:neoforgespi", version.ref = "neoForgeSpi" }
|
||||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||||
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
||||||
jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" }
|
jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" }
|
||||||
@ -106,9 +104,9 @@ fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fab
|
|||||||
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
|
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
|
||||||
emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" }
|
emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" }
|
||||||
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
iris = { module = "maven.modrinth:iris", version.ref = "iris" }
|
||||||
jei-api = { module = "mezz.jei:jei-1.20.1-common-api", version.ref = "jei" }
|
jei-api = { module = "mezz.jei:jei-1.20.2-common-api", version.ref = "jei" }
|
||||||
jei-fabric = { module = "mezz.jei:jei-1.20.1-fabric", version.ref = "jei" }
|
jei-fabric = { module = "mezz.jei:jei-1.20.2-fabric", version.ref = "jei" }
|
||||||
jei-forge = { module = "mezz.jei:jei-1.20.1-forge", version.ref = "jei" }
|
jei-forge = { module = "mezz.jei:jei-1.20.2-forge", version.ref = "jei" }
|
||||||
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
|
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
|
||||||
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
|
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
|
||||||
moreRed = { module = "commoble.morered:morered-1.20.1", version.ref = "moreRed" }
|
moreRed = { module = "commoble.morered:morered-1.20.1", version.ref = "moreRed" }
|
||||||
@ -144,11 +142,10 @@ errorProne-core = { module = "com.google.errorprone:error_prone_core", version.r
|
|||||||
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" }
|
||||||
fabric-loom = { module = "net.fabricmc:fabric-loom", version.ref = "fabric-loom" }
|
fabric-loom = { module = "net.fabricmc:fabric-loom", version.ref = "fabric-loom" }
|
||||||
forgeGradle = { module = "net.minecraftforge.gradle:ForgeGradle", version.ref = "forgeGradle" }
|
|
||||||
ideaExt = { module = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext", version.ref = "ideaExt" }
|
ideaExt = { module = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext", version.ref = "ideaExt" }
|
||||||
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" }
|
|
||||||
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
minotaur = { module = "com.modrinth.minotaur:Minotaur", version.ref = "minotaur" }
|
||||||
|
neoGradle-userdev = { module = "net.neoforged.gradle:userdev", version.ref = "neoGradle" }
|
||||||
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" }
|
||||||
teavm-classlib = { module = "org.teavm:teavm-classlib", version.ref = "teavm" }
|
teavm-classlib = { module = "org.teavm:teavm-classlib", version.ref = "teavm" }
|
||||||
@ -163,12 +160,9 @@ vanillaExtract = { module = "cc.tweaked.vanilla-extract:plugin", version.ref = "
|
|||||||
yarn = { module = "net.fabricmc:yarn", version.ref = "yarn" }
|
yarn = { module = "net.fabricmc:yarn", version.ref = "yarn" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" }
|
|
||||||
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
|
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
|
||||||
gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersions" }
|
gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradleVersions" }
|
||||||
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
|
|
||||||
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
|
|
||||||
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
||||||
versionCatalogUpdate = { id = "nl.littlerobots.version-catalog-update", version.ref = "versionCatalogUpdate" }
|
versionCatalogUpdate = { id = "nl.littlerobots.version-catalog-update", version.ref = "versionCatalogUpdate" }
|
||||||
|
|
||||||
@ -179,9 +173,9 @@ kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
|||||||
# Minecraft
|
# Minecraft
|
||||||
externalMods-common = ["jei-api", "nightConfig-core", "nightConfig-toml"]
|
externalMods-common = ["jei-api", "nightConfig-core", "nightConfig-toml"]
|
||||||
externalMods-forge-compile = ["moreRed", "oculus", "jei-api"]
|
externalMods-forge-compile = ["moreRed", "oculus", "jei-api"]
|
||||||
externalMods-forge-runtime = ["jei-forge"]
|
externalMods-forge-runtime = []
|
||||||
externalMods-fabric-compile = ["fabricPermissions", "iris", "jei-api", "rei-api", "rei-builtin"]
|
externalMods-fabric-compile = ["fabricPermissions", "iris", "jei-api", "rei-api", "rei-builtin"]
|
||||||
externalMods-fabric-runtime = ["jei-fabric", "modmenu"]
|
externalMods-fabric-runtime = []
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
|
test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"]
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.api.client;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
|
||||||
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The public API for client-only code.
|
|
||||||
*
|
|
||||||
* @see dan200.computercraft.api.ComputerCraftAPI The main API
|
|
||||||
*/
|
|
||||||
public final class ComputerCraftAPIClient {
|
|
||||||
private ComputerCraftAPIClient() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
|
||||||
* <p>
|
|
||||||
* 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 modeller The upgrade modeller.
|
|
||||||
* @param <T> The type of the turtle upgrade.
|
|
||||||
* @deprecated This method can lead to confusing load behaviour on Forge. Use
|
|
||||||
* {@code dan200.computercraft.api.client.FabricComputerCraftAPIClient#registerTurtleUpgradeModeller} on Fabric, or
|
|
||||||
* {@code dan200.computercraft.api.client.turtle.RegisterTurtleModellersEvent} on Forge.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public static <T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller) {
|
|
||||||
// TODO(1.20.4): Remove this
|
|
||||||
getInstance().registerTurtleUpgradeModeller(serialiser, modeller);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ComputerCraftAPIClientService getInstance() {
|
|
||||||
return ComputerCraftAPIClientService.get();
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@
|
|||||||
package dan200.computercraft.api.client.turtle;
|
package dan200.computercraft.api.client.turtle;
|
||||||
|
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A functional interface to register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
* A functional interface to register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
||||||
@ -22,5 +22,5 @@ public interface RegisterTurtleUpgradeModeller {
|
|||||||
* @param modeller The upgrade modeller.
|
* @param modeller The upgrade modeller.
|
||||||
* @param <T> The type of the turtle upgrade.
|
* @param <T> The type of the turtle upgrade.
|
||||||
*/
|
*/
|
||||||
<T extends ITurtleUpgrade> void register(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller);
|
<T extends ITurtleUpgrade> void register(UpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import dan200.computercraft.api.client.TransformedModel;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
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 net.minecraft.client.resources.model.ModelResourceLocation;
|
|
||||||
import net.minecraft.client.resources.model.UnbakedModel;
|
import net.minecraft.client.resources.model.UnbakedModel;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@ -31,30 +30,15 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
/**
|
/**
|
||||||
* Obtain the model to be used when rendering a turtle peripheral.
|
* Obtain the model to be used when rendering a turtle peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* When the current turtle is {@literal null}, this function should be constant for a given upgrade and side.
|
* When the current turtle is {@literal null}, this function should be constant for a given upgrade, side and data.
|
||||||
*
|
*
|
||||||
* @param upgrade The upgrade that you're getting the model for.
|
* @param upgrade The upgrade that you're getting the model for.
|
||||||
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models, unless
|
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models.
|
||||||
* {@link #getModel(ITurtleUpgrade, CompoundTag, TurtleSide)} is overriden.
|
|
||||||
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
||||||
* @return The model that you wish to be used to render your upgrade.
|
|
||||||
*/
|
|
||||||
TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the model to be used when rendering a turtle peripheral.
|
|
||||||
* <p>
|
|
||||||
* This is used when rendering the turtle's item model, and so no {@link ITurtleAccess} is available.
|
|
||||||
*
|
|
||||||
* @param upgrade The upgrade that you're getting the model for.
|
|
||||||
* @param data Upgrade data instance for current turtle side.
|
* @param data Upgrade data instance for current turtle side.
|
||||||
* @param side Which side of the turtle (left or right) the upgrade resides on.
|
|
||||||
* @return The model that you wish to be used to render your upgrade.
|
* @return The model that you wish to be used to render your upgrade.
|
||||||
*/
|
*/
|
||||||
default TransformedModel getModel(T upgrade, CompoundTag data, TurtleSide side) {
|
TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, CompoundTag data);
|
||||||
return getModel(upgrade, (ITurtleAccess) null, side);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of models that this turtle modeller depends on.
|
* Get a list of models that this turtle modeller depends on.
|
||||||
@ -85,19 +69,6 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
return (TurtleUpgradeModeller<T>) TurtleUpgradeModellers.UPGRADE_ITEM;
|
return (TurtleUpgradeModeller<T>) TurtleUpgradeModellers.UPGRADE_ITEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
|
||||||
*
|
|
||||||
* @param left The model to use on the left.
|
|
||||||
* @param right The model to use on the right.
|
|
||||||
* @param <T> The type of the turtle upgrade.
|
|
||||||
* @return The constructed modeller.
|
|
||||||
*/
|
|
||||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelResourceLocation left, ModelResourceLocation right) {
|
|
||||||
// TODO(1.21.0): Remove this.
|
|
||||||
return sided((ResourceLocation) left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
||||||
*
|
*
|
||||||
@ -109,7 +80,7 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
|||||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
||||||
return new TurtleUpgradeModeller<>() {
|
return new TurtleUpgradeModeller<>() {
|
||||||
@Override
|
@Override
|
||||||
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, CompoundTag data) {
|
||||||
return TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
return TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import dan200.computercraft.api.turtle.TurtleSide;
|
|||||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -37,16 +36,8 @@ final class TurtleUpgradeModellers {
|
|||||||
|
|
||||||
private static final class UpgradeItemModeller implements TurtleUpgradeModeller<ITurtleUpgrade> {
|
private static final class UpgradeItemModeller implements TurtleUpgradeModeller<ITurtleUpgrade> {
|
||||||
@Override
|
@Override
|
||||||
public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, CompoundTag data) {
|
||||||
return getModel(turtle == null ? upgrade.getCraftingItem() : upgrade.getUpgradeItem(turtle.getUpgradeNBTData(side)), side);
|
var stack = upgrade.getUpgradeItem(data);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TransformedModel getModel(ITurtleUpgrade upgrade, CompoundTag data, TurtleSide side) {
|
|
||||||
return getModel(upgrade.getUpgradeItem(data), side);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransformedModel getModel(ItemStack stack, TurtleSide side) {
|
|
||||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack);
|
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack);
|
||||||
if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model);
|
if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model);
|
||||||
return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform);
|
return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform);
|
||||||
|
@ -4,15 +4,12 @@
|
|||||||
|
|
||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class for pocket computers.
|
* Wrapper class for pocket computers.
|
||||||
@ -90,13 +87,4 @@ public interface IPocketAccess {
|
|||||||
* entity} changes.
|
* entity} changes.
|
||||||
*/
|
*/
|
||||||
void invalidatePeripheral();
|
void invalidatePeripheral();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of all upgrades for the pocket computer.
|
|
||||||
*
|
|
||||||
* @return A collection of all upgrade names.
|
|
||||||
* @deprecated This is a relic of a previous API, which no longer makes sense with newer versions of ComputerCraft.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
Map<ResourceLocation, IPeripheral> getUpgrades();
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,10 @@ package dan200.computercraft.api.pocket;
|
|||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -13,16 +17,46 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* A peripheral which can be equipped to the back side of a pocket computer.
|
* A peripheral which can be equipped to the back side of a pocket computer.
|
||||||
* <p>
|
* <p>
|
||||||
* Pocket upgrades are defined in two stages. First, on creates a {@link IPocketUpgrade} subclass and corresponding
|
* Pocket upgrades are defined in two stages. First, one creates a {@link IPocketUpgrade} subclass and corresponding
|
||||||
* {@link PocketUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
* {@link UpgradeSerialiser} instance, which are then registered in a registry.
|
||||||
* <p>
|
* <p>
|
||||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||||
* the upgrade registered internally. See the documentation in {@link PocketUpgradeSerialiser} for details on this process
|
* the upgrade automatically registered. It is recommended this is done via {@linkplain PocketUpgradeDataProvider data
|
||||||
* and where files should be located.
|
* generators}.
|
||||||
*
|
*
|
||||||
* @see PocketUpgradeSerialiser For how to register a pocket computer upgrade.
|
* <h2>Example</h2>
|
||||||
|
* <pre>{@code
|
||||||
|
* // We use Forge's DeferredRegister to register our serialiser. Fabric mods may register their serialiser directly.
|
||||||
|
* static final DeferredRegister<UpgradeSerialiser<? extends IPocketUpgrade>> SERIALISERS = DeferredRegister.create(IPocketUpgrade.serialiserRegistryKey(), "my_mod");
|
||||||
|
*
|
||||||
|
* // Register a new upgrade serialiser called "my_upgrade".
|
||||||
|
* public static final RegistryObject<UpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
|
||||||
|
* SERIALISERS.register("my_upgrade", () -> UpgradeSerialiser.simple(MyUpgrade::new));
|
||||||
|
*
|
||||||
|
* // Then in your constructor
|
||||||
|
* SERIALISERS.register(bus);
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* We can then define a new upgrade using JSON by placing the following in
|
||||||
|
* {@code data/<my_mod>/computercraft/pocket_upgrades/<my_upgrade_id>.json}.
|
||||||
|
* <pre>{@code
|
||||||
|
* {
|
||||||
|
* "type": my_mod:my_upgrade",
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* {@link PocketUpgradeDataProvider} provides a data provider to aid with generating these JSON files.
|
||||||
*/
|
*/
|
||||||
public interface IPocketUpgrade extends UpgradeBase {
|
public interface IPocketUpgrade extends UpgradeBase {
|
||||||
|
/**
|
||||||
|
* The registry key for upgrade serialisers.
|
||||||
|
*
|
||||||
|
* @return The registry key.
|
||||||
|
*/
|
||||||
|
static ResourceKey<Registry<UpgradeSerialiser<? extends IPocketUpgrade>>> serialiserRegistryKey() {
|
||||||
|
return ComputerCraftAPIService.get().pocketUpgradeRegistryId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a peripheral for the pocket computer.
|
* Creates a peripheral for the pocket computer.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package dan200.computercraft.api.pocket;
|
package dan200.computercraft.api.pocket;
|
||||||
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import net.minecraft.data.DataGenerator;
|
import net.minecraft.data.DataGenerator;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
|
|
||||||
@ -17,10 +18,11 @@ import java.util.function.Consumer;
|
|||||||
* {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to
|
* {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to
|
||||||
* generate them.
|
* generate them.
|
||||||
*
|
*
|
||||||
* @see PocketUpgradeSerialiser
|
* @see IPocketUpgrade
|
||||||
|
* @see UpgradeSerialiser
|
||||||
*/
|
*/
|
||||||
public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPocketUpgrade, PocketUpgradeSerialiser<?>> {
|
public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPocketUpgrade> {
|
||||||
public PocketUpgradeDataProvider(PackOutput output) {
|
public PocketUpgradeDataProvider(PackOutput output) {
|
||||||
super(output, "Pocket Computer Upgrades", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.registryId());
|
super(output, "Pocket Computer Upgrades", "computercraft/pocket_upgrades", IPocketUpgrade.serialiserRegistryKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.api.pocket;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
|
||||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
|
||||||
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a {@link IPocketUpgrade} from disk and reads/writes it to a network packet.
|
|
||||||
* <p>
|
|
||||||
* This follows the same format as {@link dan200.computercraft.api.turtle.TurtleUpgradeSerialiser} - consult the
|
|
||||||
* documentation there for more information.
|
|
||||||
*
|
|
||||||
* @param <T> The type of pocket computer upgrade this is responsible for serialising.
|
|
||||||
* @see IPocketUpgrade
|
|
||||||
* @see PocketUpgradeDataProvider
|
|
||||||
*/
|
|
||||||
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T> {
|
|
||||||
/**
|
|
||||||
* The ID for the associated registry.
|
|
||||||
*
|
|
||||||
* @return The registry key.
|
|
||||||
*/
|
|
||||||
static ResourceKey<Registry<PocketUpgradeSerialiser<?>>> registryId() {
|
|
||||||
return ComputerCraftAPIService.get().pocketUpgradeRegistryId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleCraftingRecipeSerializer},
|
|
||||||
* but for upgrades.
|
|
||||||
* <p>
|
|
||||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
|
||||||
*
|
|
||||||
* @param factory Generate a new upgrade with a specific ID.
|
|
||||||
* @param <T> The type of the generated upgrade.
|
|
||||||
* @return The serialiser for this upgrade
|
|
||||||
*/
|
|
||||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simple(Function<ResourceLocation, T> factory) {
|
|
||||||
final class Impl extends SimpleSerialiser<T> implements PocketUpgradeSerialiser<T> {
|
|
||||||
private Impl(Function<ResourceLocation, T> constructor) {
|
|
||||||
super(constructor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Impl(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
|
||||||
*
|
|
||||||
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
|
||||||
* {@link UpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
|
||||||
* @param <T> The type of the generated upgrade.
|
|
||||||
* @return The serialiser for this upgrade.
|
|
||||||
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
|
||||||
*/
|
|
||||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simpleWithCustomItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
|
||||||
final class Impl extends SerialiserWithCraftingItem<T> implements PocketUpgradeSerialiser<T> {
|
|
||||||
private Impl(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
|
||||||
super(factory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Impl(factory);
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,8 +6,12 @@ package dan200.computercraft.api.turtle;
|
|||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
|
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@ -16,15 +20,54 @@ import javax.annotation.Nullable;
|
|||||||
* peripheral.
|
* peripheral.
|
||||||
* <p>
|
* <p>
|
||||||
* Turtle upgrades are defined in two stages. First, one creates a {@link ITurtleUpgrade} subclass and corresponding
|
* Turtle upgrades are defined in two stages. First, one creates a {@link ITurtleUpgrade} subclass and corresponding
|
||||||
* {@link TurtleUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
* {@link UpgradeSerialiser} instance, which are then registered in a registry.
|
||||||
* <p>
|
* <p>
|
||||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||||
* the upgrade registered internally. See the documentation in {@link TurtleUpgradeSerialiser} for details on this process
|
* the upgrade automatically registered. It is recommended this is done via {@linkplain TurtleUpgradeDataProvider data
|
||||||
* and where files should be located.
|
* generators}.
|
||||||
*
|
*
|
||||||
* @see TurtleUpgradeSerialiser For how to register a turtle upgrade.
|
* <h2>Example</h2>
|
||||||
|
* <pre>{@code
|
||||||
|
* // We use Forge's DeferredRegister to register our serialiser. Fabric mods may register their serialiser directly.
|
||||||
|
* static final DeferredRegister<UpgradeSerialiser<? extends ITurtleUpgrade>> SERIALISERS = DeferredRegister.create(ITurtleUpgrade.serialiserRegistryKey(), "my_mod");
|
||||||
|
*
|
||||||
|
* // Register a new upgrade serialiser called "my_upgrade".
|
||||||
|
* public static final RegistryObject<UpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
|
||||||
|
* SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
|
||||||
|
*
|
||||||
|
* // Then in your constructor
|
||||||
|
* SERIALISERS.register( bus );
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* We can then define a new upgrade using JSON by placing the following in
|
||||||
|
* {@literal data/<my_mod>/computercraft/turtle_upgrades/<my_upgrade_id>.json}}.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* {
|
||||||
|
* "type": my_mod:my_upgrade",
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* {@link TurtleUpgradeDataProvider} provides a data provider to aid with generating these JSON files.
|
||||||
|
* <p>
|
||||||
|
* Finally, we need to register a model for our upgrade, see
|
||||||
|
* {@link dan200.computercraft.api.client.turtle.TurtleUpgradeModeller} for more information.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* // Register our model inside FMLClientSetupEvent
|
||||||
|
* ComputerCraftAPIClient.registerTurtleUpgradeModeller(MY_UPGRADE.get(), TurtleUpgradeModeller.flatItem())
|
||||||
|
* }</pre>
|
||||||
*/
|
*/
|
||||||
public interface ITurtleUpgrade extends UpgradeBase {
|
public interface ITurtleUpgrade extends UpgradeBase {
|
||||||
|
/**
|
||||||
|
* The registry key for upgrade serialisers.
|
||||||
|
*
|
||||||
|
* @return The registry key.
|
||||||
|
*/
|
||||||
|
static ResourceKey<Registry<UpgradeSerialiser<? extends ITurtleUpgrade>>> serialiserRegistryKey() {
|
||||||
|
return ComputerCraftAPIService.get().turtleUpgradeRegistryId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether this turtle adds a tool or a peripheral to the turtle.
|
* Return whether this turtle adds a tool or a peripheral to the turtle.
|
||||||
*
|
*
|
||||||
|
@ -7,8 +7,9 @@ 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 dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import net.minecraft.core.registries.Registries;
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.data.DataGenerator;
|
import net.minecraft.data.DataGenerator;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@ -29,13 +30,13 @@ import java.util.function.Consumer;
|
|||||||
* {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to
|
* {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to
|
||||||
* generate them.
|
* generate them.
|
||||||
*
|
*
|
||||||
* @see TurtleUpgradeSerialiser
|
* @see ITurtleUpgrade
|
||||||
*/
|
*/
|
||||||
public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITurtleUpgrade, TurtleUpgradeSerialiser<?>> {
|
public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITurtleUpgrade> {
|
||||||
private static final ResourceLocation TOOL_ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "tool");
|
private static final ResourceLocation TOOL_ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "tool");
|
||||||
|
|
||||||
public TurtleUpgradeDataProvider(PackOutput output) {
|
public TurtleUpgradeDataProvider(PackOutput output) {
|
||||||
super(output, "Turtle Upgrades", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.registryId());
|
super(output, "Turtle Upgrades", "computercraft/turtle_upgrades", ITurtleUpgrade.serialiserRegistryKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +58,7 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
|||||||
*/
|
*/
|
||||||
public static class ToolBuilder {
|
public static class ToolBuilder {
|
||||||
private final ResourceLocation id;
|
private final ResourceLocation id;
|
||||||
private final TurtleUpgradeSerialiser<?> serialiser;
|
private final UpgradeSerialiser<? extends ITurtleUpgrade> serialiser;
|
||||||
private final Item toolItem;
|
private final Item toolItem;
|
||||||
private @Nullable String adjective;
|
private @Nullable String adjective;
|
||||||
private @Nullable Item craftingItem;
|
private @Nullable Item craftingItem;
|
||||||
@ -66,7 +67,7 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
|||||||
private boolean allowEnchantments = false;
|
private boolean allowEnchantments = false;
|
||||||
private TurtleToolDurability consumeDurability = TurtleToolDurability.NEVER;
|
private TurtleToolDurability consumeDurability = TurtleToolDurability.NEVER;
|
||||||
|
|
||||||
ToolBuilder(ResourceLocation id, TurtleUpgradeSerialiser<?> serialiser, Item toolItem) {
|
ToolBuilder(ResourceLocation id, UpgradeSerialiser<? extends ITurtleUpgrade> serialiser, Item toolItem) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.serialiser = serialiser;
|
this.serialiser = serialiser;
|
||||||
this.toolItem = toolItem;
|
this.toolItem = toolItem;
|
||||||
@ -149,12 +150,12 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
|
|||||||
*
|
*
|
||||||
* @param add The callback given to {@link #addUpgrades(Consumer)}.
|
* @param add The callback given to {@link #addUpgrades(Consumer)}.
|
||||||
*/
|
*/
|
||||||
public void add(Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> add) {
|
public void add(Consumer<Upgrade<UpgradeSerialiser<? extends ITurtleUpgrade>>> add) {
|
||||||
add.accept(new Upgrade<>(id, serialiser, s -> {
|
add.accept(new Upgrade<>(id, serialiser, s -> {
|
||||||
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registries.ITEM, toolItem).toString());
|
s.addProperty("item", RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, 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", PlatformHelper.get().getRegistryKey(Registries.ITEM, craftingItem).toString());
|
s.addProperty("craftItem", RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, 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());
|
||||||
|
@ -1,109 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.api.turtle;
|
|
||||||
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
|
||||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
|
||||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
|
||||||
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
|
||||||
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a {@link ITurtleUpgrade} from disk and reads/writes it to a network packet.
|
|
||||||
* <p>
|
|
||||||
* These should be registered in a {@link Registry} while the game is loading, much like {@link RecipeSerializer}s.
|
|
||||||
* <p>
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* <h2>Example (Forge)</h2>
|
|
||||||
* <pre>{@code
|
|
||||||
* static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
|
|
||||||
*
|
|
||||||
* // Register a new upgrade serialiser called "my_upgrade".
|
|
||||||
* public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
|
|
||||||
* SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
|
|
||||||
*
|
|
||||||
* // Then in your constructor
|
|
||||||
* SERIALISERS.register( bus );
|
|
||||||
* }</pre>
|
|
||||||
* <p>
|
|
||||||
* We can then define a new upgrade using JSON by placing the following in
|
|
||||||
* {@literal data/<my_mod>/computercraft/turtle_upgrades/<my_upgrade_id>.json}}.
|
|
||||||
*
|
|
||||||
* <pre>{@code
|
|
||||||
* {
|
|
||||||
* "type": my_mod:my_upgrade",
|
|
||||||
* }
|
|
||||||
* }</pre>
|
|
||||||
* <p>
|
|
||||||
* Finally, we need to register a model for our upgrade. The way to do this varies on mod loader, see
|
|
||||||
* {@link dan200.computercraft.api.client.turtle.TurtleUpgradeModeller} for more information.
|
|
||||||
* <p>
|
|
||||||
* {@link TurtleUpgradeDataProvider} provides a data provider to aid with generating these JSON files.
|
|
||||||
*
|
|
||||||
* @param <T> The type of turtle upgrade this is responsible for serialising.
|
|
||||||
* @see ITurtleUpgrade
|
|
||||||
* @see TurtleUpgradeDataProvider
|
|
||||||
* @see dan200.computercraft.api.client.turtle.TurtleUpgradeModeller
|
|
||||||
*/
|
|
||||||
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T> {
|
|
||||||
/**
|
|
||||||
* The ID for the associated registry.
|
|
||||||
*
|
|
||||||
* @return The registry key.
|
|
||||||
*/
|
|
||||||
static ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> registryId() {
|
|
||||||
return ComputerCraftAPIService.get().turtleUpgradeRegistryId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleCraftingRecipeSerializer},
|
|
||||||
* but for upgrades.
|
|
||||||
* <p>
|
|
||||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
|
||||||
*
|
|
||||||
* @param factory Generate a new upgrade with a specific ID.
|
|
||||||
* @param <T> The type of the generated upgrade.
|
|
||||||
* @return The serialiser for this upgrade
|
|
||||||
*/
|
|
||||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simple(Function<ResourceLocation, T> factory) {
|
|
||||||
final class Impl extends SimpleSerialiser<T> implements TurtleUpgradeSerialiser<T> {
|
|
||||||
private Impl(Function<ResourceLocation, T> constructor) {
|
|
||||||
super(constructor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Impl(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
|
||||||
*
|
|
||||||
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
|
||||||
* {@link UpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
|
||||||
* @param <T> The type of the generated upgrade.
|
|
||||||
* @return The serialiser for this upgrade.
|
|
||||||
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
|
||||||
*/
|
|
||||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simpleWithCustomItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
|
||||||
final class Impl extends SerialiserWithCraftingItem<T> implements TurtleUpgradeSerialiser<T> {
|
|
||||||
private Impl(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
|
||||||
super(factory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Impl(factory);
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,6 @@ import dan200.computercraft.api.pocket.IPocketUpgrade;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
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 dan200.computercraft.impl.PlatformHelper;
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@ -100,7 +99,7 @@ public interface UpgradeBase {
|
|||||||
* 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>
|
* <p>
|
||||||
* This is based on {@code net.minecraftforge.common.crafting.StrictNBTIngredient}'s check.
|
* This is based on {@code net.neoforged.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()}.
|
||||||
@ -111,12 +110,12 @@ public interface UpgradeBase {
|
|||||||
|
|
||||||
// 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 = PlatformHelper.get().getShareTag(stack);
|
var tag = stack.getTag();
|
||||||
var craftingShareTag = PlatformHelper.get().getShareTag(crafting);
|
var craftingTag = crafting.getTag();
|
||||||
if (shareTag == craftingShareTag) return true;
|
if (tag == craftingTag) return true;
|
||||||
if (shareTag == null) return Objects.requireNonNull(craftingShareTag).isEmpty();
|
if (tag == null) return Objects.requireNonNull(craftingTag).isEmpty();
|
||||||
if (craftingShareTag == null) return shareTag.isEmpty();
|
if (craftingTag == null) return tag.isEmpty();
|
||||||
return shareTag.equals(craftingShareTag);
|
return tag.equals(craftingTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,19 +6,20 @@ 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.impl.PlatformHelper;
|
import dan200.computercraft.impl.PlatformHelper;
|
||||||
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.data.CachedOutput;
|
import net.minecraft.data.CachedOutput;
|
||||||
import net.minecraft.data.DataProvider;
|
import net.minecraft.data.DataProvider;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
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 org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -31,31 +32,31 @@ import java.util.function.Function;
|
|||||||
* the other subclasses.
|
* the other subclasses.
|
||||||
*
|
*
|
||||||
* @param <T> The base class of upgrades.
|
* @param <T> The base class of upgrades.
|
||||||
* @param <R> The upgrade serialiser to register for.
|
|
||||||
*/
|
*/
|
||||||
public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends UpgradeSerialiser<? extends T>> implements DataProvider {
|
public abstract class UpgradeDataProvider<T extends UpgradeBase> implements DataProvider {
|
||||||
private final PackOutput output;
|
private final PackOutput output;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String folder;
|
private final String folder;
|
||||||
private final ResourceKey<Registry<R>> registry;
|
private final Registry<UpgradeSerialiser<? extends T>> registry;
|
||||||
|
|
||||||
private @Nullable List<T> upgrades;
|
private @Nullable List<T> upgrades;
|
||||||
|
|
||||||
protected UpgradeDataProvider(PackOutput output, String name, String folder, ResourceKey<Registry<R>> registry) {
|
@ApiStatus.Internal
|
||||||
|
protected UpgradeDataProvider(PackOutput output, String name, String folder, ResourceKey<Registry<UpgradeSerialiser<? extends T>>> registry) {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.folder = folder;
|
this.folder = folder;
|
||||||
this.registry = registry;
|
this.registry = RegistryHelper.getRegistry(registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
* Register an upgrade using a {@linkplain UpgradeSerialiser#simple(Function) "simple" serialiser}.
|
||||||
*
|
*
|
||||||
* @param id The ID of the upgrade to create.
|
* @param id The ID of the upgrade to create.
|
||||||
* @param serialiser The simple serialiser.
|
* @param serialiser The simple serialiser.
|
||||||
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||||
*/
|
*/
|
||||||
public final Upgrade<R> simple(ResourceLocation id, R serialiser) {
|
public final Upgrade<UpgradeSerialiser<? extends T>> simple(ResourceLocation id, UpgradeSerialiser<? extends T> serialiser) {
|
||||||
if (!(serialiser instanceof SimpleSerialiser)) {
|
if (!(serialiser instanceof SimpleSerialiser)) {
|
||||||
throw new IllegalStateException(serialiser + " must be a simple() seriaiser.");
|
throw new IllegalStateException(serialiser + " must be a simple() seriaiser.");
|
||||||
}
|
}
|
||||||
@ -65,20 +66,20 @@ public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends Upgra
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
* Register an upgrade using a {@linkplain UpgradeSerialiser#simple(Function) simple serialiser}.
|
||||||
*
|
*
|
||||||
* @param id The ID of the upgrade to create.
|
* @param id The ID of the upgrade to create.
|
||||||
* @param serialiser The simple serialiser.
|
* @param serialiser The simple serialiser.
|
||||||
* @param item The crafting upgrade for this item.
|
* @param item The crafting upgrade for this item.
|
||||||
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||||
*/
|
*/
|
||||||
public final Upgrade<R> simpleWithCustomItem(ResourceLocation id, R serialiser, Item item) {
|
public final Upgrade<UpgradeSerialiser<? extends T>> simpleWithCustomItem(ResourceLocation id, UpgradeSerialiser<? extends T> serialiser, Item item) {
|
||||||
if (!(serialiser instanceof SerialiserWithCraftingItem)) {
|
if (!(serialiser instanceof SerialiserWithCraftingItem)) {
|
||||||
throw new IllegalStateException(serialiser + " must be a simpleWithCustomItem() serialiser.");
|
throw new IllegalStateException(serialiser + " must be a simpleWithCustomItem() serialiser.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Upgrade<>(id, serialiser, s ->
|
return new Upgrade<>(id, serialiser, s ->
|
||||||
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registries.ITEM, item).toString())
|
s.addProperty("item", RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, item).toString())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +95,7 @@ public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends Upgra
|
|||||||
*
|
*
|
||||||
* @param addUpgrade A callback used to register an upgrade.
|
* @param addUpgrade A callback used to register an upgrade.
|
||||||
*/
|
*/
|
||||||
protected abstract void addUpgrades(Consumer<Upgrade<R>> addUpgrade);
|
protected abstract void addUpgrades(Consumer<Upgrade<UpgradeSerialiser<? extends T>>> addUpgrade);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<?> run(CachedOutput cache) {
|
public CompletableFuture<?> run(CachedOutput cache) {
|
||||||
@ -107,7 +108,7 @@ public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends Upgra
|
|||||||
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", PlatformHelper.get().getRegistryKey(registry, upgrade.serialiser()).toString());
|
json.addProperty("type", RegistryHelper.getKeyOrThrow(registry, upgrade.serialiser()).toString());
|
||||||
upgrade.serialise().accept(json);
|
upgrade.serialise().accept(json);
|
||||||
|
|
||||||
futures.add(DataProvider.saveStable(cache, json, base.resolve(upgrade.id().getNamespace() + "/" + folder + "/" + upgrade.id().getPath() + ".json")));
|
futures.add(DataProvider.saveStable(cache, json, base.resolve(upgrade.id().getNamespace() + "/" + folder + "/" + upgrade.id().getPath() + ".json")));
|
||||||
@ -129,9 +130,9 @@ public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends Upgra
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final R existingSerialiser(ResourceLocation id) {
|
public final UpgradeSerialiser<? extends T> existingSerialiser(ResourceLocation id) {
|
||||||
var result = PlatformHelper.get().getRegistryObject(registry, id);
|
var result = registry.get(id);
|
||||||
if (result == null) throw new IllegalArgumentException("No such serialiser " + registry);
|
if (result == null) throw new IllegalArgumentException("No such serialiser " + id);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,21 +5,40 @@
|
|||||||
package dan200.computercraft.api.upgrades;
|
package dan200.computercraft.api.upgrades;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
||||||
|
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||||
|
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||||
|
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base interface for upgrade serialisers. This should generally not be implemented directly, instead implementing one
|
* A serialiser for {@link ITurtleUpgrade} or {@link IPocketUpgrade}s.
|
||||||
* of {@link TurtleUpgradeSerialiser} or {@link PocketUpgradeSerialiser}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* However, it may sometimes be useful to implement this if you have some shared logic between upgrade types.
|
* These should be registered in a {@link Registry} while the game is loading, much like {@link RecipeSerializer}s.
|
||||||
|
* <p>
|
||||||
|
* This interface is very similar to {@link RecipeSerializer}; each serialiser should correspond to a specific upgrade
|
||||||
|
* class. Upgrades are then read from JSON files in datapacks, allowing multiple instances of the upgrade to be
|
||||||
|
* registered.
|
||||||
|
* <p>
|
||||||
|
* If your 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.
|
||||||
|
* <p>
|
||||||
|
* Upgrades may be data generated via a {@link UpgradeDataProvider} (see {@link TurtleUpgradeDataProvider} and
|
||||||
|
* {@link PocketUpgradeDataProvider}).
|
||||||
*
|
*
|
||||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||||
* @see TurtleUpgradeSerialiser
|
* @see ITurtleUpgrade
|
||||||
* @see PocketUpgradeSerialiser
|
* @see IPocketUpgrade
|
||||||
*/
|
*/
|
||||||
public interface UpgradeSerialiser<T extends UpgradeBase> {
|
public interface UpgradeSerialiser<T extends UpgradeBase> {
|
||||||
/**
|
/**
|
||||||
@ -49,4 +68,30 @@ public interface UpgradeSerialiser<T extends UpgradeBase> {
|
|||||||
*/
|
*/
|
||||||
void toNetwork(FriendlyByteBuf buffer, T upgrade);
|
void toNetwork(FriendlyByteBuf buffer, T upgrade);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleCraftingRecipeSerializer},
|
||||||
|
* but for upgrades.
|
||||||
|
* <p>
|
||||||
|
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||||
|
*
|
||||||
|
* @param factory Generate a new upgrade with a specific ID.
|
||||||
|
* @param <T> The type of the generated upgrade.
|
||||||
|
* @return The serialiser for this upgrade
|
||||||
|
*/
|
||||||
|
static <T extends UpgradeBase> UpgradeSerialiser<T> simple(Function<ResourceLocation, T> factory) {
|
||||||
|
return new SimpleSerialiser<>(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
||||||
|
*
|
||||||
|
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
||||||
|
* {@link UpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
||||||
|
* @param <T> The type of the generated upgrade.
|
||||||
|
* @return The serialiser for this upgrade.
|
||||||
|
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
||||||
|
*/
|
||||||
|
static <T extends UpgradeBase> UpgradeSerialiser<T> simpleWithCustomItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||||
|
return new SerialiserWithCraftingItem<>(factory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,11 @@ import dan200.computercraft.api.media.MediaProvider;
|
|||||||
import dan200.computercraft.api.network.PacketNetwork;
|
import dan200.computercraft.api.network.PacketNetwork;
|
||||||
import dan200.computercraft.api.network.wired.WiredElement;
|
import dan200.computercraft.api.network.wired.WiredElement;
|
||||||
import dan200.computercraft.api.network.wired.WiredNode;
|
import dan200.computercraft.api.network.wired.WiredNode;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.redstone.BundledRedstoneProvider;
|
import dan200.computercraft.api.redstone.BundledRedstoneProvider;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
@ -67,9 +68,9 @@ public interface ComputerCraftAPIService {
|
|||||||
|
|
||||||
void registerRefuelHandler(TurtleRefuelHandler handler);
|
void registerRefuelHandler(TurtleRefuelHandler handler);
|
||||||
|
|
||||||
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> turtleUpgradeRegistryId();
|
ResourceKey<Registry<UpgradeSerialiser<? extends ITurtleUpgrade>>> turtleUpgradeRegistryId();
|
||||||
|
|
||||||
ResourceKey<Registry<PocketUpgradeSerialiser<?>>> pocketUpgradeRegistryId();
|
ResourceKey<Registry<UpgradeSerialiser<? extends IPocketUpgrade>>> pocketUpgradeRegistryId();
|
||||||
|
|
||||||
DetailRegistry<ItemStack> getItemStackDetailRegistry();
|
DetailRegistry<ItemStack> getItemStackDetailRegistry();
|
||||||
|
|
||||||
|
@ -6,11 +6,6 @@ package dan200.computercraft.impl;
|
|||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||||
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 org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -32,39 +27,6 @@ public interface PlatformHelper {
|
|||||||
return instance == null ? Services.raise(PlatformHelper.class, Instance.ERROR) : 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a resource condition which requires a mod to be loaded. This should be used by data providers such as
|
* Add a resource condition which requires a mod to be loaded. This should be used by data providers such as
|
||||||
* {@link UpgradeDataProvider}.
|
* {@link UpgradeDataProvider}.
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.impl;
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additioanl functions for working with {@linkplain Registry registries}.
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public final class RegistryHelper {
|
||||||
|
private RegistryHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a registry from a {@link ResourceKey}, throwing if it does not exist.
|
||||||
|
*
|
||||||
|
* @param id The id of the registry.
|
||||||
|
* @param <T> The contents of the registry
|
||||||
|
* @return The associated registry.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> id) {
|
||||||
|
var registry = (Registry<T>) BuiltInRegistries.REGISTRY.get(id.location());
|
||||||
|
if (registry == null) throw new IllegalArgumentException("Unknown registry " + id);
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the key of a registry entry, throwing if it is not registered.
|
||||||
|
*
|
||||||
|
* @param registry The registry to look up in.
|
||||||
|
* @param object The object to look up.
|
||||||
|
* @param <T> The type of this registry.
|
||||||
|
* @return The ID of this object
|
||||||
|
* @see Registry#getResourceKey(Object)
|
||||||
|
*/
|
||||||
|
public static <T> ResourceLocation getKeyOrThrow(Registry<T> registry, T object) {
|
||||||
|
var key = registry.getResourceKey(object);
|
||||||
|
if (key.isEmpty()) throw new IllegalArgumentException(object + " was not registered in " + registry.key());
|
||||||
|
return key.get().location();
|
||||||
|
}
|
||||||
|
}
|
@ -23,27 +23,27 @@ 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
|
@ApiStatus.Internal
|
||||||
public abstract class SerialiserWithCraftingItem<T extends UpgradeBase> implements UpgradeSerialiser<T> {
|
public final class SerialiserWithCraftingItem<T extends UpgradeBase> implements UpgradeSerialiser<T> {
|
||||||
private final BiFunction<ResourceLocation, ItemStack, T> factory;
|
private final BiFunction<ResourceLocation, ItemStack, T> factory;
|
||||||
|
|
||||||
protected SerialiserWithCraftingItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
public SerialiserWithCraftingItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final T fromJson(ResourceLocation id, JsonObject object) {
|
public T fromJson(ResourceLocation id, JsonObject object) {
|
||||||
var item = GsonHelper.getAsItem(object, "item");
|
var item = GsonHelper.getAsItem(object, "item");
|
||||||
return factory.apply(id, new ItemStack(item));
|
return factory.apply(id, new ItemStack(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
public T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||||
var item = buffer.readItem();
|
var item = buffer.readItem();
|
||||||
return factory.apply(id, item);
|
return factory.apply(id, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void toNetwork(FriendlyByteBuf buffer, T upgrade) {
|
public void toNetwork(FriendlyByteBuf buffer, T upgrade) {
|
||||||
buffer.writeItem(upgrade.getCraftingItem());
|
buffer.writeItem(upgrade.getCraftingItem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,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
|
@ApiStatus.Internal
|
||||||
public abstract class SimpleSerialiser<T extends UpgradeBase> implements UpgradeSerialiser<T> {
|
public final class SimpleSerialiser<T extends UpgradeBase> implements UpgradeSerialiser<T> {
|
||||||
private final Function<ResourceLocation, T> constructor;
|
private final Function<ResourceLocation, T> constructor;
|
||||||
|
|
||||||
public SimpleSerialiser(Function<ResourceLocation, T> constructor) {
|
public SimpleSerialiser(Function<ResourceLocation, T> constructor) {
|
||||||
@ -29,16 +29,16 @@ public abstract class SimpleSerialiser<T extends UpgradeBase> implements Upgrade
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final T fromJson(ResourceLocation id, JsonObject object) {
|
public T fromJson(ResourceLocation id, JsonObject object) {
|
||||||
return constructor.apply(id);
|
return constructor.apply(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
public T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||||
return constructor.apply(id);
|
return constructor.apply(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void toNetwork(FriendlyByteBuf buffer, T upgrade) {
|
public void toNetwork(FriendlyByteBuf buffer, T upgrade) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ public final class ClientHooks {
|
|||||||
*/
|
*/
|
||||||
public static void addBlockDebugInfo(Consumer<String> addText) {
|
public static void addBlockDebugInfo(Consumer<String> addText) {
|
||||||
var minecraft = Minecraft.getInstance();
|
var minecraft = Minecraft.getInstance();
|
||||||
if (!minecraft.options.renderDebug || minecraft.level == null) return;
|
if (!minecraft.getDebugOverlay().showDebugScreen() || minecraft.level == null) return;
|
||||||
if (minecraft.hitResult == null || minecraft.hitResult.getType() != HitResult.Type.BLOCK) return;
|
if (minecraft.hitResult == null || minecraft.hitResult.getType() != HitResult.Type.BLOCK) return;
|
||||||
|
|
||||||
var tile = minecraft.level.getBlockEntity(((BlockHitResult) minecraft.hitResult).getBlockPos());
|
var tile = minecraft.level.getBlockEntity(((BlockHitResult) minecraft.hitResult).getBlockPos());
|
||||||
@ -138,7 +138,7 @@ public final class ClientHooks {
|
|||||||
* @param addText A callback which adds a single line of text.
|
* @param addText A callback which adds a single line of text.
|
||||||
*/
|
*/
|
||||||
public static void addGameDebugInfo(Consumer<String> addText) {
|
public static void addGameDebugInfo(Consumer<String> addText) {
|
||||||
if (MonitorBlockEntityRenderer.hasRenderedThisFrame() && Minecraft.getInstance().options.renderDebug) {
|
if (MonitorBlockEntityRenderer.hasRenderedThisFrame() && Minecraft.getInstance().getDebugOverlay().showDebugScreen()) {
|
||||||
addText.accept("[CC:T] Monitor renderer: " + MonitorBlockEntityRenderer.currentRenderer());
|
addText.accept("[CC:T] Monitor renderer: " + MonitorBlockEntityRenderer.currentRenderer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ import net.minecraft.Util;
|
|||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.color.item.ItemColor;
|
import net.minecraft.client.color.item.ItemColor;
|
||||||
import net.minecraft.client.gui.screens.MenuScreens;
|
import net.minecraft.client.gui.screens.MenuScreens;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.client.gui.screens.inventory.MenuAccess;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.ShaderInstance;
|
import net.minecraft.client.renderer.ShaderInstance;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
@ -42,6 +44,8 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||||
import net.minecraft.server.packs.resources.ResourceProvider;
|
import net.minecraft.server.packs.resources.ResourceProvider;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraft.world.inventory.MenuType;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.ItemLike;
|
import net.minecraft.world.level.ItemLike;
|
||||||
@ -79,17 +83,6 @@ public final class ClientRegistry {
|
|||||||
* Register any client-side objects which must be done on the main thread.
|
* Register any client-side objects which must be done on the main thread.
|
||||||
*/
|
*/
|
||||||
public static void registerMainThread() {
|
public static void registerMainThread() {
|
||||||
MenuScreens.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.COMPUTER.get(), ComputerScreen::new);
|
|
||||||
MenuScreens.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER.get(), ComputerScreen::new);
|
|
||||||
MenuScreens.<AbstractComputerMenu, NoTermComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER_NO_TERM.get(), NoTermComputerScreen::new);
|
|
||||||
MenuScreens.register(ModRegistry.Menus.TURTLE.get(), TurtleScreen::new);
|
|
||||||
|
|
||||||
MenuScreens.register(ModRegistry.Menus.PRINTER.get(), PrinterScreen::new);
|
|
||||||
MenuScreens.register(ModRegistry.Menus.DISK_DRIVE.get(), DiskDriveScreen::new);
|
|
||||||
MenuScreens.register(ModRegistry.Menus.PRINTOUT.get(), PrintoutScreen::new);
|
|
||||||
|
|
||||||
MenuScreens.<ViewComputerMenu, ComputerScreen<ViewComputerMenu>>register(ModRegistry.Menus.VIEW_COMPUTER.get(), ComputerScreen::new);
|
|
||||||
|
|
||||||
registerItemProperty("state",
|
registerItemProperty("state",
|
||||||
new UnclampedPropertyFunction((stack, world, player, random) -> ClientPocketComputers.get(stack).getState().ordinal()),
|
new UnclampedPropertyFunction((stack, world, player, random) -> ClientPocketComputers.get(stack).getState().ordinal()),
|
||||||
ModRegistry.Items.POCKET_COMPUTER_NORMAL, ModRegistry.Items.POCKET_COMPUTER_ADVANCED
|
ModRegistry.Items.POCKET_COMPUTER_NORMAL, ModRegistry.Items.POCKET_COMPUTER_ADVANCED
|
||||||
@ -100,6 +93,23 @@ public final class ClientRegistry {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void registerMenuScreens(RegisterMenuScreen register) {
|
||||||
|
register.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.COMPUTER.get(), ComputerScreen::new);
|
||||||
|
register.<AbstractComputerMenu, ComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER.get(), ComputerScreen::new);
|
||||||
|
register.<AbstractComputerMenu, NoTermComputerScreen<AbstractComputerMenu>>register(ModRegistry.Menus.POCKET_COMPUTER_NO_TERM.get(), NoTermComputerScreen::new);
|
||||||
|
register.register(ModRegistry.Menus.TURTLE.get(), TurtleScreen::new);
|
||||||
|
|
||||||
|
register.register(ModRegistry.Menus.PRINTER.get(), PrinterScreen::new);
|
||||||
|
register.register(ModRegistry.Menus.DISK_DRIVE.get(), DiskDriveScreen::new);
|
||||||
|
register.register(ModRegistry.Menus.PRINTOUT.get(), PrintoutScreen::new);
|
||||||
|
|
||||||
|
register.<ViewComputerMenu, ComputerScreen<ViewComputerMenu>>register(ModRegistry.Menus.VIEW_COMPUTER.get(), ComputerScreen::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface RegisterMenuScreen {
|
||||||
|
<M extends AbstractContainerMenu, U extends Screen & MenuAccess<M>> void register(MenuType<? extends M> type, MenuScreens.ScreenConstructor<M, U> factory);
|
||||||
|
}
|
||||||
|
|
||||||
public static void registerTurtleModellers(RegisterTurtleUpgradeModeller register) {
|
public static void registerTurtleModellers(RegisterTurtleUpgradeModeller register) {
|
||||||
register.register(ModRegistry.TurtleSerialisers.SPEAKER.get(), TurtleUpgradeModeller.sided(
|
register.register(ModRegistry.TurtleSerialisers.SPEAKER.get(), TurtleUpgradeModeller.sided(
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_left"),
|
new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_speaker_left"),
|
||||||
|
@ -125,7 +125,6 @@ public abstract class AbstractComputerScreen<T extends AbstractComputerMenu> ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(graphics);
|
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(graphics, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(graphics);
|
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(graphics, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import net.minecraft.client.gui.GuiGraphics;
|
|||||||
import net.minecraft.client.gui.components.toasts.Toast;
|
import net.minecraft.client.gui.components.toasts.Toast;
|
||||||
import net.minecraft.client.gui.components.toasts.ToastComponent;
|
import net.minecraft.client.gui.components.toasts.ToastComponent;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.FormattedCharSequence;
|
import net.minecraft.util.FormattedCharSequence;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ import java.util.List;
|
|||||||
* A {@link Toast} implementation which displays an arbitrary message along with an optional {@link ItemStack}.
|
* A {@link Toast} implementation which displays an arbitrary message along with an optional {@link ItemStack}.
|
||||||
*/
|
*/
|
||||||
public class ItemToast implements Toast {
|
public class ItemToast implements Toast {
|
||||||
|
private static final ResourceLocation TEXTURE = new ResourceLocation("toast/recipe");
|
||||||
public static final Object TRANSFER_NO_RESPONSE_TOKEN = new Object();
|
public static final Object TRANSFER_NO_RESPONSE_TOKEN = new Object();
|
||||||
|
|
||||||
private static final long DISPLAY_TIME = 7000L;
|
private static final long DISPLAY_TIME = 7000L;
|
||||||
@ -79,7 +81,7 @@ public class ItemToast implements Toast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (width == 160 && message.size() <= 1) {
|
if (width == 160 && message.size() <= 1) {
|
||||||
graphics.blit(TEXTURE, 0, 0, 0, 64, width, height());
|
graphics.blitSprite(TEXTURE, 0, 0, width, height());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
var height = height();
|
var height = height();
|
||||||
@ -109,14 +111,14 @@ public class ItemToast implements Toast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) {
|
private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) {
|
||||||
var leftOffset = 5;
|
var leftOffset = u == 0 ? 20 : 5;
|
||||||
var rightOffset = Math.min(60, x - leftOffset);
|
var rightOffset = Math.min(60, x - leftOffset);
|
||||||
|
|
||||||
graphics.blit(TEXTURE, 0, y, 0, 32 + u, leftOffset, height);
|
graphics.blitSprite(TEXTURE, 160, 32, 0, u, 0, y, leftOffset, height);
|
||||||
for (var k = leftOffset; k < x - rightOffset; k += 64) {
|
for (var k = leftOffset; k < x - rightOffset; k += 64) {
|
||||||
graphics.blit(TEXTURE, k, y, 32, 32 + u, Math.min(64, x - k - rightOffset), height);
|
graphics.blitSprite(TEXTURE, 160, 32, 32, u, k, y, Math.min(64, x - k - rightOffset), height);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics.blit(TEXTURE, x - rightOffset, y, 160 - rightOffset, 32 + u, rightOffset, height);
|
graphics.blitSprite(TEXTURE, 160, 32, 160 - rightOffset, u, x - rightOffset, y, rightOffset, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,9 +63,9 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) {
|
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
|
||||||
minecraft.player.getInventory().swapPaint(pDelta);
|
minecraft.player.getInventory().swapPaint(scrollX);
|
||||||
return super.mouseScrolled(pMouseX, pMouseY, pDelta);
|
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -86,8 +86,6 @@ public final class OptionScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(graphics);
|
|
||||||
|
|
||||||
// Render the actual texture.
|
// Render the actual texture.
|
||||||
graphics.blit(BACKGROUND, x, y, 0, 0, innerWidth, PADDING);
|
graphics.blit(BACKGROUND, x, y, 0, 0, innerWidth, PADDING);
|
||||||
graphics.blit(BACKGROUND,
|
graphics.blit(BACKGROUND,
|
||||||
|
@ -30,7 +30,6 @@ public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
renderBackground(graphics);
|
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
renderTooltip(graphics, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
@ -64,15 +64,15 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double x, double y, double delta) {
|
public boolean mouseScrolled(double x, double y, double deltaX, double deltaY) {
|
||||||
if (super.mouseScrolled(x, y, delta)) return true;
|
if (super.mouseScrolled(x, y, deltaX, deltaY)) return true;
|
||||||
if (delta < 0) {
|
if (deltaX < 0) {
|
||||||
// Scroll up goes to the next page
|
// Scroll up goes to the next page
|
||||||
if (page < pages - 1) page++;
|
if (page < pages - 1) page++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delta > 0) {
|
if (deltaX > 0) {
|
||||||
// Scroll down goes to the previous page
|
// Scroll down goes to the previous page
|
||||||
if (page > 0) page--;
|
if (page > 0) page--;
|
||||||
return true;
|
return true;
|
||||||
@ -91,14 +91,12 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void renderBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
// We must take the background further back in order to not overlap with our printed pages.
|
// We must take the background further back in order to not overlap with our printed pages.
|
||||||
graphics.pose().pushPose();
|
graphics.pose().pushPose();
|
||||||
graphics.pose().translate(0, 0, -1);
|
graphics.pose().translate(0, 0, -1);
|
||||||
renderBackground(graphics);
|
super.renderBackground(graphics, mouseX, mouseY, partialTicks);
|
||||||
graphics.pose().popPose();
|
graphics.pose().popPose();
|
||||||
|
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,6 +43,10 @@ public class DynamicImageButton extends Button {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
var message = this.message.get();
|
||||||
|
setMessage(message.message());
|
||||||
|
setTooltip(message.tooltip());
|
||||||
|
|
||||||
var texture = this.texture.get(isHoveredOrFocused());
|
var texture = this.texture.get(isHoveredOrFocused());
|
||||||
|
|
||||||
RenderSystem.disableDepthTest();
|
RenderSystem.disableDepthTest();
|
||||||
@ -50,14 +54,6 @@ public class DynamicImageButton extends Button {
|
|||||||
RenderSystem.enableDepthTest();
|
RenderSystem.enableDepthTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
|
||||||
var message = this.message.get();
|
|
||||||
setMessage(message.message());
|
|
||||||
setTooltip(message.tooltip());
|
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
public record HintedMessage(Component message, Tooltip tooltip) {
|
public record HintedMessage(Component message, Tooltip tooltip) {
|
||||||
public HintedMessage(Component message, @Nullable Component hint) {
|
public HintedMessage(Component message, @Nullable Component hint) {
|
||||||
this(
|
this(
|
||||||
|
@ -195,7 +195,7 @@ public class TerminalWidget extends AbstractWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
public boolean mouseScrolled(double mouseX, double mouseY, double delta, double deltaY) {
|
||||||
if (!inTermRegion(mouseX, mouseY)) return false;
|
if (!inTermRegion(mouseX, mouseY)) return false;
|
||||||
if (!hasMouseSupport() || delta == 0) return false;
|
if (!hasMouseSupport() || delta == 0) return false;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import net.minecraft.client.renderer.MultiBufferSource;
|
|||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.network.protocol.Packet;
|
import net.minecraft.network.protocol.Packet;
|
||||||
import net.minecraft.network.protocol.game.ServerGamePacketListener;
|
import net.minecraft.network.protocol.common.ServerCommonPacketListener;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -27,7 +27,7 @@ public interface ClientPlatformHelper extends dan200.computercraft.impl.client.C
|
|||||||
* @param message The messsge to convert.
|
* @param message The messsge to convert.
|
||||||
* @return The converted message.
|
* @return The converted message.
|
||||||
*/
|
*/
|
||||||
Packet<ServerGamePacketListener> createPacket(NetworkMessage<ServerNetworkContext> message);
|
Packet<ServerCommonPacketListener> createPacket(NetworkMessage<ServerNetworkContext> message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a {@link BakedModel}, using any loader-specific hooks.
|
* Render a {@link BakedModel}, using any loader-specific hooks.
|
||||||
|
@ -125,10 +125,10 @@ public class SpriteRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static float u(TextureAtlasSprite sprite, int x, int width) {
|
public static float u(TextureAtlasSprite sprite, int x, int width) {
|
||||||
return sprite.getU((double) x / width * 16);
|
return sprite.getU((float) x / width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float v(TextureAtlasSprite sprite, int y, int height) {
|
public static float v(TextureAtlasSprite sprite, int y, int height) {
|
||||||
return sprite.getV((double) y / height * 16);
|
return sprite.getV((float) y / height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import com.mojang.blaze3d.platform.MemoryTracker;
|
|||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.*;
|
import com.mojang.blaze3d.vertex.*;
|
||||||
import com.mojang.math.Axis;
|
import com.mojang.math.Axis;
|
||||||
|
import dan200.computercraft.annotations.ForgeOverride;
|
||||||
import dan200.computercraft.client.FrameInfo;
|
import dan200.computercraft.client.FrameInfo;
|
||||||
import dan200.computercraft.client.integration.ShaderMod;
|
import dan200.computercraft.client.integration.ShaderMod;
|
||||||
import dan200.computercraft.client.render.RenderTypes;
|
import dan200.computercraft.client.render.RenderTypes;
|
||||||
@ -25,6 +26,7 @@ import dan200.computercraft.shared.util.DirectionUtil;
|
|||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
import org.joml.Matrix3f;
|
import org.joml.Matrix3f;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
@ -255,6 +257,11 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
|||||||
return Config.monitorDistance;
|
return Config.monitorDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ForgeOverride
|
||||||
|
public AABB getRenderBoundingBox(MonitorBlockEntity monitor) {
|
||||||
|
return monitor.getRenderBoundingBox();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if any monitors were rendered this frame.
|
* Determine if any monitors were rendered this frame.
|
||||||
*
|
*
|
||||||
|
@ -10,6 +10,7 @@ import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.shared.turtle.upgrades.TurtleModem;
|
import dan200.computercraft.shared.turtle.upgrades.TurtleModem;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ public class TurtleModemModeller implements TurtleUpgradeModeller<TurtleModem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TransformedModel getModel(TurtleModem upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
public TransformedModel getModel(TurtleModem upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, CompoundTag data) {
|
||||||
var active = false;
|
var active = false;
|
||||||
if (turtle != null) {
|
if (turtle != null) {
|
||||||
var turtleNBT = turtle.getUpgradeNBTData(side);
|
var turtleNBT = turtle.getUpgradeNBTData(side);
|
||||||
|
@ -10,15 +10,13 @@ import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
|||||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
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 dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.impl.PlatformHelper;
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import dan200.computercraft.impl.TurtleUpgrades;
|
import dan200.computercraft.impl.TurtleUpgrades;
|
||||||
import dan200.computercraft.impl.UpgradeManager;
|
import dan200.computercraft.impl.UpgradeManager;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
@ -29,12 +27,10 @@ import java.util.stream.Stream;
|
|||||||
* A registry of {@link TurtleUpgradeModeller}s.
|
* A registry of {@link TurtleUpgradeModeller}s.
|
||||||
*/
|
*/
|
||||||
public final class TurtleUpgradeModellers {
|
public final class TurtleUpgradeModellers {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TurtleUpgradeModellers.class);
|
private static final TurtleUpgradeModeller<ITurtleUpgrade> NULL_TURTLE_MODELLER = (upgrade, turtle, side, data) ->
|
||||||
|
|
||||||
private static final TurtleUpgradeModeller<ITurtleUpgrade> NULL_TURTLE_MODELLER = (upgrade, turtle, side) ->
|
|
||||||
new TransformedModel(Minecraft.getInstance().getModelManager().getMissingModel(), Transformation.identity());
|
new TransformedModel(Minecraft.getInstance().getModelManager().getMissingModel(), Transformation.identity());
|
||||||
|
|
||||||
private static final Map<TurtleUpgradeSerialiser<?>, TurtleUpgradeModeller<?>> turtleModels = new ConcurrentHashMap<>();
|
private static final Map<UpgradeSerialiser<? extends ITurtleUpgrade>, TurtleUpgradeModeller<?>> turtleModels = new ConcurrentHashMap<>();
|
||||||
private static volatile boolean fetchedModels;
|
private static volatile boolean fetchedModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,15 +44,12 @@ public final class TurtleUpgradeModellers {
|
|||||||
private TurtleUpgradeModellers() {
|
private TurtleUpgradeModellers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends ITurtleUpgrade> void register(TurtleUpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller) {
|
public static <T extends ITurtleUpgrade> void register(UpgradeSerialiser<T> serialiser, TurtleUpgradeModeller<T> modeller) {
|
||||||
if (fetchedModels) {
|
if (fetchedModels) {
|
||||||
// TODO(1.20.4): Replace with an error.
|
throw new IllegalStateException(String.format(
|
||||||
LOG.warn(
|
"Turtle upgrade serialiser %s must be registered before models are baked.",
|
||||||
"Turtle upgrade serialiser {} was registered too late, its models may not be loaded correctly. If you are " +
|
RegistryHelper.getKeyOrThrow(RegistryHelper.getRegistry(ITurtleUpgrade.serialiserRegistryKey()), serialiser)
|
||||||
"the mod author, you may be using a deprecated API - see https://github.com/cc-tweaked/CC-Tweaked/pull/1684 " +
|
));
|
||||||
"for further information.",
|
|
||||||
PlatformHelper.get().getRegistryKey(TurtleUpgradeSerialiser.registryId(), serialiser)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (turtleModels.putIfAbsent(serialiser, modeller) != null) {
|
if (turtleModels.putIfAbsent(serialiser, modeller) != null) {
|
||||||
@ -67,13 +60,13 @@ public final class TurtleUpgradeModellers {
|
|||||||
public static TransformedModel getModel(ITurtleUpgrade upgrade, ITurtleAccess access, TurtleSide side) {
|
public static TransformedModel getModel(ITurtleUpgrade upgrade, ITurtleAccess access, TurtleSide side) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
|
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
|
||||||
return modeller.getModel(upgrade, access, side);
|
return modeller.getModel(upgrade, access, side, access.getUpgradeNBTData(side));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransformedModel getModel(ITurtleUpgrade upgrade, CompoundTag data, TurtleSide side) {
|
public static TransformedModel getModel(ITurtleUpgrade upgrade, CompoundTag data, TurtleSide side) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
|
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
|
||||||
return modeller.getModel(upgrade, data, side);
|
return modeller.getModel(upgrade, null, side, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TurtleUpgradeModeller<?> getModeller(ITurtleUpgrade upgradeA) {
|
private static TurtleUpgradeModeller<?> getModeller(ITurtleUpgrade upgradeA) {
|
||||||
|
@ -17,13 +17,12 @@ import dan200.computercraft.shared.computer.metrics.basic.Aggregate;
|
|||||||
import dan200.computercraft.shared.computer.metrics.basic.AggregatedMetric;
|
import dan200.computercraft.shared.computer.metrics.basic.AggregatedMetric;
|
||||||
import dan200.computercraft.shared.config.ConfigFile;
|
import dan200.computercraft.shared.config.ConfigFile;
|
||||||
import dan200.computercraft.shared.config.ConfigSpec;
|
import dan200.computercraft.shared.config.ConfigSpec;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.data.CachedOutput;
|
import net.minecraft.data.CachedOutput;
|
||||||
import net.minecraft.data.DataProvider;
|
import net.minecraft.data.DataProvider;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
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 java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -272,12 +271,12 @@ public final class LanguageProvider implements DataProvider {
|
|||||||
|
|
||||||
private Stream<String> getExpectedKeys() {
|
private Stream<String> getExpectedKeys() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
RegistryWrappers.BLOCKS.stream()
|
BuiltInRegistries.BLOCK.holders()
|
||||||
.filter(x -> RegistryWrappers.BLOCKS.getKey(x).getNamespace().equals(ComputerCraftAPI.MOD_ID))
|
.filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID))
|
||||||
.map(Block::getDescriptionId),
|
.map(x -> x.value().getDescriptionId()),
|
||||||
RegistryWrappers.ITEMS.stream()
|
BuiltInRegistries.ITEM.holders()
|
||||||
.filter(x -> RegistryWrappers.ITEMS.getKey(x).getNamespace().equals(ComputerCraftAPI.MOD_ID))
|
.filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID))
|
||||||
.map(Item::getDescriptionId),
|
.map(x -> x.value().getDescriptionId()),
|
||||||
turtleUpgrades.getGeneratedUpgrades().stream().map(UpgradeBase::getUnlocalisedAdjective),
|
turtleUpgrades.getGeneratedUpgrades().stream().map(UpgradeBase::getUnlocalisedAdjective),
|
||||||
pocketUpgrades.getGeneratedUpgrades().stream().map(UpgradeBase::getUnlocalisedAdjective),
|
pocketUpgrades.getGeneratedUpgrades().stream().map(UpgradeBase::getUnlocalisedAdjective),
|
||||||
Metric.metrics().values().stream().map(x -> AggregatedMetric.TRANSLATION_PREFIX + x.name() + ".name"),
|
Metric.metrics().values().stream().map(x -> AggregatedMetric.TRANSLATION_PREFIX + x.name() + ".name"),
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
package dan200.computercraft.data;
|
package dan200.computercraft.data;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.data.CachedOutput;
|
import net.minecraft.data.CachedOutput;
|
||||||
import net.minecraft.data.DataProvider;
|
import net.minecraft.data.DataProvider;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
@ -67,7 +68,7 @@ public class ModelProvider implements DataProvider {
|
|||||||
blocks.accept(new BlockModelGenerators(addBlockState, addModel, explicitItems::add));
|
blocks.accept(new BlockModelGenerators(addBlockState, addModel, explicitItems::add));
|
||||||
items.accept(new ItemModelGenerators(addModel));
|
items.accept(new ItemModelGenerators(addModel));
|
||||||
|
|
||||||
for (var block : RegistryWrappers.BLOCKS) {
|
for (var block : BuiltInRegistries.BLOCK) {
|
||||||
if (!blockStates.containsKey(block)) continue;
|
if (!blockStates.containsKey(block)) continue;
|
||||||
|
|
||||||
var item = Item.BY_BLOCK.get(block);
|
var item = Item.BY_BLOCK.get(block);
|
||||||
@ -80,7 +81,7 @@ public class ModelProvider implements DataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<CompletableFuture<?>> futures = new ArrayList<>();
|
List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||||
saveCollection(output, futures, blockStates, x -> blockStatePath.json(RegistryWrappers.BLOCKS.getKey(x)));
|
saveCollection(output, futures, blockStates, x -> blockStatePath.json(RegistryHelper.getKeyOrThrow(BuiltInRegistries.BLOCK, x)));
|
||||||
saveCollection(output, futures, models, modelPath::json);
|
saveCollection(output, futures, models, modelPath::json);
|
||||||
return Util.sequenceFailFast(futures);
|
return Util.sequenceFailFast(futures);
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
package dan200.computercraft.data;
|
package dan200.computercraft.data;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ class PocketUpgradeProvider extends PocketUpgradeDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addUpgrades(Consumer<Upgrade<PocketUpgradeSerialiser<?>>> addUpgrade) {
|
protected void addUpgrades(Consumer<Upgrade<UpgradeSerialiser<? extends IPocketUpgrade>>> addUpgrade) {
|
||||||
addUpgrade.accept(simpleWithCustomItem(id("speaker"), PocketUpgradeSerialisers.SPEAKER.get(), Items.SPEAKER.get()));
|
addUpgrade.accept(simpleWithCustomItem(id("speaker"), PocketUpgradeSerialisers.SPEAKER.get(), Items.SPEAKER.get()));
|
||||||
simpleWithCustomItem(id("wireless_modem_normal"), PocketUpgradeSerialisers.WIRELESS_MODEM_NORMAL.get(), Items.WIRELESS_MODEM_NORMAL.get()).add(addUpgrade);
|
simpleWithCustomItem(id("wireless_modem_normal"), PocketUpgradeSerialisers.WIRELESS_MODEM_NORMAL.get(), Items.WIRELESS_MODEM_NORMAL.get()).add(addUpgrade);
|
||||||
simpleWithCustomItem(id("wireless_modem_advanced"), PocketUpgradeSerialisers.WIRELESS_MODEM_ADVANCED.get(), Items.WIRELESS_MODEM_ADVANCED.get()).add(addUpgrade);
|
simpleWithCustomItem(id("wireless_modem_advanced"), PocketUpgradeSerialisers.WIRELESS_MODEM_ADVANCED.get(), Items.WIRELESS_MODEM_ADVANCED.get()).add(addUpgrade);
|
||||||
|
@ -5,34 +5,56 @@
|
|||||||
package dan200.computercraft.data;
|
package dan200.computercraft.data;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import com.mojang.serialization.JsonOps;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||||
import dan200.computercraft.core.util.Colour;
|
import dan200.computercraft.core.util.Colour;
|
||||||
|
import dan200.computercraft.data.recipe.ShapedSpecBuilder;
|
||||||
|
import dan200.computercraft.data.recipe.ShapelessSpecBuilder;
|
||||||
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.common.IColouredItem;
|
import dan200.computercraft.shared.common.ClearColourRecipe;
|
||||||
|
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||||
|
import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe;
|
||||||
|
import dan200.computercraft.shared.media.items.DiskItem;
|
||||||
|
import dan200.computercraft.shared.media.recipes.DiskRecipe;
|
||||||
|
import dan200.computercraft.shared.media.recipes.PrintoutRecipe;
|
||||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||||
import dan200.computercraft.shared.platform.RecipeIngredients;
|
import dan200.computercraft.shared.platform.RecipeIngredients;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
|
||||||
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
||||||
|
import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe;
|
||||||
|
import dan200.computercraft.shared.recipe.CustomShapelessRecipe;
|
||||||
|
import dan200.computercraft.shared.recipe.ImpostorShapedRecipe;
|
||||||
|
import dan200.computercraft.shared.recipe.ImpostorShapelessRecipe;
|
||||||
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
||||||
|
import dan200.computercraft.shared.turtle.recipes.TurtleOverlayRecipe;
|
||||||
|
import dan200.computercraft.shared.turtle.recipes.TurtleRecipe;
|
||||||
|
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
|
||||||
import dan200.computercraft.shared.util.ColourUtils;
|
import dan200.computercraft.shared.util.ColourUtils;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.advancements.Criterion;
|
||||||
import net.minecraft.advancements.critereon.InventoryChangeTrigger;
|
import net.minecraft.advancements.critereon.InventoryChangeTrigger;
|
||||||
import net.minecraft.advancements.critereon.ItemPredicate;
|
import net.minecraft.advancements.critereon.ItemPredicate;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
import net.minecraft.data.recipes.*;
|
import net.minecraft.data.recipes.RecipeCategory;
|
||||||
|
import net.minecraft.data.recipes.RecipeOutput;
|
||||||
|
import net.minecraft.data.recipes.ShapedRecipeBuilder;
|
||||||
|
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.util.GsonHelper;
|
import net.minecraft.util.GsonHelper;
|
||||||
import net.minecraft.world.item.*;
|
import net.minecraft.world.item.*;
|
||||||
|
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.item.crafting.ShapedRecipe;
|
import net.minecraft.world.item.crafting.Recipe;
|
||||||
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
|
||||||
import net.minecraft.world.level.ItemLike;
|
import net.minecraft.world.level.ItemLike;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
|
||||||
@ -43,7 +65,7 @@ import java.util.function.Consumer;
|
|||||||
import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER;
|
import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER;
|
||||||
import static dan200.computercraft.api.ComputerCraftTags.Items.WIRED_MODEM;
|
import static dan200.computercraft.api.ComputerCraftTags.Items.WIRED_MODEM;
|
||||||
|
|
||||||
class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
||||||
private final RecipeIngredients ingredients = PlatformHelper.get().getRecipeIngredients();
|
private final RecipeIngredients ingredients = PlatformHelper.get().getRecipeIngredients();
|
||||||
private final TurtleUpgradeDataProvider turtleUpgrades;
|
private final TurtleUpgradeDataProvider turtleUpgrades;
|
||||||
private final PocketUpgradeDataProvider pocketUpgrades;
|
private final PocketUpgradeDataProvider pocketUpgrades;
|
||||||
@ -55,40 +77,37 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildRecipes(Consumer<FinishedRecipe> add) {
|
public void buildRecipes(RecipeOutput add) {
|
||||||
basicRecipes(add);
|
basicRecipes(add);
|
||||||
diskColours(add);
|
diskColours(add);
|
||||||
pocketUpgrades(add);
|
pocketUpgrades(add);
|
||||||
turtleUpgrades(add);
|
turtleUpgrades(add);
|
||||||
turtleOverlays(add);
|
turtleOverlays(add);
|
||||||
|
|
||||||
addSpecial(add, ModRegistry.RecipeSerializers.PRINTOUT.get());
|
addSpecial(add, new PrintoutRecipe(CraftingBookCategory.MISC));
|
||||||
addSpecial(add, ModRegistry.RecipeSerializers.DISK.get());
|
addSpecial(add, new DiskRecipe(CraftingBookCategory.MISC));
|
||||||
addSpecial(add, ModRegistry.RecipeSerializers.DYEABLE_ITEM.get());
|
addSpecial(add, new ColourableRecipe(CraftingBookCategory.MISC));
|
||||||
addSpecial(add, ModRegistry.RecipeSerializers.DYEABLE_ITEM_CLEAR.get());
|
addSpecial(add, new ClearColourRecipe(CraftingBookCategory.MISC));
|
||||||
addSpecial(add, ModRegistry.RecipeSerializers.TURTLE_UPGRADE.get());
|
addSpecial(add, new TurtleUpgradeRecipe(CraftingBookCategory.MISC));
|
||||||
addSpecial(add, ModRegistry.RecipeSerializers.POCKET_COMPUTER_UPGRADE.get());
|
addSpecial(add, new PocketComputerUpgradeRecipe(CraftingBookCategory.MISC));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a crafting recipe for a disk of every dye colour.
|
* Register a crafting recipe for a disk of every dye colour.
|
||||||
*
|
*
|
||||||
* @param add The callback to add recipes.
|
* @param output The callback to add recipes.
|
||||||
*/
|
*/
|
||||||
private void diskColours(Consumer<FinishedRecipe> add) {
|
private void diskColours(RecipeOutput output) {
|
||||||
for (var colour : Colour.VALUES) {
|
for (var colour : Colour.VALUES) {
|
||||||
ShapelessRecipeBuilder
|
ShapelessSpecBuilder
|
||||||
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.DISK.get())
|
.shapeless(RecipeCategory.REDSTONE, DiskItem.createFromIDAndColour(-1, null, colour.getHex()))
|
||||||
.requires(ingredients.redstone())
|
.requires(ingredients.redstone())
|
||||||
.requires(Items.PAPER)
|
.requires(Items.PAPER)
|
||||||
.requires(DyeItem.byColor(ofColour(colour)))
|
.requires(DyeItem.byColor(ofColour(colour)))
|
||||||
.group("computercraft:disk")
|
.group("computercraft:disk")
|
||||||
.unlockedBy("has_drive", inventoryChange(ModRegistry.Blocks.DISK_DRIVE.get()))
|
.unlockedBy("has_drive", inventoryChange(ModRegistry.Blocks.DISK_DRIVE.get()))
|
||||||
.save(
|
.build(ImpostorShapelessRecipe::new)
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPELESS.get(), add)
|
.save(output, new ResourceLocation(ComputerCraftAPI.MOD_ID, "disk_" + (colour.ordinal() + 1)));
|
||||||
.withResultTag(x -> x.putInt(IColouredItem.NBT_COLOUR, colour.getHex())),
|
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "disk_" + (colour.ordinal() + 1))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,23 +120,22 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
*
|
*
|
||||||
* @param add The callback to add recipes.
|
* @param add The callback to add recipes.
|
||||||
*/
|
*/
|
||||||
private void turtleUpgrades(Consumer<FinishedRecipe> add) {
|
private void turtleUpgrades(RecipeOutput add) {
|
||||||
for (var turtleItem : turtleItems()) {
|
for (var turtleItem : turtleItems()) {
|
||||||
var base = turtleItem.create(-1, null, -1, null, null, 0, null);
|
var base = turtleItem.create(-1, null, -1, null, null, 0, null);
|
||||||
var name = RegistryWrappers.ITEMS.getKey(turtleItem);
|
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem);
|
||||||
|
|
||||||
for (var upgrade : turtleUpgrades.getGeneratedUpgrades()) {
|
for (var upgrade : turtleUpgrades.getGeneratedUpgrades()) {
|
||||||
var result = turtleItem.create(-1, null, -1, null, UpgradeData.ofDefault(upgrade), -1, null);
|
ShapedSpecBuilder
|
||||||
ShapedRecipeBuilder
|
.shaped(RecipeCategory.REDSTONE, turtleItem.create(-1, null, -1, null, UpgradeData.ofDefault(upgrade), -1, null))
|
||||||
.shaped(RecipeCategory.REDSTONE, result.getItem())
|
|
||||||
.group(name.toString())
|
.group(name.toString())
|
||||||
.pattern("#T")
|
.pattern("#T")
|
||||||
.define('T', base.getItem())
|
.define('T', base.getItem())
|
||||||
.define('#', upgrade.getCraftingItem().getItem())
|
.define('#', upgrade.getCraftingItem().getItem())
|
||||||
.unlockedBy("has_items",
|
.unlockedBy("has_items", inventoryChange(base.getItem(), upgrade.getCraftingItem().getItem()))
|
||||||
inventoryChange(base.getItem(), upgrade.getCraftingItem().getItem()))
|
.build(ImpostorShapedRecipe::new)
|
||||||
.save(
|
.save(
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPED.get(), add).withResultTag(result.getTag()),
|
add,
|
||||||
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -133,31 +151,30 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
*
|
*
|
||||||
* @param add The callback to add recipes.
|
* @param add The callback to add recipes.
|
||||||
*/
|
*/
|
||||||
private void pocketUpgrades(Consumer<FinishedRecipe> add) {
|
private void pocketUpgrades(RecipeOutput add) {
|
||||||
for (var pocket : pocketComputerItems()) {
|
for (var pocket : pocketComputerItems()) {
|
||||||
var base = pocket.create(-1, null, -1, null);
|
var base = pocket.create(-1, null, -1, null);
|
||||||
var name = RegistryWrappers.ITEMS.getKey(pocket).withPath(x -> x.replace("pocket_computer_", "pocket_"));
|
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, pocket).withPath(x -> x.replace("pocket_computer_", "pocket_"));
|
||||||
|
|
||||||
for (var upgrade : pocketUpgrades.getGeneratedUpgrades()) {
|
for (var upgrade : pocketUpgrades.getGeneratedUpgrades()) {
|
||||||
var result = pocket.create(-1, null, -1, UpgradeData.ofDefault(upgrade));
|
ShapedSpecBuilder
|
||||||
ShapedRecipeBuilder
|
.shaped(RecipeCategory.REDSTONE, pocket.create(-1, null, -1, UpgradeData.ofDefault(upgrade)))
|
||||||
.shaped(RecipeCategory.REDSTONE, result.getItem())
|
|
||||||
.group(name.toString())
|
.group(name.toString())
|
||||||
.pattern("#")
|
.pattern("#")
|
||||||
.pattern("P")
|
.pattern("P")
|
||||||
.define('P', base.getItem())
|
.define('P', base.getItem())
|
||||||
.define('#', upgrade.getCraftingItem().getItem())
|
.define('#', upgrade.getCraftingItem().getItem())
|
||||||
.unlockedBy("has_items",
|
.unlockedBy("has_items", inventoryChange(base.getItem(), upgrade.getCraftingItem().getItem()))
|
||||||
inventoryChange(base.getItem(), upgrade.getCraftingItem().getItem()))
|
.build(ImpostorShapedRecipe::new)
|
||||||
.save(
|
.save(
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPED.get(), add).withResultTag(result.getTag()),
|
add,
|
||||||
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void turtleOverlays(Consumer<FinishedRecipe> add) {
|
private void turtleOverlays(RecipeOutput add) {
|
||||||
turtleOverlay(add, "turtle_trans_overlay", x -> x
|
turtleOverlay(add, "turtle_trans_overlay", x -> x
|
||||||
.unlockedBy("has_dye", inventoryChange(itemPredicate(ingredients.dye())))
|
.unlockedBy("has_dye", inventoryChange(itemPredicate(ingredients.dye())))
|
||||||
.requires(ColourUtils.getDyeTag(DyeColor.LIGHT_BLUE))
|
.requires(ColourUtils.getDyeTag(DyeColor.LIGHT_BLUE))
|
||||||
@ -178,28 +195,24 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void turtleOverlay(Consumer<FinishedRecipe> add, String overlay, Consumer<ShapelessRecipeBuilder> build) {
|
private void turtleOverlay(RecipeOutput add, String overlay, Consumer<ShapelessSpecBuilder> build) {
|
||||||
for (var turtleItem : turtleItems()) {
|
for (var turtleItem : turtleItems()) {
|
||||||
var base = turtleItem.create(-1, null, -1, null, null, 0, null);
|
var base = turtleItem.create(-1, null, -1, null, null, 0, null);
|
||||||
var name = RegistryWrappers.ITEMS.getKey(turtleItem);
|
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem);
|
||||||
|
|
||||||
var builder = ShapelessRecipeBuilder.shapeless(RecipeCategory.REDSTONE, base.getItem())
|
var builder = ShapelessSpecBuilder.shapeless(RecipeCategory.REDSTONE, base)
|
||||||
.group(name.withSuffix("_overlay").toString())
|
.group(name.withSuffix("_overlay").toString())
|
||||||
.unlockedBy("has_turtle", inventoryChange(base.getItem()));
|
.unlockedBy("has_turtle", inventoryChange(base.getItem()));
|
||||||
build.accept(builder);
|
build.accept(builder);
|
||||||
builder
|
builder
|
||||||
.requires(base.getItem())
|
.requires(base.getItem())
|
||||||
.save(
|
.build(s -> new TurtleOverlayRecipe(s, new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/" + overlay)))
|
||||||
RecipeWrapper
|
.save(add, name.withSuffix("_overlays/" + overlay));
|
||||||
.wrap(ModRegistry.RecipeSerializers.TURTLE_OVERLAY.get(), add)
|
|
||||||
.withExtraData(x -> x.addProperty("overlay", new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/" + overlay).toString())),
|
|
||||||
name.withSuffix("_overlays/" + overlay)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void basicRecipes(Consumer<FinishedRecipe> add) {
|
private void basicRecipes(RecipeOutput add) {
|
||||||
ShapedRecipeBuilder
|
ShapedRecipeBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.CABLE.get(), 6)
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.CABLE.get(), 6)
|
||||||
.pattern(" # ")
|
.pattern(" # ")
|
||||||
@ -233,7 +246,7 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.unlockedBy("has_components", inventoryChange(itemPredicate(ingredients.redstone()), itemPredicate(ingredients.goldIngot())))
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ingredients.redstone()), itemPredicate(ingredients.goldIngot())))
|
||||||
.save(add);
|
.save(add);
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedSpecBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get())
|
||||||
.pattern("###")
|
.pattern("###")
|
||||||
.pattern("#C#")
|
.pattern("#C#")
|
||||||
@ -241,10 +254,8 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.define('#', ingredients.goldIngot())
|
.define('#', ingredients.goldIngot())
|
||||||
.define('C', ModRegistry.Items.COMPUTER_NORMAL.get())
|
.define('C', ModRegistry.Items.COMPUTER_NORMAL.get())
|
||||||
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
||||||
.save(
|
.build(ComputerUpgradeRecipe::new)
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.COMPUTER_UPGRADE.get(), add),
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer_advanced_upgrade"));
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer_advanced_upgrade")
|
|
||||||
);
|
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedRecipeBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_COMMAND.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_COMMAND.get())
|
||||||
@ -257,7 +268,7 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.unlockedBy("has_components", inventoryChange(Blocks.COMMAND_BLOCK))
|
.unlockedBy("has_components", inventoryChange(Blocks.COMMAND_BLOCK))
|
||||||
.save(add);
|
.save(add);
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedSpecBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_NORMAL.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_NORMAL.get())
|
||||||
.pattern("###")
|
.pattern("###")
|
||||||
.pattern("#C#")
|
.pattern("#C#")
|
||||||
@ -266,9 +277,10 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.define('C', ModRegistry.Items.COMPUTER_NORMAL.get())
|
.define('C', ModRegistry.Items.COMPUTER_NORMAL.get())
|
||||||
.define('I', ingredients.woodenChest())
|
.define('I', ingredients.woodenChest())
|
||||||
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get()))
|
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get()))
|
||||||
.save(RecipeWrapper.wrap(ModRegistry.RecipeSerializers.TURTLE.get(), add));
|
.buildOrThrow(TurtleRecipe::of)
|
||||||
|
.save(add);
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedSpecBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
|
||||||
.pattern("###")
|
.pattern("###")
|
||||||
.pattern("#C#")
|
.pattern("#C#")
|
||||||
@ -277,9 +289,10 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.define('C', ModRegistry.Items.COMPUTER_ADVANCED.get())
|
.define('C', ModRegistry.Items.COMPUTER_ADVANCED.get())
|
||||||
.define('I', ingredients.woodenChest())
|
.define('I', ingredients.woodenChest())
|
||||||
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get()))
|
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get()))
|
||||||
.save(RecipeWrapper.wrap(ModRegistry.RecipeSerializers.TURTLE.get(), add));
|
.buildOrThrow(TurtleRecipe::of)
|
||||||
|
.save(add);
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedSpecBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
|
||||||
.pattern("###")
|
.pattern("###")
|
||||||
.pattern("#C#")
|
.pattern("#C#")
|
||||||
@ -288,10 +301,8 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.define('C', ModRegistry.Items.TURTLE_NORMAL.get())
|
.define('C', ModRegistry.Items.TURTLE_NORMAL.get())
|
||||||
.define('B', ingredients.goldBlock())
|
.define('B', ingredients.goldBlock())
|
||||||
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.TURTLE_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.TURTLE_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
||||||
.save(
|
.build(ComputerUpgradeRecipe::new)
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.COMPUTER_UPGRADE.get(), add),
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_advanced_upgrade"));
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_advanced_upgrade")
|
|
||||||
);
|
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedRecipeBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.DISK_DRIVE.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.DISK_DRIVE.get())
|
||||||
@ -347,7 +358,7 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.unlockedBy("has_apple", inventoryChange(Items.GOLDEN_APPLE))
|
.unlockedBy("has_apple", inventoryChange(Items.GOLDEN_APPLE))
|
||||||
.save(add);
|
.save(add);
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedSpecBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get())
|
||||||
.pattern("###")
|
.pattern("###")
|
||||||
.pattern("#C#")
|
.pattern("#C#")
|
||||||
@ -355,10 +366,8 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.define('#', ingredients.goldIngot())
|
.define('#', ingredients.goldIngot())
|
||||||
.define('C', ModRegistry.Items.POCKET_COMPUTER_NORMAL.get())
|
.define('C', ModRegistry.Items.POCKET_COMPUTER_NORMAL.get())
|
||||||
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
||||||
.save(
|
.build(ComputerUpgradeRecipe::new)
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.COMPUTER_UPGRADE.get(), add),
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_computer_advanced_upgrade"));
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_computer_advanced_upgrade")
|
|
||||||
);
|
|
||||||
|
|
||||||
ShapedRecipeBuilder
|
ShapedRecipeBuilder
|
||||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.PRINTER.get())
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.PRINTER.get())
|
||||||
@ -425,57 +434,53 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.unlockedBy("has_wireless", inventoryChange(ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get()))
|
.unlockedBy("has_wireless", inventoryChange(ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get()))
|
||||||
.save(add);
|
.save(add);
|
||||||
|
|
||||||
ShapelessRecipeBuilder
|
ShapelessSpecBuilder
|
||||||
.shapeless(RecipeCategory.DECORATIONS, Items.PLAYER_HEAD)
|
.shapeless(RecipeCategory.DECORATIONS, playerHead("Cloudhunter", "6d074736-b1e9-4378-a99b-bd8777821c9c"))
|
||||||
.requires(ingredients.head())
|
.requires(ingredients.head())
|
||||||
.requires(ModRegistry.Items.MONITOR_NORMAL.get())
|
.requires(ModRegistry.Items.MONITOR_NORMAL.get())
|
||||||
.unlockedBy("has_monitor", inventoryChange(ModRegistry.Items.MONITOR_NORMAL.get()))
|
.unlockedBy("has_monitor", inventoryChange(ModRegistry.Items.MONITOR_NORMAL.get()))
|
||||||
.save(
|
.build(CustomShapelessRecipe::new)
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.SHAPELESS.get(), add)
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_cloudy"));
|
||||||
.withResultTag(playerHead("Cloudhunter", "6d074736-b1e9-4378-a99b-bd8777821c9c")),
|
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_cloudy")
|
|
||||||
);
|
|
||||||
|
|
||||||
ShapelessRecipeBuilder
|
ShapelessSpecBuilder
|
||||||
.shapeless(RecipeCategory.DECORATIONS, Items.PLAYER_HEAD)
|
.shapeless(RecipeCategory.DECORATIONS, playerHead("dan200", "f3c8d69b-0776-4512-8434-d1b2165909eb"))
|
||||||
.requires(ingredients.head())
|
.requires(ingredients.head())
|
||||||
.requires(ModRegistry.Items.COMPUTER_ADVANCED.get())
|
.requires(ModRegistry.Items.COMPUTER_ADVANCED.get())
|
||||||
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_ADVANCED.get()))
|
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_ADVANCED.get()))
|
||||||
.save(
|
.build(CustomShapelessRecipe::new)
|
||||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.SHAPELESS.get(), add)
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_dan200"));
|
||||||
.withResultTag(playerHead("dan200", "f3c8d69b-0776-4512-8434-d1b2165909eb")),
|
|
||||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_dan200")
|
|
||||||
);
|
|
||||||
|
|
||||||
ShapelessRecipeBuilder
|
ShapelessSpecBuilder
|
||||||
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_PAGES.get())
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_PAGES.get())
|
||||||
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 2)
|
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 2)
|
||||||
.requires(ingredients.string())
|
.requires(ingredients.string())
|
||||||
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
||||||
.save(RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPELESS.get(), add));
|
.build(ImpostorShapelessRecipe::new)
|
||||||
|
.save(add);
|
||||||
|
|
||||||
ShapelessRecipeBuilder
|
ShapelessSpecBuilder
|
||||||
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_BOOK.get())
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_BOOK.get())
|
||||||
.requires(ingredients.leather())
|
.requires(ingredients.leather())
|
||||||
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 1)
|
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 1)
|
||||||
.requires(ingredients.string())
|
.requires(ingredients.string())
|
||||||
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
||||||
.save(RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPELESS.get(), add));
|
.build(ImpostorShapelessRecipe::new)
|
||||||
|
.save(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DyeColor ofColour(Colour colour) {
|
private static DyeColor ofColour(Colour colour) {
|
||||||
return DyeColor.byId(15 - colour.ordinal());
|
return DyeColor.byId(15 - colour.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InventoryChangeTrigger.TriggerInstance inventoryChange(TagKey<Item> stack) {
|
private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryChange(TagKey<Item> stack) {
|
||||||
return InventoryChangeTrigger.TriggerInstance.hasItems(itemPredicate(stack));
|
return InventoryChangeTrigger.TriggerInstance.hasItems(itemPredicate(stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InventoryChangeTrigger.TriggerInstance inventoryChange(ItemLike... stack) {
|
private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryChange(ItemLike... stack) {
|
||||||
return InventoryChangeTrigger.TriggerInstance.hasItems(stack);
|
return InventoryChangeTrigger.TriggerInstance.hasItems(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InventoryChangeTrigger.TriggerInstance inventoryChange(ItemPredicate... items) {
|
private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryChange(ItemPredicate... items) {
|
||||||
return InventoryChangeTrigger.TriggerInstance.hasItems(items);
|
return InventoryChangeTrigger.TriggerInstance.hasItems(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,11 +493,12 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ItemPredicate itemPredicate(Ingredient ingredient) {
|
private static ItemPredicate itemPredicate(Ingredient ingredient) {
|
||||||
var json = ingredient.toJson();
|
var json = Util.getOrThrow(Ingredient.CODEC_NONEMPTY.encodeStart(JsonOps.INSTANCE, ingredient), JsonParseException::new);
|
||||||
if (!(json instanceof JsonObject object)) throw new IllegalStateException("Unknown ingredient " + json);
|
if (!(json instanceof JsonObject object)) throw new IllegalStateException("Unknown ingredient " + json);
|
||||||
|
|
||||||
if (object.has("item")) {
|
if (object.has("item")) {
|
||||||
return itemPredicate(ShapedRecipe.itemFromJson(object));
|
var item = Util.getOrThrow(ItemStack.ITEM_WITH_COUNT_CODEC.parse(JsonOps.INSTANCE, object), JsonParseException::new);
|
||||||
|
return itemPredicate(item.getItem());
|
||||||
} else if (object.has("tag")) {
|
} else if (object.has("tag")) {
|
||||||
return itemPredicate(TagKey.create(Registries.ITEM, new ResourceLocation(GsonHelper.getAsString(object, "tag"))));
|
return itemPredicate(TagKey.create(Registries.ITEM, new ResourceLocation(GsonHelper.getAsString(object, "tag"))));
|
||||||
} else {
|
} else {
|
||||||
@ -500,15 +506,14 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompoundTag playerHead(String name, String uuid) {
|
private static ItemStack playerHead(String name, String uuid) {
|
||||||
|
var item = new ItemStack(Items.PLAYER_HEAD);
|
||||||
var owner = NbtUtils.writeGameProfile(new CompoundTag(), new GameProfile(UUID.fromString(uuid), name));
|
var owner = NbtUtils.writeGameProfile(new CompoundTag(), new GameProfile(UUID.fromString(uuid), name));
|
||||||
|
item.getOrCreateTag().put(PlayerHeadItem.TAG_SKULL_OWNER, owner);
|
||||||
var tag = new CompoundTag();
|
return item;
|
||||||
tag.put(PlayerHeadItem.TAG_SKULL_OWNER, owner);
|
|
||||||
return tag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addSpecial(Consumer<FinishedRecipe> add, SimpleCraftingRecipeSerializer<?> special) {
|
private static void addSpecial(RecipeOutput add, Recipe<?> recipe) {
|
||||||
SpecialRecipeBuilder.special(special).save(add, RegistryWrappers.RECIPE_SERIALIZERS.getKey(special).toString());
|
add.accept(RegistryHelper.getKeyOrThrow(BuiltInRegistries.RECIPE_SERIALIZER, recipe.getSerializer()), recipe, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.data;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import net.minecraft.data.recipes.FinishedRecipe;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.util.GsonHelper;
|
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter for recipes which overrides the serializer and adds custom item NBT.
|
|
||||||
*/
|
|
||||||
final class RecipeWrapper implements Consumer<FinishedRecipe> {
|
|
||||||
private final Consumer<FinishedRecipe> add;
|
|
||||||
private final RecipeSerializer<?> serializer;
|
|
||||||
private final List<Consumer<JsonObject>> extend = new ArrayList<>(0);
|
|
||||||
|
|
||||||
RecipeWrapper(Consumer<FinishedRecipe> add, RecipeSerializer<?> serializer) {
|
|
||||||
this.add = add;
|
|
||||||
this.serializer = serializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RecipeWrapper wrap(RecipeSerializer<?> serializer, Consumer<FinishedRecipe> original) {
|
|
||||||
return new RecipeWrapper(original, serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecipeWrapper withExtraData(Consumer<JsonObject> extra) {
|
|
||||||
extend.add(extra);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecipeWrapper withResultTag(@Nullable CompoundTag resultTag) {
|
|
||||||
if (resultTag == null) return this;
|
|
||||||
|
|
||||||
extend.add(json -> {
|
|
||||||
var object = GsonHelper.getAsJsonObject(json, "result");
|
|
||||||
object.addProperty("nbt", resultTag.toString());
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecipeWrapper withResultTag(Consumer<CompoundTag> resultTag) {
|
|
||||||
var tag = new CompoundTag();
|
|
||||||
resultTag.accept(tag);
|
|
||||||
return withResultTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(FinishedRecipe finishedRecipe) {
|
|
||||||
add.accept(new RecipeImpl(finishedRecipe, serializer, extend));
|
|
||||||
}
|
|
||||||
|
|
||||||
private record RecipeImpl(
|
|
||||||
FinishedRecipe recipe, RecipeSerializer<?> serializer, List<Consumer<JsonObject>> extend
|
|
||||||
) implements FinishedRecipe {
|
|
||||||
@Override
|
|
||||||
public void serializeRecipeData(JsonObject jsonObject) {
|
|
||||||
recipe.serializeRecipeData(jsonObject);
|
|
||||||
for (var extender : extend) extender.accept(jsonObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceLocation getId() {
|
|
||||||
return recipe.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RecipeSerializer<?> getType() {
|
|
||||||
return serializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public JsonObject serializeAdvancement() {
|
|
||||||
return recipe.serializeAdvancement();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public ResourceLocation getAdvancementId() {
|
|
||||||
return recipe.getAdvancementId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,8 +5,9 @@
|
|||||||
package dan200.computercraft.data;
|
package dan200.computercraft.data;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftTags;
|
import dan200.computercraft.api.ComputerCraftTags;
|
||||||
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.data.tags.ItemTagsProvider;
|
import net.minecraft.data.tags.ItemTagsProvider;
|
||||||
import net.minecraft.data.tags.TagsProvider;
|
import net.minecraft.data.tags.TagsProvider;
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
@ -111,9 +112,9 @@ class TagProvider {
|
|||||||
TagAppender<T> tag(TagKey<T> tag);
|
TagAppender<T> tag(TagKey<T> tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record TagAppender<T>(RegistryWrappers.RegistryWrapper<T> registry, TagBuilder builder) {
|
public record TagAppender<T>(Registry<T> registry, TagBuilder builder) {
|
||||||
public TagAppender<T> add(T object) {
|
public TagAppender<T> add(T object) {
|
||||||
builder.addElement(registry.getKey(object));
|
builder.addElement(RegistryHelper.getKeyOrThrow(registry, object));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@ package dan200.computercraft.data;
|
|||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.ComputerCraftTags.Blocks;
|
import dan200.computercraft.api.ComputerCraftTags.Blocks;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ class TurtleUpgradeProvider extends TurtleUpgradeDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addUpgrades(Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) {
|
protected void addUpgrades(Consumer<Upgrade<UpgradeSerialiser<? extends ITurtleUpgrade>>> addUpgrade) {
|
||||||
simpleWithCustomItem(id("speaker"), TurtleSerialisers.SPEAKER.get(), Items.SPEAKER.get()).add(addUpgrade);
|
simpleWithCustomItem(id("speaker"), TurtleSerialisers.SPEAKER.get(), Items.SPEAKER.get()).add(addUpgrade);
|
||||||
simpleWithCustomItem(vanilla("crafting_table"), TurtleSerialisers.WORKBENCH.get(), net.minecraft.world.item.Items.CRAFTING_TABLE).add(addUpgrade);
|
simpleWithCustomItem(vanilla("crafting_table"), TurtleSerialisers.WORKBENCH.get(), net.minecraft.world.item.Items.CRAFTING_TABLE).add(addUpgrade);
|
||||||
simpleWithCustomItem(id("wireless_modem_normal"), TurtleSerialisers.WIRELESS_MODEM_NORMAL.get(), Items.WIRELESS_MODEM_NORMAL.get()).add(addUpgrade);
|
simpleWithCustomItem(id("wireless_modem_normal"), TurtleSerialisers.WIRELESS_MODEM_NORMAL.get(), Items.WIRELESS_MODEM_NORMAL.get()).add(addUpgrade);
|
||||||
|
@ -0,0 +1,129 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.data.recipe;
|
||||||
|
|
||||||
|
import com.mojang.serialization.DataResult;
|
||||||
|
import dan200.computercraft.shared.recipe.RecipeProperties;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.advancements.AdvancementRequirements;
|
||||||
|
import net.minecraft.advancements.AdvancementRewards;
|
||||||
|
import net.minecraft.advancements.Criterion;
|
||||||
|
import net.minecraft.advancements.critereon.RecipeUnlockedTrigger;
|
||||||
|
import net.minecraft.data.recipes.RecipeBuilder;
|
||||||
|
import net.minecraft.data.recipes.RecipeCategory;
|
||||||
|
import net.minecraft.data.recipes.RecipeOutput;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.Recipe;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract base class for creating recipes, in the style of {@link RecipeBuilder}.
|
||||||
|
*
|
||||||
|
* @param <S> The type of this class.
|
||||||
|
* @param <O> The output of this builder.
|
||||||
|
* @see ShapelessSpecBuilder
|
||||||
|
*/
|
||||||
|
public abstract class AbstractRecipeBuilder<S extends AbstractRecipeBuilder<S, O>, O> {
|
||||||
|
private final RecipeCategory category;
|
||||||
|
protected final ItemStack result;
|
||||||
|
private String group = "";
|
||||||
|
private final Map<String, Criterion<?>> criteria = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
protected AbstractRecipeBuilder(RecipeCategory category, ItemStack result) {
|
||||||
|
this.category = category;
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the group for this recipe.
|
||||||
|
*
|
||||||
|
* @param group The new group.
|
||||||
|
* @return This object, for chaining.
|
||||||
|
*/
|
||||||
|
public final S group(String group) {
|
||||||
|
this.group = group;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a criterion to this recipe.
|
||||||
|
*
|
||||||
|
* @param name The name of the criterion.
|
||||||
|
* @param criterion The criterion to add.
|
||||||
|
* @return This object, for chaining.
|
||||||
|
*/
|
||||||
|
public final S unlockedBy(String name, Criterion<?> criterion) {
|
||||||
|
criteria.put(name, criterion);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this builder into the output ({@link O}) object.
|
||||||
|
*
|
||||||
|
* @param properties The properties for this recipe.
|
||||||
|
* @return The built object.
|
||||||
|
*/
|
||||||
|
protected abstract O build(RecipeProperties properties);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this builder into a concrete recipe.
|
||||||
|
*
|
||||||
|
* @param factory The recipe's constructor.
|
||||||
|
* @return The "built" recipe.
|
||||||
|
*/
|
||||||
|
public final FinishedRecipe build(Function<O, Recipe<?>> factory) {
|
||||||
|
var properties = new RecipeProperties(group, RecipeBuilder.determineBookCategory(category), true);
|
||||||
|
return new FinishedRecipe(factory.apply(build(properties)), result.getItem(), category, criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this builder into a concrete recipe.
|
||||||
|
*
|
||||||
|
* @param factory The recipe's constructor.
|
||||||
|
* @return The "built" recipe.
|
||||||
|
*/
|
||||||
|
public final FinishedRecipe buildOrThrow(Function<O, DataResult<? extends Recipe<?>>> factory) {
|
||||||
|
return build(s -> Util.getOrThrow(factory.apply(s), IllegalStateException::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private S self() {
|
||||||
|
return (S) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class FinishedRecipe {
|
||||||
|
private final Recipe<?> recipe;
|
||||||
|
private final Item result;
|
||||||
|
private final RecipeCategory category;
|
||||||
|
private final Map<String, Criterion<?>> criteria;
|
||||||
|
|
||||||
|
private FinishedRecipe(Recipe<?> recipe, Item result, RecipeCategory category, Map<String, Criterion<?>> criteria) {
|
||||||
|
this.recipe = recipe;
|
||||||
|
this.result = result;
|
||||||
|
this.category = category;
|
||||||
|
this.criteria = criteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(RecipeOutput output, ResourceLocation id) {
|
||||||
|
if (criteria.isEmpty()) throw new IllegalStateException("No way of obtaining recipe " + id);
|
||||||
|
var advancement = output.advancement()
|
||||||
|
.addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(id))
|
||||||
|
.rewards(AdvancementRewards.Builder.recipe(id))
|
||||||
|
.requirements(AdvancementRequirements.Strategy.OR);
|
||||||
|
for (var entry : criteria.entrySet()) advancement.addCriterion(entry.getKey(), entry.getValue());
|
||||||
|
|
||||||
|
output.accept(id, recipe, advancement.build(id.withPrefix("recipes/" + category.getFolderName() + "/")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(RecipeOutput output) {
|
||||||
|
save(output, RecipeBuilder.getDefaultRecipeId(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.data.recipe;
|
||||||
|
|
||||||
|
import dan200.computercraft.shared.recipe.RecipeProperties;
|
||||||
|
import dan200.computercraft.shared.recipe.ShapedRecipeSpec;
|
||||||
|
import net.minecraft.data.recipes.RecipeCategory;
|
||||||
|
import net.minecraft.data.recipes.ShapedRecipeBuilder;
|
||||||
|
import net.minecraft.tags.TagKey;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.world.item.crafting.ShapedRecipePattern;
|
||||||
|
import net.minecraft.world.level.ItemLike;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for {@link ShapedRecipeSpec}s, much like {@link ShapedRecipeBuilder}.
|
||||||
|
*/
|
||||||
|
public final class ShapedSpecBuilder extends AbstractRecipeBuilder<ShapedSpecBuilder, ShapedRecipeSpec> {
|
||||||
|
private final List<String> rows = new ArrayList<>();
|
||||||
|
private final Map<Character, Ingredient> key = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
private ShapedSpecBuilder(RecipeCategory category, ItemStack result) {
|
||||||
|
super(category, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShapedSpecBuilder shaped(RecipeCategory category, ItemStack result) {
|
||||||
|
return new ShapedSpecBuilder(category, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShapedSpecBuilder shaped(RecipeCategory category, ItemLike result) {
|
||||||
|
return new ShapedSpecBuilder(category, new ItemStack(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapedSpecBuilder define(char key, Ingredient ingredient) {
|
||||||
|
if (this.key.containsKey(key)) throw new IllegalArgumentException("Symbol '" + key + "' is already defined!");
|
||||||
|
if (key == ' ') throw new IllegalArgumentException("Symbol ' ' (whitespace) is reserved and cannot be defined");
|
||||||
|
|
||||||
|
this.key.put(key, ingredient);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapedSpecBuilder define(char key, TagKey<Item> tag) {
|
||||||
|
return this.define(key, Ingredient.of(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapedSpecBuilder define(char key, ItemLike item) {
|
||||||
|
return this.define(key, Ingredient.of(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapedSpecBuilder pattern(String pattern) {
|
||||||
|
if (!this.rows.isEmpty() && pattern.length() != this.rows.get(0).length()) {
|
||||||
|
throw new IllegalArgumentException("Pattern must be the same width on every line!");
|
||||||
|
} else {
|
||||||
|
this.rows.add(pattern);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ShapedRecipeSpec build(RecipeProperties properties) {
|
||||||
|
return new ShapedRecipeSpec(properties, ShapedRecipePattern.of(key, rows), result);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.data.recipe;
|
||||||
|
|
||||||
|
import dan200.computercraft.shared.recipe.RecipeProperties;
|
||||||
|
import dan200.computercraft.shared.recipe.ShapelessRecipeSpec;
|
||||||
|
import net.minecraft.core.NonNullList;
|
||||||
|
import net.minecraft.data.recipes.RecipeCategory;
|
||||||
|
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
||||||
|
import net.minecraft.tags.TagKey;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.world.level.ItemLike;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for {@link ShapelessRecipeSpec}s, much like {@link ShapelessRecipeBuilder}.
|
||||||
|
*/
|
||||||
|
public final class ShapelessSpecBuilder extends AbstractRecipeBuilder<ShapelessSpecBuilder, ShapelessRecipeSpec> {
|
||||||
|
private final NonNullList<Ingredient> ingredients = NonNullList.create();
|
||||||
|
|
||||||
|
private ShapelessSpecBuilder(RecipeCategory category, ItemStack result) {
|
||||||
|
super(category, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShapelessSpecBuilder shapeless(RecipeCategory category, ItemStack result) {
|
||||||
|
return new ShapelessSpecBuilder(category, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShapelessSpecBuilder shapeless(RecipeCategory category, ItemLike result) {
|
||||||
|
return new ShapelessSpecBuilder(category, new ItemStack(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapelessSpecBuilder requires(Ingredient ingredient, int count) {
|
||||||
|
for (int i = 0; i < count; i++) ingredients.add(ingredient);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapelessSpecBuilder requires(Ingredient ingredient) {
|
||||||
|
return requires(ingredient, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapelessSpecBuilder requires(ItemLike item) {
|
||||||
|
return requires(Ingredient.of(new ItemStack(item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapelessSpecBuilder requires(ItemLike item, int count) {
|
||||||
|
return requires(Ingredient.of(new ItemStack(item)), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapelessSpecBuilder requires(TagKey<Item> item) {
|
||||||
|
return requires(Ingredient.of(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ShapelessRecipeSpec build(RecipeProperties properties) {
|
||||||
|
return new ShapelessRecipeSpec(properties, ingredients, result);
|
||||||
|
}
|
||||||
|
}
|
@ -15,10 +15,11 @@ import dan200.computercraft.api.media.MediaProvider;
|
|||||||
import dan200.computercraft.api.network.PacketNetwork;
|
import dan200.computercraft.api.network.PacketNetwork;
|
||||||
import dan200.computercraft.api.network.wired.WiredElement;
|
import dan200.computercraft.api.network.wired.WiredElement;
|
||||||
import dan200.computercraft.api.network.wired.WiredNode;
|
import dan200.computercraft.api.network.wired.WiredNode;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.redstone.BundledRedstoneProvider;
|
import dan200.computercraft.api.redstone.BundledRedstoneProvider;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.core.filesystem.WritableFileMount;
|
import dan200.computercraft.core.filesystem.WritableFileMount;
|
||||||
import dan200.computercraft.impl.detail.DetailRegistryImpl;
|
import dan200.computercraft.impl.detail.DetailRegistryImpl;
|
||||||
import dan200.computercraft.impl.network.wired.WiredNodeImpl;
|
import dan200.computercraft.impl.network.wired.WiredNodeImpl;
|
||||||
@ -44,8 +45,8 @@ public abstract class AbstractComputerCraftAPI implements ComputerCraftAPIServic
|
|||||||
private final DetailRegistry<ItemStack> itemStackDetails = new DetailRegistryImpl<>(ItemDetails::fillBasic);
|
private final DetailRegistry<ItemStack> itemStackDetails = new DetailRegistryImpl<>(ItemDetails::fillBasic);
|
||||||
private final DetailRegistry<BlockReference> blockDetails = new DetailRegistryImpl<>(BlockDetails::fillBasic);
|
private final DetailRegistry<BlockReference> blockDetails = new DetailRegistryImpl<>(BlockDetails::fillBasic);
|
||||||
|
|
||||||
protected static final ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> turtleUpgradeRegistryId = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade_serialiser"));
|
protected static final ResourceKey<Registry<UpgradeSerialiser<? extends ITurtleUpgrade>>> turtleUpgradeRegistryId = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade_serialiser"));
|
||||||
protected static final ResourceKey<Registry<PocketUpgradeSerialiser<?>>> pocketUpgradeRegistryId = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade_serialiser"));
|
protected static final ResourceKey<Registry<UpgradeSerialiser<? extends IPocketUpgrade>>> pocketUpgradeRegistryId = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade_serialiser"));
|
||||||
|
|
||||||
public static @Nullable InputStream getResourceFile(MinecraftServer server, String domain, String subPath) {
|
public static @Nullable InputStream getResourceFile(MinecraftServer server, String domain, String subPath) {
|
||||||
var manager = server.getResourceManager();
|
var manager = server.getResourceManager();
|
||||||
@ -116,12 +117,12 @@ public abstract class AbstractComputerCraftAPI implements ComputerCraftAPIServic
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> turtleUpgradeRegistryId() {
|
public final ResourceKey<Registry<UpgradeSerialiser<? extends ITurtleUpgrade>>> turtleUpgradeRegistryId() {
|
||||||
return turtleUpgradeRegistryId;
|
return turtleUpgradeRegistryId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ResourceKey<Registry<PocketUpgradeSerialiser<?>>> pocketUpgradeRegistryId() {
|
public final ResourceKey<Registry<UpgradeSerialiser<? extends IPocketUpgrade>>> pocketUpgradeRegistryId() {
|
||||||
return pocketUpgradeRegistryId;
|
return pocketUpgradeRegistryId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,20 +16,18 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The registry for peripheral providers.
|
* The registry for peripheral providers.
|
||||||
* <p>
|
|
||||||
* This lives in the {@code impl} package despite it not being part of the public API, in order to mirror Forge's class.
|
|
||||||
*/
|
*/
|
||||||
public final class Peripherals {
|
public final class Peripherals {
|
||||||
private static final GenericPeripheralProvider<Runnable> genericProvider = new GenericPeripheralProvider<>();
|
private static final GenericPeripheralProvider genericProvider = new GenericPeripheralProvider();
|
||||||
|
|
||||||
private Peripherals() {
|
private Peripherals() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addGenericLookup(ComponentLookup<? super Runnable> lookup) {
|
public static void addGenericLookup(ComponentLookup lookup) {
|
||||||
genericProvider.registerLookup(lookup);
|
genericProvider.registerLookup(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable IPeripheral getGenericPeripheral(ServerLevel level, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity, Runnable invalidate) {
|
public static @Nullable IPeripheral getGenericPeripheral(ServerLevel level, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity) {
|
||||||
return genericProvider.getPeripheral(level, pos, side, blockEntity, invalidate);
|
return genericProvider.getPeripheral(level, pos, side, blockEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,19 +6,18 @@ package dan200.computercraft.impl;
|
|||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public final class PocketUpgrades {
|
public final class PocketUpgrades {
|
||||||
private static final UpgradeManager<PocketUpgradeSerialiser<?>, IPocketUpgrade> registry = new UpgradeManager<>(
|
private static final UpgradeManager<IPocketUpgrade> registry = new UpgradeManager<>(
|
||||||
"pocket computer upgrade", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.registryId()
|
"pocket computer upgrade", "computercraft/pocket_upgrades", IPocketUpgrade.serialiserRegistryKey()
|
||||||
);
|
);
|
||||||
|
|
||||||
private PocketUpgrades() {
|
private PocketUpgrades() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UpgradeManager<PocketUpgradeSerialiser<?>, IPocketUpgrade> instance() {
|
public static UpgradeManager<IPocketUpgrade> instance() {
|
||||||
return registry;
|
return registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,19 +6,18 @@ package dan200.computercraft.impl;
|
|||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public final class TurtleUpgrades {
|
public final class TurtleUpgrades {
|
||||||
private static final UpgradeManager<TurtleUpgradeSerialiser<?>, ITurtleUpgrade> registry = new UpgradeManager<>(
|
private static final UpgradeManager<ITurtleUpgrade> registry = new UpgradeManager<>(
|
||||||
"turtle upgrade", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.registryId()
|
"turtle upgrade", "computercraft/turtle_upgrades", ITurtleUpgrade.serialiserRegistryKey()
|
||||||
);
|
);
|
||||||
|
|
||||||
private TurtleUpgrades() {
|
private TurtleUpgrades() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UpgradeManager<TurtleUpgradeSerialiser<?>, ITurtleUpgrade> instance() {
|
public static UpgradeManager<ITurtleUpgrade> instance() {
|
||||||
return registry;
|
return registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,27 +31,26 @@ import java.util.stream.Collectors;
|
|||||||
/**
|
/**
|
||||||
* Manages turtle and pocket computer upgrades.
|
* Manages turtle and pocket computer upgrades.
|
||||||
*
|
*
|
||||||
* @param <R> The type of upgrade serialisers.
|
|
||||||
* @param <T> The type of upgrade.
|
* @param <T> The type of upgrade.
|
||||||
* @see TurtleUpgrades
|
* @see TurtleUpgrades
|
||||||
* @see PocketUpgrades
|
* @see PocketUpgrades
|
||||||
*/
|
*/
|
||||||
public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase> extends SimpleJsonResourceReloadListener {
|
public class UpgradeManager<T extends UpgradeBase> extends SimpleJsonResourceReloadListener {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(UpgradeManager.class);
|
private static final Logger LOG = LoggerFactory.getLogger(UpgradeManager.class);
|
||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
|
|
||||||
public record UpgradeWrapper<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase>(
|
public record UpgradeWrapper<T extends UpgradeBase>(
|
||||||
String id, T upgrade, R serialiser, String modId
|
String id, T upgrade, UpgradeSerialiser<? extends T> serialiser, String modId
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String kind;
|
private final String kind;
|
||||||
private final ResourceKey<Registry<R>> registry;
|
private final ResourceKey<Registry<UpgradeSerialiser<? extends T>>> registry;
|
||||||
|
|
||||||
private Map<String, UpgradeWrapper<R, T>> current = Map.of();
|
private Map<String, UpgradeWrapper<T>> current = Map.of();
|
||||||
private Map<T, UpgradeWrapper<R, T>> currentWrappers = Map.of();
|
private Map<T, UpgradeWrapper<T>> currentWrappers = Map.of();
|
||||||
|
|
||||||
public UpgradeManager(String kind, String path, ResourceKey<Registry<R>> registry) {
|
public UpgradeManager(String kind, String path, ResourceKey<Registry<UpgradeSerialiser<? extends T>>> registry) {
|
||||||
super(GSON, path);
|
super(GSON, path);
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
this.registry = registry;
|
this.registry = registry;
|
||||||
@ -64,7 +63,7 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public UpgradeWrapper<R, T> getWrapper(T upgrade) {
|
public UpgradeWrapper<T> getWrapper(T upgrade) {
|
||||||
return currentWrappers.get(upgrade);
|
return currentWrappers.get(upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,16 +91,17 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
|||||||
return currentWrappers.keySet();
|
return currentWrappers.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, UpgradeWrapper<R, T>> getUpgradeWrappers() {
|
public Map<String, UpgradeWrapper<T>> getUpgradeWrappers() {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void apply(Map<ResourceLocation, JsonElement> upgrades, ResourceManager manager, ProfilerFiller profiler) {
|
protected void apply(Map<ResourceLocation, JsonElement> upgrades, ResourceManager manager, ProfilerFiller profiler) {
|
||||||
Map<String, UpgradeWrapper<R, T>> newUpgrades = new HashMap<>();
|
var registry = RegistryHelper.getRegistry(this.registry);
|
||||||
|
Map<String, UpgradeWrapper<T>> newUpgrades = new HashMap<>();
|
||||||
for (var element : upgrades.entrySet()) {
|
for (var element : upgrades.entrySet()) {
|
||||||
try {
|
try {
|
||||||
loadUpgrade(newUpgrades, element.getKey(), element.getValue());
|
loadUpgrade(registry, newUpgrades, element.getKey(), element.getValue());
|
||||||
} catch (IllegalArgumentException | JsonParseException e) {
|
} catch (IllegalArgumentException | JsonParseException e) {
|
||||||
LOG.error("Error loading {} {} from JSON file", kind, element.getKey(), e);
|
LOG.error("Error loading {} {} from JSON file", kind, element.getKey(), e);
|
||||||
}
|
}
|
||||||
@ -112,12 +112,12 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
|||||||
LOG.info("Loaded {} {}s", current.size(), kind);
|
LOG.info("Loaded {} {}s", current.size(), kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadUpgrade(Map<String, UpgradeWrapper<R, T>> current, ResourceLocation id, JsonElement json) {
|
private void loadUpgrade(Registry<UpgradeSerialiser<? extends T>> registry, Map<String, UpgradeWrapper<T>> current, ResourceLocation id, JsonElement json) {
|
||||||
var root = GsonHelper.convertToJsonObject(json, "top element");
|
var root = GsonHelper.convertToJsonObject(json, "top element");
|
||||||
if (!PlatformHelper.get().shouldLoadResource(root)) return;
|
if (!PlatformHelper.get().shouldLoadResource(root)) return;
|
||||||
|
|
||||||
var serialiserId = new ResourceLocation(GsonHelper.getAsString(root, "type"));
|
var serialiserId = new ResourceLocation(GsonHelper.getAsString(root, "type"));
|
||||||
var serialiser = PlatformHelper.get().tryGetRegistryObject(registry, serialiserId);
|
var serialiser = registry.get(serialiserId);
|
||||||
if (serialiser == null) throw new JsonSyntaxException("Unknown upgrade type '" + serialiserId + "'");
|
if (serialiser == null) throw new JsonSyntaxException("Unknown upgrade type '" + serialiserId + "'");
|
||||||
|
|
||||||
// TODO: Can we track which mod this resource came from and use that instead? It's theoretically possible,
|
// TODO: Can we track which mod this resource came from and use that instead? It's theoretically possible,
|
||||||
@ -130,11 +130,11 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
|||||||
throw new IllegalArgumentException("Upgrade " + id + " from " + serialiser + " was incorrectly given id " + upgrade.getUpgradeID());
|
throw new IllegalArgumentException("Upgrade " + id + " from " + serialiser + " was incorrectly given id " + upgrade.getUpgradeID());
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new UpgradeWrapper<R, T>(id.toString(), upgrade, serialiser, modId);
|
var result = new UpgradeWrapper<T>(id.toString(), upgrade, serialiser, modId);
|
||||||
current.put(result.id(), result);
|
current.put(result.id(), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadFromNetwork(Map<String, UpgradeWrapper<R, T>> newUpgrades) {
|
public void loadFromNetwork(Map<String, UpgradeWrapper<T>> newUpgrades) {
|
||||||
current = Collections.unmodifiableMap(newUpgrades);
|
current = Collections.unmodifiableMap(newUpgrades);
|
||||||
currentWrappers = newUpgrades.values().stream().collect(Collectors.toUnmodifiableMap(UpgradeWrapper::upgrade, x -> x));
|
currentWrappers = newUpgrades.values().stream().collect(Collectors.toUnmodifiableMap(UpgradeWrapper::upgrade, x -> x));
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,12 @@ public final class CommonHooks {
|
|||||||
ComputerMBean.start(server);
|
ComputerMBean.start(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void onServerStarted(MinecraftServer server) {
|
||||||
|
// ItemDetails requires creative tabs to be populated, however by default this is done lazily on the client and
|
||||||
|
// not at all on the server! We instead do this once on server startup.
|
||||||
|
CreativeModeTabs.tryRebuildTabContents(server.getWorldData().enabledFeatures(), false, server.registryAccess());
|
||||||
|
}
|
||||||
|
|
||||||
public static void onServerStopped() {
|
public static void onServerStopped() {
|
||||||
resetState();
|
resetState();
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,15 @@
|
|||||||
package dan200.computercraft.shared;
|
package dan200.computercraft.shared;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.api.detail.DetailProvider;
|
import dan200.computercraft.api.detail.DetailProvider;
|
||||||
import dan200.computercraft.api.detail.VanillaDetailRegistries;
|
import dan200.computercraft.api.detail.VanillaDetailRegistries;
|
||||||
import dan200.computercraft.api.media.IMedia;
|
import dan200.computercraft.api.media.IMedia;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||||
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.core.util.Colour;
|
import dan200.computercraft.core.util.Colour;
|
||||||
import dan200.computercraft.impl.PocketUpgrades;
|
import dan200.computercraft.impl.PocketUpgrades;
|
||||||
import dan200.computercraft.impl.TurtleUpgrades;
|
import dan200.computercraft.impl.TurtleUpgrades;
|
||||||
@ -36,7 +38,6 @@ import dan200.computercraft.shared.computer.items.ComputerItem;
|
|||||||
import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe;
|
import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe;
|
||||||
import dan200.computercraft.shared.config.Config;
|
import dan200.computercraft.shared.config.Config;
|
||||||
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
|
import dan200.computercraft.shared.data.BlockNamedEntityLootCondition;
|
||||||
import dan200.computercraft.shared.data.ConstantLootConditionSerializer;
|
|
||||||
import dan200.computercraft.shared.data.HasComputerIdLootCondition;
|
import dan200.computercraft.shared.data.HasComputerIdLootCondition;
|
||||||
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
||||||
import dan200.computercraft.shared.details.BlockDetails;
|
import dan200.computercraft.shared.details.BlockDetails;
|
||||||
@ -263,29 +264,29 @@ public final class ModRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class TurtleSerialisers {
|
public static class TurtleSerialisers {
|
||||||
static final RegistrationHelper<TurtleUpgradeSerialiser<?>> REGISTRY = PlatformHelper.get().createRegistrationHelper(TurtleUpgradeSerialiser.registryId());
|
static final RegistrationHelper<UpgradeSerialiser<? extends ITurtleUpgrade>> REGISTRY = PlatformHelper.get().createRegistrationHelper(ITurtleUpgrade.serialiserRegistryKey());
|
||||||
|
|
||||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleSpeaker>> SPEAKER =
|
public static final RegistryEntry<UpgradeSerialiser<TurtleSpeaker>> SPEAKER =
|
||||||
REGISTRY.register("speaker", () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleSpeaker::new));
|
REGISTRY.register("speaker", () -> UpgradeSerialiser.simpleWithCustomItem(TurtleSpeaker::new));
|
||||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleCraftingTable>> WORKBENCH =
|
public static final RegistryEntry<UpgradeSerialiser<TurtleCraftingTable>> WORKBENCH =
|
||||||
REGISTRY.register("workbench", () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleCraftingTable::new));
|
REGISTRY.register("workbench", () -> UpgradeSerialiser.simpleWithCustomItem(TurtleCraftingTable::new));
|
||||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_NORMAL =
|
public static final RegistryEntry<UpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_NORMAL =
|
||||||
REGISTRY.register("wireless_modem_normal", () -> TurtleUpgradeSerialiser.simpleWithCustomItem((id, item) -> new TurtleModem(id, item, false)));
|
REGISTRY.register("wireless_modem_normal", () -> UpgradeSerialiser.simpleWithCustomItem((id, item) -> new TurtleModem(id, item, false)));
|
||||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_ADVANCED =
|
public static final RegistryEntry<UpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_ADVANCED =
|
||||||
REGISTRY.register("wireless_modem_advanced", () -> TurtleUpgradeSerialiser.simpleWithCustomItem((id, item) -> new TurtleModem(id, item, true)));
|
REGISTRY.register("wireless_modem_advanced", () -> UpgradeSerialiser.simpleWithCustomItem((id, item) -> new TurtleModem(id, item, true)));
|
||||||
|
|
||||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleTool>> TOOL = REGISTRY.register("tool", () -> TurtleToolSerialiser.INSTANCE);
|
public static final RegistryEntry<UpgradeSerialiser<TurtleTool>> TOOL = REGISTRY.register("tool", () -> TurtleToolSerialiser.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PocketUpgradeSerialisers {
|
public static class PocketUpgradeSerialisers {
|
||||||
static final RegistrationHelper<PocketUpgradeSerialiser<?>> REGISTRY = PlatformHelper.get().createRegistrationHelper(PocketUpgradeSerialiser.registryId());
|
static final RegistrationHelper<UpgradeSerialiser<? extends IPocketUpgrade>> REGISTRY = PlatformHelper.get().createRegistrationHelper(IPocketUpgrade.serialiserRegistryKey());
|
||||||
|
|
||||||
public static final RegistryEntry<PocketUpgradeSerialiser<PocketSpeaker>> SPEAKER =
|
public static final RegistryEntry<UpgradeSerialiser<PocketSpeaker>> SPEAKER =
|
||||||
REGISTRY.register("speaker", () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketSpeaker::new));
|
REGISTRY.register("speaker", () -> UpgradeSerialiser.simpleWithCustomItem(PocketSpeaker::new));
|
||||||
public static final RegistryEntry<PocketUpgradeSerialiser<PocketModem>> WIRELESS_MODEM_NORMAL =
|
public static final RegistryEntry<UpgradeSerialiser<PocketModem>> WIRELESS_MODEM_NORMAL =
|
||||||
REGISTRY.register("wireless_modem_normal", () -> PocketUpgradeSerialiser.simpleWithCustomItem((id, item) -> new PocketModem(id, item, false)));
|
REGISTRY.register("wireless_modem_normal", () -> UpgradeSerialiser.simpleWithCustomItem((id, item) -> new PocketModem(id, item, false)));
|
||||||
public static final RegistryEntry<PocketUpgradeSerialiser<PocketModem>> WIRELESS_MODEM_ADVANCED =
|
public static final RegistryEntry<UpgradeSerialiser<PocketModem>> WIRELESS_MODEM_ADVANCED =
|
||||||
REGISTRY.register("wireless_modem_advanced", () -> PocketUpgradeSerialiser.simpleWithCustomItem((id, item) -> new PocketModem(id, item, true)));
|
REGISTRY.register("wireless_modem_advanced", () -> UpgradeSerialiser.simpleWithCustomItem((id, item) -> new PocketModem(id, item, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Menus {
|
public static class Menus {
|
||||||
@ -347,13 +348,13 @@ public final class ModRegistry {
|
|||||||
static final RegistrationHelper<LootItemConditionType> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.LOOT_CONDITION_TYPE);
|
static final RegistrationHelper<LootItemConditionType> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.LOOT_CONDITION_TYPE);
|
||||||
|
|
||||||
public static final RegistryEntry<LootItemConditionType> BLOCK_NAMED = REGISTRY.register("block_named",
|
public static final RegistryEntry<LootItemConditionType> BLOCK_NAMED = REGISTRY.register("block_named",
|
||||||
() -> ConstantLootConditionSerializer.type(BlockNamedEntityLootCondition.INSTANCE));
|
() -> new LootItemConditionType(Codec.unit(BlockNamedEntityLootCondition.INSTANCE)));
|
||||||
|
|
||||||
public static final RegistryEntry<LootItemConditionType> PLAYER_CREATIVE = REGISTRY.register("player_creative",
|
public static final RegistryEntry<LootItemConditionType> PLAYER_CREATIVE = REGISTRY.register("player_creative",
|
||||||
() -> ConstantLootConditionSerializer.type(PlayerCreativeLootCondition.INSTANCE));
|
() -> new LootItemConditionType(Codec.unit(PlayerCreativeLootCondition.INSTANCE)));
|
||||||
|
|
||||||
public static final RegistryEntry<LootItemConditionType> HAS_ID = REGISTRY.register("has_id",
|
public static final RegistryEntry<LootItemConditionType> HAS_ID = REGISTRY.register("has_id",
|
||||||
() -> ConstantLootConditionSerializer.type(HasComputerIdLootCondition.INSTANCE));
|
() -> new LootItemConditionType(Codec.unit(HasComputerIdLootCondition.INSTANCE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RecipeSerializers {
|
public static class RecipeSerializers {
|
||||||
@ -466,8 +467,8 @@ public final class ModRegistry {
|
|||||||
* Register any objects which must be done on the main thread.
|
* Register any objects which must be done on the main thread.
|
||||||
*/
|
*/
|
||||||
public static void registerMainThread() {
|
public static void registerMainThread() {
|
||||||
CauldronInteraction.WATER.put(Items.TURTLE_NORMAL.get(), TurtleItem.CAULDRON_INTERACTION);
|
CauldronInteraction.WATER.map().put(Items.TURTLE_NORMAL.get(), TurtleItem.CAULDRON_INTERACTION);
|
||||||
CauldronInteraction.WATER.put(Items.TURTLE_ADVANCED.get(), TurtleItem.CAULDRON_INTERACTION);
|
CauldronInteraction.WATER.map().put(Items.TURTLE_ADVANCED.get(), TurtleItem.CAULDRON_INTERACTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addTurtle(CreativeModeTab.Output out, TurtleItem turtle) {
|
private static void addTurtle(CreativeModeTab.Output out, TurtleItem turtle) {
|
||||||
|
@ -8,8 +8,9 @@ import com.google.gson.JsonObject;
|
|||||||
import com.mojang.brigadier.Message;
|
import com.mojang.brigadier.Message;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
|
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ public class ArgumentUtils {
|
|||||||
public static <A extends ArgumentType<?>> JsonObject serializeToJson(ArgumentTypeInfo.Template<A> template) {
|
public static <A extends ArgumentType<?>> JsonObject serializeToJson(ArgumentTypeInfo.Template<A> template) {
|
||||||
var object = new JsonObject();
|
var object = new JsonObject();
|
||||||
object.addProperty("type", "argument");
|
object.addProperty("type", "argument");
|
||||||
object.addProperty("parser", RegistryWrappers.COMMAND_ARGUMENT_TYPES.getKey(template.type()).toString());
|
object.addProperty("parser", RegistryHelper.getKeyOrThrow(BuiltInRegistries.COMMAND_ARGUMENT_TYPE, template.type()).toString());
|
||||||
|
|
||||||
var properties = new JsonObject();
|
var properties = new JsonObject();
|
||||||
serializeToJson(properties, template.type(), template);
|
serializeToJson(properties, template.type(), template);
|
||||||
@ -44,12 +45,12 @@ public class ArgumentUtils {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static <A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>> void serializeToNetwork(FriendlyByteBuf buffer, ArgumentTypeInfo<A, T> type, ArgumentTypeInfo.Template<A> template) {
|
private static <A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>> void serializeToNetwork(FriendlyByteBuf buffer, ArgumentTypeInfo<A, T> type, ArgumentTypeInfo.Template<A> template) {
|
||||||
buffer.writeId(RegistryWrappers.COMMAND_ARGUMENT_TYPES, type);
|
buffer.writeId(BuiltInRegistries.COMMAND_ARGUMENT_TYPE, type);
|
||||||
type.serializeToNetwork((T) template, buffer);
|
type.serializeToNetwork((T) template, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArgumentTypeInfo.Template<?> deserialize(FriendlyByteBuf buffer) {
|
public static ArgumentTypeInfo.Template<?> deserialize(FriendlyByteBuf buffer) {
|
||||||
var type = buffer.readById(RegistryWrappers.COMMAND_ARGUMENT_TYPES);
|
var type = buffer.readById(BuiltInRegistries.COMMAND_ARGUMENT_TYPE);
|
||||||
Objects.requireNonNull(type, "Unknown argument type");
|
Objects.requireNonNull(type, "Unknown argument type");
|
||||||
return type.deserializeFromNetwork(buffer);
|
return type.deserializeFromNetwork(buffer);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ package dan200.computercraft.shared.common;
|
|||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.inventory.CraftingContainer;
|
import net.minecraft.world.inventory.CraftingContainer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
@ -20,8 +19,8 @@ import net.minecraft.world.level.Level;
|
|||||||
* Craft a wet sponge with a {@linkplain IColouredItem dyable item} to remove its dye.
|
* Craft a wet sponge with a {@linkplain IColouredItem dyable item} to remove its dye.
|
||||||
*/
|
*/
|
||||||
public final class ClearColourRecipe extends CustomRecipe {
|
public final class ClearColourRecipe extends CustomRecipe {
|
||||||
public ClearColourRecipe(ResourceLocation id, CraftingBookCategory category) {
|
public ClearColourRecipe(CraftingBookCategory category) {
|
||||||
super(id, category);
|
super(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -8,7 +8,6 @@ import dan200.computercraft.shared.ModRegistry;
|
|||||||
import dan200.computercraft.shared.util.ColourTracker;
|
import dan200.computercraft.shared.util.ColourTracker;
|
||||||
import dan200.computercraft.shared.util.ColourUtils;
|
import dan200.computercraft.shared.util.ColourUtils;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.inventory.CraftingContainer;
|
import net.minecraft.world.inventory.CraftingContainer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||||
@ -17,8 +16,8 @@ import net.minecraft.world.item.crafting.RecipeSerializer;
|
|||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public final class ColourableRecipe extends CustomRecipe {
|
public final class ColourableRecipe extends CustomRecipe {
|
||||||
public ColourableRecipe(ResourceLocation id, CraftingBookCategory category) {
|
public ColourableRecipe(CraftingBookCategory category) {
|
||||||
super(id, category);
|
super(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,14 +56,22 @@ public class CommandAPI implements ILuaAPI {
|
|||||||
var receiver = computer.getReceiver();
|
var receiver = computer.getReceiver();
|
||||||
try {
|
try {
|
||||||
receiver.clearOutput();
|
receiver.clearOutput();
|
||||||
var result = commandManager.performPrefixedCommand(computer.getSource(), command);
|
var state = new CommandState();
|
||||||
return new Object[]{ result > 0, receiver.copyOutput(), result };
|
var source = computer.getSource().withCallback((success, x) -> {
|
||||||
|
if (success) state.successes++;
|
||||||
|
});
|
||||||
|
commandManager.performPrefixedCommand(source, command);
|
||||||
|
return new Object[]{ state.successes > 0, receiver.copyOutput(), state.successes };
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
LOG.error(Logging.JAVA_ERROR, "Error running command.", t);
|
LOG.error(Logging.JAVA_ERROR, "Error running command.", t);
|
||||||
return new Object[]{ false, createOutput("Java Exception Thrown: " + t) };
|
return new Object[]{ false, createOutput("Java Exception Thrown: " + t) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class CommandState {
|
||||||
|
int successes;
|
||||||
|
}
|
||||||
|
|
||||||
private static Map<?, ?> getBlockInfo(Level world, BlockPos pos) {
|
private static Map<?, ?> getBlockInfo(Level world, BlockPos pos) {
|
||||||
// Get the details of the block
|
// Get the details of the block
|
||||||
var block = new BlockReference(world, pos);
|
var block = new BlockReference(world, pos);
|
||||||
|
@ -99,7 +99,7 @@ public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
|
public ItemStack getCloneItemStack(LevelReader world, BlockPos pos, BlockState state) {
|
||||||
var tile = world.getBlockEntity(pos);
|
var tile = world.getBlockEntity(pos);
|
||||||
if (tile instanceof AbstractComputerBlockEntity computer) {
|
if (tile instanceof AbstractComputerBlockEntity computer) {
|
||||||
var result = getItem(computer);
|
var result = getItem(computer);
|
||||||
@ -117,9 +117,9 @@ public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntit
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
|
public BlockState playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
|
||||||
super.playerWillDestroy(world, pos, state, player);
|
var result = super.playerWillDestroy(world, pos, state, player);
|
||||||
if (!(world instanceof ServerLevel serverWorld)) return;
|
if (!(world instanceof ServerLevel serverWorld)) return result;
|
||||||
|
|
||||||
// We drop the item here instead of doing it in the harvest method, as we should
|
// We drop the item here instead of doing it in the harvest method, as we should
|
||||||
// drop computers for creative players too.
|
// drop computers for creative players too.
|
||||||
@ -138,6 +138,8 @@ public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntit
|
|||||||
|
|
||||||
state.spawnAfterBreak(serverWorld, pos, player.getMainHandItem(), true);
|
state.spawnAfterBreak(serverWorld, pos, player.getMainHandItem(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import dan200.computercraft.shared.platform.RegistryEntry;
|
import dan200.computercraft.shared.platform.RegistryEntry;
|
||||||
|
import dan200.computercraft.shared.util.BlockCodecs;
|
||||||
import net.minecraft.world.level.block.GameMasterBlock;
|
import net.minecraft.world.level.block.GameMasterBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
|
||||||
@ -16,7 +19,17 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
|
|||||||
* @see dan200.computercraft.shared.computer.items.CommandComputerItem
|
* @see dan200.computercraft.shared.computer.items.CommandComputerItem
|
||||||
*/
|
*/
|
||||||
public class CommandComputerBlock<T extends CommandComputerBlockEntity> extends ComputerBlock<T> implements GameMasterBlock {
|
public class CommandComputerBlock<T extends CommandComputerBlockEntity> extends ComputerBlock<T> implements GameMasterBlock {
|
||||||
|
private static final MapCodec<CommandComputerBlock<?>> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||||
|
BlockCodecs.propertiesCodec(),
|
||||||
|
BlockCodecs.blockEntityCodec(x -> x.type)
|
||||||
|
).apply(instance, CommandComputerBlock::new));
|
||||||
|
|
||||||
public CommandComputerBlock(Properties settings, RegistryEntry<BlockEntityType<T>> type) {
|
public CommandComputerBlock(Properties settings, RegistryEntry<BlockEntityType<T>> type) {
|
||||||
super(settings, type);
|
super(settings, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MapCodec<? extends CommandComputerBlock<?>> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.computer.blocks;
|
package dan200.computercraft.shared.computer.blocks;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||||
import dan200.computercraft.shared.computer.items.ComputerItem;
|
import dan200.computercraft.shared.computer.items.ComputerItem;
|
||||||
import dan200.computercraft.shared.platform.RegistryEntry;
|
import dan200.computercraft.shared.platform.RegistryEntry;
|
||||||
|
import dan200.computercraft.shared.util.BlockCodecs;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
@ -21,6 +24,11 @@ import net.minecraft.world.level.block.state.properties.EnumProperty;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class ComputerBlock<T extends ComputerBlockEntity> extends AbstractComputerBlock<T> {
|
public class ComputerBlock<T extends ComputerBlockEntity> extends AbstractComputerBlock<T> {
|
||||||
|
private static final MapCodec<ComputerBlock<?>> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||||
|
BlockCodecs.propertiesCodec(),
|
||||||
|
BlockCodecs.blockEntityCodec(x -> x.type)
|
||||||
|
).apply(instance, ComputerBlock::new));
|
||||||
|
|
||||||
public static final EnumProperty<ComputerState> STATE = EnumProperty.create("state", ComputerState.class);
|
public static final EnumProperty<ComputerState> STATE = EnumProperty.create("state", ComputerState.class);
|
||||||
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||||
|
|
||||||
@ -37,6 +45,11 @@ public class ComputerBlock<T extends ComputerBlockEntity> extends AbstractComput
|
|||||||
builder.add(FACING, STATE);
|
builder.add(FACING, STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MapCodec<? extends ComputerBlock<?>> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockState getStateForPlacement(BlockPlaceContext placement) {
|
public BlockState getStateForPlacement(BlockPlaceContext placement) {
|
||||||
|
@ -8,7 +8,6 @@ import dan200.computercraft.shared.computer.items.IComputerItem;
|
|||||||
import dan200.computercraft.shared.recipe.CustomShapedRecipe;
|
import dan200.computercraft.shared.recipe.CustomShapedRecipe;
|
||||||
import dan200.computercraft.shared.recipe.ShapedRecipeSpec;
|
import dan200.computercraft.shared.recipe.ShapedRecipeSpec;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.inventory.CraftingContainer;
|
import net.minecraft.world.inventory.CraftingContainer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
@ -17,8 +16,8 @@ import net.minecraft.world.level.Level;
|
|||||||
* A recipe which converts a computer from one form into another.
|
* A recipe which converts a computer from one form into another.
|
||||||
*/
|
*/
|
||||||
public abstract class ComputerConvertRecipe extends CustomShapedRecipe {
|
public abstract class ComputerConvertRecipe extends CustomShapedRecipe {
|
||||||
public ComputerConvertRecipe(ResourceLocation identifier, ShapedRecipeSpec recipe) {
|
public ComputerConvertRecipe(ShapedRecipeSpec recipe) {
|
||||||
super(identifier, recipe);
|
super(recipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ItemStack convert(IComputerItem item, ItemStack stack);
|
protected abstract ItemStack convert(IComputerItem item, ItemStack stack);
|
||||||
|
@ -8,7 +8,6 @@ import com.mojang.serialization.DataResult;
|
|||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.computer.items.IComputerItem;
|
import dan200.computercraft.shared.computer.items.IComputerItem;
|
||||||
import dan200.computercraft.shared.recipe.ShapedRecipeSpec;
|
import dan200.computercraft.shared.recipe.ShapedRecipeSpec;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
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;
|
||||||
@ -22,17 +21,17 @@ import net.minecraft.world.item.crafting.RecipeSerializer;
|
|||||||
public final class ComputerUpgradeRecipe extends ComputerConvertRecipe {
|
public final class ComputerUpgradeRecipe extends ComputerConvertRecipe {
|
||||||
private final Item result;
|
private final Item result;
|
||||||
|
|
||||||
private ComputerUpgradeRecipe(ResourceLocation identifier, ShapedRecipeSpec recipe) {
|
public ComputerUpgradeRecipe(ShapedRecipeSpec recipe) {
|
||||||
super(identifier, recipe);
|
super(recipe);
|
||||||
this.result = recipe.result().getItem();
|
this.result = recipe.result().getItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataResult<ComputerUpgradeRecipe> of(ResourceLocation id, ShapedRecipeSpec recipe) {
|
public static DataResult<ComputerUpgradeRecipe> of(ShapedRecipeSpec recipe) {
|
||||||
if (!(recipe.result().getItem() instanceof IComputerItem)) {
|
if (!(recipe.result().getItem() instanceof IComputerItem)) {
|
||||||
return DataResult.error(() -> recipe.result().getItem() + " is not a computer item");
|
return DataResult.error(() -> recipe.result().getItem() + " is not a computer item");
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataResult.success(new ComputerUpgradeRecipe(id, recipe));
|
return DataResult.success(new ComputerUpgradeRecipe(recipe));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2019 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.shared.data;
|
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonSerializationContext;
|
|
||||||
import net.minecraft.world.level.storage.loot.Serializer;
|
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
|
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType;
|
|
||||||
|
|
||||||
public final class ConstantLootConditionSerializer<T extends LootItemCondition> implements Serializer<T> {
|
|
||||||
private final T instance;
|
|
||||||
|
|
||||||
public ConstantLootConditionSerializer(T instance) {
|
|
||||||
this.instance = instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends LootItemCondition> LootItemConditionType type(T condition) {
|
|
||||||
return new LootItemConditionType(new ConstantLootConditionSerializer<>(condition));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serialize(JsonObject json, T object, JsonSerializationContext context) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T deserialize(JsonObject json, JsonDeserializationContext context) {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@
|
|||||||
package dan200.computercraft.shared.details;
|
package dan200.computercraft.shared.details;
|
||||||
|
|
||||||
import dan200.computercraft.api.detail.BlockReference;
|
import dan200.computercraft.api.detail.BlockReference;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -15,7 +15,7 @@ public class BlockDetails {
|
|||||||
public static void fillBasic(Map<? super String, Object> data, BlockReference block) {
|
public static void fillBasic(Map<? super String, Object> data, BlockReference block) {
|
||||||
var state = block.state();
|
var state = block.state();
|
||||||
|
|
||||||
data.put("name", DetailHelpers.getId(RegistryWrappers.BLOCKS, state.getBlock()));
|
data.put("name", DetailHelpers.getId(BuiltInRegistries.BLOCK, state.getBlock()));
|
||||||
|
|
||||||
Map<Object, Object> stateTable = new HashMap<>();
|
Map<Object, Object> stateTable = new HashMap<>();
|
||||||
for (Map.Entry<Property<?>, ? extends Comparable<?>> entry : state.getValues().entrySet()) {
|
for (Map.Entry<Property<?>, ? extends Comparable<?>> entry : state.getValues().entrySet()) {
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.details;
|
package dan200.computercraft.shared.details;
|
||||||
|
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -24,7 +25,7 @@ public final class DetailHelpers {
|
|||||||
return tags.collect(Collectors.toMap(x -> x.location().toString(), x -> true));
|
return tags.collect(Collectors.toMap(x -> x.location().toString(), x -> true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> String getId(RegistryWrappers.RegistryWrapper<T> registry, T entry) {
|
public static <T> String getId(Registry<T> registry, T entry) {
|
||||||
return registry.getKey(entry).toString();
|
return RegistryHelper.getKeyOrThrow(registry, entry).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,13 @@
|
|||||||
package dan200.computercraft.shared.details;
|
package dan200.computercraft.shared.details;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
|
||||||
import dan200.computercraft.shared.util.NBTUtil;
|
import dan200.computercraft.shared.util.NBTUtil;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.ListTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.item.CreativeModeTab;
|
||||||
|
import net.minecraft.world.item.CreativeModeTabs;
|
||||||
import net.minecraft.world.item.EnchantedBookItem;
|
import net.minecraft.world.item.EnchantedBookItem;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||||
@ -22,7 +24,7 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class ItemDetails {
|
public class ItemDetails {
|
||||||
public static void fillBasic(Map<? super String, Object> data, ItemStack stack) {
|
public static void fillBasic(Map<? super String, Object> data, ItemStack stack) {
|
||||||
data.put("name", DetailHelpers.getId(RegistryWrappers.ITEMS, stack.getItem()));
|
data.put("name", DetailHelpers.getId(BuiltInRegistries.ITEM, stack.getItem()));
|
||||||
data.put("count", stack.getCount());
|
data.put("count", stack.getCount());
|
||||||
var hash = NBTUtil.getNBTHash(stack.getTag());
|
var hash = NBTUtil.getNBTHash(stack.getTag());
|
||||||
if (hash != null) data.put("nbt", hash);
|
if (hash != null) data.put("nbt", hash);
|
||||||
@ -42,9 +44,7 @@ public class ItemDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.put("tags", DetailHelpers.getTags(stack.getTags()));
|
data.put("tags", DetailHelpers.getTags(stack.getTags()));
|
||||||
|
data.put("itemGroups", getItemGroups(stack));
|
||||||
// Include deprecated itemGroups field
|
|
||||||
data.put("itemGroups", List.of());
|
|
||||||
|
|
||||||
var tag = stack.getTag();
|
var tag = stack.getTag();
|
||||||
if (tag != null && tag.contains("display", Tag.TAG_COMPOUND)) {
|
if (tag != null && tag.contains("display", Tag.TAG_COMPOUND)) {
|
||||||
@ -83,6 +83,27 @@ public class ItemDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all item groups an item stack pertains to.
|
||||||
|
*
|
||||||
|
* @param stack Stack to analyse
|
||||||
|
* @return A filled list that contains pairs of item group IDs and their display names.
|
||||||
|
*/
|
||||||
|
private static List<Map<String, Object>> getItemGroups(ItemStack stack) {
|
||||||
|
return CreativeModeTabs.allTabs().stream()
|
||||||
|
.filter(x -> x.shouldDisplay() && x.getType() == CreativeModeTab.Type.CATEGORY && x.contains(stack))
|
||||||
|
.map(group -> {
|
||||||
|
Map<String, Object> groupData = new HashMap<>(2);
|
||||||
|
|
||||||
|
var id = BuiltInRegistries.CREATIVE_MODE_TAB.getKey(group);
|
||||||
|
if (id != null) groupData.put("id", id.toString());
|
||||||
|
|
||||||
|
groupData.put("displayName", group.getDisplayName().getString());
|
||||||
|
return groupData;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all visible enchantments from given stack. Try to follow all tooltip rules : order and visibility.
|
* Retrieve all visible enchantments from given stack. Try to follow all tooltip rules : order and visibility.
|
||||||
*
|
*
|
||||||
@ -126,7 +147,7 @@ public class ItemDetails {
|
|||||||
var enchantment = entry.getKey();
|
var enchantment = entry.getKey();
|
||||||
var level = entry.getValue();
|
var level = entry.getValue();
|
||||||
var enchant = new HashMap<String, Object>(3);
|
var enchant = new HashMap<String, Object>(3);
|
||||||
enchant.put("name", DetailHelpers.getId(RegistryWrappers.ENCHANTMENTS, enchantment));
|
enchant.put("name", DetailHelpers.getId(BuiltInRegistries.ENCHANTMENT, enchantment));
|
||||||
enchant.put("level", level);
|
enchant.put("level", level);
|
||||||
enchant.put("displayName", enchantment.getFullname(level).getString());
|
enchant.put("displayName", enchantment.getFullname(level).getString());
|
||||||
enchants.add(enchant);
|
enchants.add(enchant);
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.integration;
|
package dan200.computercraft.shared.integration;
|
||||||
|
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
|
||||||
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.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
@ -15,13 +14,12 @@ import dan200.computercraft.impl.TurtleUpgrades;
|
|||||||
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
||||||
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||||
import net.minecraft.world.item.crafting.CraftingRecipe;
|
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.item.crafting.ShapedRecipe;
|
import net.minecraft.world.item.crafting.ShapedRecipe;
|
||||||
|
import net.minecraft.world.item.crafting.ShapedRecipePattern;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -38,17 +36,14 @@ import static dan200.computercraft.shared.integration.RecipeModHelpers.TURTLES;
|
|||||||
* @see RecipeModHelpers
|
* @see RecipeModHelpers
|
||||||
*/
|
*/
|
||||||
public class UpgradeRecipeGenerator<T> {
|
public class UpgradeRecipeGenerator<T> {
|
||||||
private static final ResourceLocation TURTLE_UPGRADE = new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade");
|
private final Function<ShapedRecipe, T> wrap;
|
||||||
private static final ResourceLocation POCKET_UPGRADE = new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade");
|
|
||||||
|
|
||||||
private final Function<CraftingRecipe, T> wrap;
|
|
||||||
|
|
||||||
private final Map<Item, List<UpgradeInfo>> upgradeItemLookup = new HashMap<>();
|
private final Map<Item, List<UpgradeInfo>> upgradeItemLookup = new HashMap<>();
|
||||||
private final List<UpgradeInfo> pocketUpgrades = new ArrayList<>();
|
private final List<UpgradeInfo> pocketUpgrades = new ArrayList<>();
|
||||||
private final List<UpgradeInfo> turtleUpgrades = new ArrayList<>();
|
private final List<UpgradeInfo> turtleUpgrades = new ArrayList<>();
|
||||||
private boolean initialised = false;
|
private boolean initialised = false;
|
||||||
|
|
||||||
public UpgradeRecipeGenerator(Function<CraftingRecipe, T> wrap) {
|
public UpgradeRecipeGenerator(Function<ShapedRecipe, T> wrap) {
|
||||||
this.wrap = wrap;
|
this.wrap = wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,11 +230,19 @@ public class UpgradeRecipeGenerator<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private T pocket(Ingredient upgrade, Ingredient pocketComputer, ItemStack result) {
|
private T pocket(Ingredient upgrade, Ingredient pocketComputer, ItemStack result) {
|
||||||
return wrap.apply(new ShapedRecipe(POCKET_UPGRADE, "", CraftingBookCategory.MISC, 1, 2, NonNullList.of(Ingredient.EMPTY, upgrade, pocketComputer), result));
|
return wrap.apply(new ShapedRecipe(
|
||||||
|
"", CraftingBookCategory.MISC,
|
||||||
|
new ShapedRecipePattern(1, 2, NonNullList.of(Ingredient.EMPTY, upgrade, pocketComputer), Optional.empty()),
|
||||||
|
result
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private T turtle(Ingredient left, Ingredient right, ItemStack result) {
|
private T turtle(Ingredient left, Ingredient right, ItemStack result) {
|
||||||
return wrap.apply(new ShapedRecipe(TURTLE_UPGRADE, "", CraftingBookCategory.MISC, 2, 1, NonNullList.of(Ingredient.EMPTY, left, right), result));
|
return wrap.apply(new ShapedRecipe(
|
||||||
|
"", CraftingBookCategory.MISC,
|
||||||
|
new ShapedRecipePattern(2, 1, NonNullList.of(Ingredient.EMPTY, left, right), Optional.empty()),
|
||||||
|
result
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UpgradeInfo {
|
private class UpgradeInfo {
|
||||||
|
@ -60,7 +60,7 @@ public class JEIComputerCraft implements IModPlugin {
|
|||||||
// Hide all upgrade recipes
|
// Hide all upgrade recipes
|
||||||
var category = registry.createRecipeLookup(RecipeTypes.CRAFTING);
|
var category = registry.createRecipeLookup(RecipeTypes.CRAFTING);
|
||||||
category.get().forEach(wrapper -> {
|
category.get().forEach(wrapper -> {
|
||||||
if (RecipeModHelpers.shouldRemoveRecipe(wrapper.getId())) {
|
if (RecipeModHelpers.shouldRemoveRecipe(wrapper.id())) {
|
||||||
registry.hideRecipes(RecipeTypes.CRAFTING, List.of(wrapper));
|
registry.hideRecipes(RecipeTypes.CRAFTING, List.of(wrapper));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -11,7 +11,6 @@ import dan200.computercraft.shared.platform.PlatformHelper;
|
|||||||
import dan200.computercraft.shared.util.ColourTracker;
|
import dan200.computercraft.shared.util.ColourTracker;
|
||||||
import dan200.computercraft.shared.util.ColourUtils;
|
import dan200.computercraft.shared.util.ColourUtils;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.inventory.CraftingContainer;
|
import net.minecraft.world.inventory.CraftingContainer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
@ -24,8 +23,8 @@ import net.minecraft.world.level.Level;
|
|||||||
public class DiskRecipe extends CustomRecipe {
|
public class DiskRecipe extends CustomRecipe {
|
||||||
private final Ingredient redstone;
|
private final Ingredient redstone;
|
||||||
|
|
||||||
public DiskRecipe(ResourceLocation id, CraftingBookCategory category) {
|
public DiskRecipe(CraftingBookCategory category) {
|
||||||
super(id, category);
|
super(category);
|
||||||
redstone = PlatformHelper.get().getRecipeIngredients().redstone();
|
redstone = PlatformHelper.get().getRecipeIngredients().redstone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import dan200.computercraft.shared.ModRegistry;
|
|||||||
import dan200.computercraft.shared.media.items.PrintoutItem;
|
import dan200.computercraft.shared.media.items.PrintoutItem;
|
||||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.inventory.CraftingContainer;
|
import net.minecraft.world.inventory.CraftingContainer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
@ -22,8 +21,8 @@ public final class PrintoutRecipe extends CustomRecipe {
|
|||||||
private final Ingredient leather;
|
private final Ingredient leather;
|
||||||
private final Ingredient string;
|
private final Ingredient string;
|
||||||
|
|
||||||
public PrintoutRecipe(ResourceLocation id, CraftingBookCategory category) {
|
public PrintoutRecipe(CraftingBookCategory category) {
|
||||||
super(id, category);
|
super(category);
|
||||||
|
|
||||||
var ingredients = PlatformHelper.get().getRecipeIngredients();
|
var ingredients = PlatformHelper.get().getRecipeIngredients();
|
||||||
leather = ingredients.leather();
|
leather = ingredients.leather();
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.network;
|
package dan200.computercraft.shared.network;
|
||||||
|
|
||||||
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type of message to send over the network.
|
* A type of message to send over the network.
|
||||||
* <p>
|
* <p>
|
||||||
@ -15,4 +18,11 @@ package dan200.computercraft.shared.network;
|
|||||||
* @see NetworkMessage#type()
|
* @see NetworkMessage#type()
|
||||||
*/
|
*/
|
||||||
public interface MessageType<T extends NetworkMessage<?>> {
|
public interface MessageType<T extends NetworkMessage<?>> {
|
||||||
|
/**
|
||||||
|
* Get the id of this message type. This will be used as the custom packet channel name.
|
||||||
|
*
|
||||||
|
* @return The id of this message type.
|
||||||
|
* @see CustomPacketPayload#id()
|
||||||
|
*/
|
||||||
|
ResourceLocation id();
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
|||||||
import dan200.computercraft.shared.network.client.*;
|
import dan200.computercraft.shared.network.client.*;
|
||||||
import dan200.computercraft.shared.network.server.*;
|
import dan200.computercraft.shared.network.server.*;
|
||||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
@ -21,50 +19,48 @@ import java.util.*;
|
|||||||
* @see PlatformHelper The platform helper is used to send packets.
|
* @see PlatformHelper The platform helper is used to send packets.
|
||||||
*/
|
*/
|
||||||
public final class NetworkMessages {
|
public final class NetworkMessages {
|
||||||
private static final IntSet seenIds = new IntOpenHashSet();
|
|
||||||
private static final Set<String> seenChannel = new HashSet<>();
|
private static final Set<String> seenChannel = new HashSet<>();
|
||||||
private static final List<MessageType<? extends NetworkMessage<ServerNetworkContext>>> serverMessages = new ArrayList<>();
|
private static final List<MessageType<? extends NetworkMessage<ServerNetworkContext>>> serverMessages = new ArrayList<>();
|
||||||
private static final List<MessageType<? extends NetworkMessage<ClientNetworkContext>>> clientMessages = new ArrayList<>();
|
private static final List<MessageType<? extends NetworkMessage<ClientNetworkContext>>> clientMessages = new ArrayList<>();
|
||||||
|
|
||||||
public static final MessageType<ComputerActionServerMessage> COMPUTER_ACTION = registerServerbound(0, "computer_action", ComputerActionServerMessage.class, ComputerActionServerMessage::new);
|
public static final MessageType<ComputerActionServerMessage> COMPUTER_ACTION = registerServerbound("computer_action", ComputerActionServerMessage::new);
|
||||||
public static final MessageType<QueueEventServerMessage> QUEUE_EVENT = registerServerbound(1, "queue_event", QueueEventServerMessage.class, QueueEventServerMessage::new);
|
public static final MessageType<QueueEventServerMessage> QUEUE_EVENT = registerServerbound("queue_event", QueueEventServerMessage::new);
|
||||||
public static final MessageType<KeyEventServerMessage> KEY_EVENT = registerServerbound(2, "key_event", KeyEventServerMessage.class, KeyEventServerMessage::new);
|
public static final MessageType<KeyEventServerMessage> KEY_EVENT = registerServerbound("key_event", KeyEventServerMessage::new);
|
||||||
public static final MessageType<MouseEventServerMessage> MOUSE_EVENT = registerServerbound(3, "mouse_event", MouseEventServerMessage.class, MouseEventServerMessage::new);
|
public static final MessageType<MouseEventServerMessage> MOUSE_EVENT = registerServerbound("mouse_event", MouseEventServerMessage::new);
|
||||||
public static final MessageType<UploadFileMessage> UPLOAD_FILE = registerServerbound(4, "upload_file", UploadFileMessage.class, UploadFileMessage::new);
|
public static final MessageType<UploadFileMessage> UPLOAD_FILE = registerServerbound("upload_file", UploadFileMessage::new);
|
||||||
|
|
||||||
public static final MessageType<ChatTableClientMessage> CHAT_TABLE = registerClientbound(10, "chat_table", ChatTableClientMessage.class, ChatTableClientMessage::new);
|
public static final MessageType<ChatTableClientMessage> CHAT_TABLE = registerClientbound("chat_table", ChatTableClientMessage::new);
|
||||||
public static final MessageType<PocketComputerDataMessage> POCKET_COMPUTER_DATA = registerClientbound(11, "pocket_computer_data", PocketComputerDataMessage.class, PocketComputerDataMessage::new);
|
public static final MessageType<PocketComputerDataMessage> POCKET_COMPUTER_DATA = registerClientbound("pocket_computer_data", PocketComputerDataMessage::new);
|
||||||
public static final MessageType<PocketComputerDeletedClientMessage> POCKET_COMPUTER_DELETED = registerClientbound(12, "pocket_computer_deleted", PocketComputerDeletedClientMessage.class, PocketComputerDeletedClientMessage::new);
|
public static final MessageType<PocketComputerDeletedClientMessage> POCKET_COMPUTER_DELETED = registerClientbound("pocket_computer_deleted", PocketComputerDeletedClientMessage::new);
|
||||||
public static final MessageType<ComputerTerminalClientMessage> COMPUTER_TERMINAL = registerClientbound(13, "computer_terminal", ComputerTerminalClientMessage.class, ComputerTerminalClientMessage::new);
|
public static final MessageType<ComputerTerminalClientMessage> COMPUTER_TERMINAL = registerClientbound("computer_terminal", ComputerTerminalClientMessage::new);
|
||||||
public static final MessageType<PlayRecordClientMessage> PLAY_RECORD = registerClientbound(14, "play_record", PlayRecordClientMessage.class, PlayRecordClientMessage::new);
|
public static final MessageType<PlayRecordClientMessage> PLAY_RECORD = registerClientbound("play_record", PlayRecordClientMessage::new);
|
||||||
public static final MessageType<MonitorClientMessage> MONITOR_CLIENT = registerClientbound(15, "monitor_client", MonitorClientMessage.class, MonitorClientMessage::new);
|
public static final MessageType<MonitorClientMessage> MONITOR_CLIENT = registerClientbound("monitor_client", MonitorClientMessage::new);
|
||||||
public static final MessageType<SpeakerAudioClientMessage> SPEAKER_AUDIO = registerClientbound(16, "speaker_audio", SpeakerAudioClientMessage.class, SpeakerAudioClientMessage::new);
|
public static final MessageType<SpeakerAudioClientMessage> SPEAKER_AUDIO = registerClientbound("speaker_audio", SpeakerAudioClientMessage::new);
|
||||||
public static final MessageType<SpeakerMoveClientMessage> SPEAKER_MOVE = registerClientbound(17, "speaker_move", SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new);
|
public static final MessageType<SpeakerMoveClientMessage> SPEAKER_MOVE = registerClientbound("speaker_move", SpeakerMoveClientMessage::new);
|
||||||
public static final MessageType<SpeakerPlayClientMessage> SPEAKER_PLAY = registerClientbound(18, "speaker_play", SpeakerPlayClientMessage.class, SpeakerPlayClientMessage::new);
|
public static final MessageType<SpeakerPlayClientMessage> SPEAKER_PLAY = registerClientbound("speaker_play", SpeakerPlayClientMessage::new);
|
||||||
public static final MessageType<SpeakerStopClientMessage> SPEAKER_STOP = registerClientbound(19, "speaker_stop", SpeakerStopClientMessage.class, SpeakerStopClientMessage::new);
|
public static final MessageType<SpeakerStopClientMessage> SPEAKER_STOP = registerClientbound("speaker_stop", SpeakerStopClientMessage::new);
|
||||||
public static final MessageType<UploadResultMessage> UPLOAD_RESULT = registerClientbound(20, "upload_result", UploadResultMessage.class, UploadResultMessage::new);
|
public static final MessageType<UploadResultMessage> UPLOAD_RESULT = registerClientbound("upload_result", UploadResultMessage::new);
|
||||||
public static final MessageType<UpgradesLoadedMessage> UPGRADES_LOADED = registerClientbound(21, "upgrades_loaded", UpgradesLoadedMessage.class, UpgradesLoadedMessage::new);
|
public static final MessageType<UpgradesLoadedMessage> UPGRADES_LOADED = registerClientbound("upgrades_loaded", UpgradesLoadedMessage::new);
|
||||||
|
|
||||||
private NetworkMessages() {
|
private NetworkMessages() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <C, T extends NetworkMessage<C>> MessageType<T> register(
|
private static <C, T extends NetworkMessage<C>> MessageType<T> register(
|
||||||
List<MessageType<? extends NetworkMessage<C>>> messages,
|
List<MessageType<? extends NetworkMessage<C>>> messages,
|
||||||
int id, String channel, Class<T> klass, FriendlyByteBuf.Reader<T> reader
|
String channel, FriendlyByteBuf.Reader<T> reader
|
||||||
) {
|
) {
|
||||||
if (!seenIds.add(id)) throw new IllegalArgumentException("Duplicate id " + id);
|
|
||||||
if (!seenChannel.add(channel)) throw new IllegalArgumentException("Duplicate channel " + channel);
|
if (!seenChannel.add(channel)) throw new IllegalArgumentException("Duplicate channel " + channel);
|
||||||
var type = PlatformHelper.get().createMessageType(id, new ResourceLocation(ComputerCraftAPI.MOD_ID, channel), klass, reader);
|
var type = PlatformHelper.get().createMessageType(new ResourceLocation(ComputerCraftAPI.MOD_ID, channel), reader);
|
||||||
messages.add(type);
|
messages.add(type);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T extends NetworkMessage<ServerNetworkContext>> MessageType<T> registerServerbound(int id, String channel, Class<T> klass, FriendlyByteBuf.Reader<T> reader) {
|
private static <T extends NetworkMessage<ServerNetworkContext>> MessageType<T> registerServerbound(String id, FriendlyByteBuf.Reader<T> reader) {
|
||||||
return register(serverMessages, id, channel, klass, reader);
|
return register(serverMessages, id, reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T extends NetworkMessage<ClientNetworkContext>> MessageType<T> registerClientbound(int id, String channel, Class<T> klass, FriendlyByteBuf.Reader<T> reader) {
|
private static <T extends NetworkMessage<ClientNetworkContext>> MessageType<T> registerClientbound(String id, FriendlyByteBuf.Reader<T> reader) {
|
||||||
return register(clientMessages, id, channel, klass, reader);
|
return register(clientMessages, id, reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,18 +5,16 @@
|
|||||||
package dan200.computercraft.shared.network.client;
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
|
||||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||||
import dan200.computercraft.impl.PocketUpgrades;
|
import dan200.computercraft.impl.PocketUpgrades;
|
||||||
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import dan200.computercraft.impl.TurtleUpgrades;
|
import dan200.computercraft.impl.TurtleUpgrades;
|
||||||
import dan200.computercraft.impl.UpgradeManager;
|
import dan200.computercraft.impl.UpgradeManager;
|
||||||
import dan200.computercraft.shared.network.MessageType;
|
import dan200.computercraft.shared.network.MessageType;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
import dan200.computercraft.shared.network.NetworkMessages;
|
import dan200.computercraft.shared.network.NetworkMessages;
|
||||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
@ -24,14 +22,13 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syncs turtle and pocket upgrades to the client.
|
* Syncs turtle and pocket upgrades to the client.
|
||||||
*/
|
*/
|
||||||
public final class UpgradesLoadedMessage implements NetworkMessage<ClientNetworkContext> {
|
public final class UpgradesLoadedMessage implements NetworkMessage<ClientNetworkContext> {
|
||||||
private final Map<String, UpgradeManager.UpgradeWrapper<TurtleUpgradeSerialiser<?>, ITurtleUpgrade>> turtleUpgrades;
|
private final Map<String, UpgradeManager.UpgradeWrapper<ITurtleUpgrade>> turtleUpgrades;
|
||||||
private final Map<String, UpgradeManager.UpgradeWrapper<PocketUpgradeSerialiser<?>, IPocketUpgrade>> pocketUpgrades;
|
private final Map<String, UpgradeManager.UpgradeWrapper<IPocketUpgrade>> pocketUpgrades;
|
||||||
|
|
||||||
public UpgradesLoadedMessage() {
|
public UpgradesLoadedMessage() {
|
||||||
turtleUpgrades = TurtleUpgrades.instance().getUpgradeWrappers();
|
turtleUpgrades = TurtleUpgrades.instance().getUpgradeWrappers();
|
||||||
@ -39,28 +36,28 @@ public final class UpgradesLoadedMessage implements NetworkMessage<ClientNetwork
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UpgradesLoadedMessage(FriendlyByteBuf buf) {
|
public UpgradesLoadedMessage(FriendlyByteBuf buf) {
|
||||||
turtleUpgrades = fromBytes(buf, TurtleUpgradeSerialiser.registryId());
|
turtleUpgrades = fromBytes(buf, ITurtleUpgrade.serialiserRegistryKey());
|
||||||
pocketUpgrades = fromBytes(buf, PocketUpgradeSerialiser.registryId());
|
pocketUpgrades = fromBytes(buf, IPocketUpgrade.serialiserRegistryKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
private <R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase> Map<String, UpgradeManager.UpgradeWrapper<R, T>> fromBytes(
|
private <T extends UpgradeBase> Map<String, UpgradeManager.UpgradeWrapper<T>> fromBytes(
|
||||||
FriendlyByteBuf buf, ResourceKey<Registry<R>> registryKey
|
FriendlyByteBuf buf, ResourceKey<Registry<UpgradeSerialiser<? extends T>>> registryKey
|
||||||
) {
|
) {
|
||||||
var registry = PlatformHelper.get().wrap(registryKey);
|
var registry = RegistryHelper.getRegistry(registryKey);
|
||||||
|
|
||||||
var size = buf.readVarInt();
|
var size = buf.readVarInt();
|
||||||
Map<String, UpgradeManager.UpgradeWrapper<R, T>> upgrades = new HashMap<>(size);
|
Map<String, UpgradeManager.UpgradeWrapper<T>> upgrades = new HashMap<>(size);
|
||||||
for (var i = 0; i < size; i++) {
|
for (var i = 0; i < size; i++) {
|
||||||
var id = buf.readUtf();
|
var id = buf.readUtf();
|
||||||
|
|
||||||
var serialiserId = buf.readResourceLocation();
|
var serialiserId = buf.readResourceLocation();
|
||||||
var serialiser = registry.tryGet(serialiserId);
|
var serialiser = registry.get(serialiserId);
|
||||||
if (serialiser == null) throw new IllegalStateException("Unknown serialiser " + serialiserId);
|
if (serialiser == null) throw new IllegalStateException("Unknown serialiser " + serialiserId);
|
||||||
|
|
||||||
var upgrade = serialiser.fromNetwork(new ResourceLocation(id), buf);
|
var upgrade = serialiser.fromNetwork(new ResourceLocation(id), buf);
|
||||||
var modId = buf.readUtf();
|
var modId = buf.readUtf();
|
||||||
|
|
||||||
upgrades.put(id, new UpgradeManager.UpgradeWrapper<R, T>(id, upgrade, serialiser, modId));
|
upgrades.put(id, new UpgradeManager.UpgradeWrapper<T>(id, upgrade, serialiser, modId));
|
||||||
}
|
}
|
||||||
|
|
||||||
return upgrades;
|
return upgrades;
|
||||||
@ -68,14 +65,14 @@ public final class UpgradesLoadedMessage implements NetworkMessage<ClientNetwork
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(FriendlyByteBuf buf) {
|
public void write(FriendlyByteBuf buf) {
|
||||||
toBytes(buf, TurtleUpgradeSerialiser.registryId(), turtleUpgrades);
|
toBytes(buf, ITurtleUpgrade.serialiserRegistryKey(), turtleUpgrades);
|
||||||
toBytes(buf, PocketUpgradeSerialiser.registryId(), pocketUpgrades);
|
toBytes(buf, IPocketUpgrade.serialiserRegistryKey(), pocketUpgrades);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase> void toBytes(
|
private <T extends UpgradeBase> void toBytes(
|
||||||
FriendlyByteBuf buf, ResourceKey<Registry<R>> registryKey, Map<String, UpgradeManager.UpgradeWrapper<R, T>> upgrades
|
FriendlyByteBuf buf, ResourceKey<Registry<UpgradeSerialiser<? extends T>>> registryKey, Map<String, UpgradeManager.UpgradeWrapper<T>> upgrades
|
||||||
) {
|
) {
|
||||||
var registry = PlatformHelper.get().wrap(registryKey);
|
var registry = RegistryHelper.getRegistry(registryKey);
|
||||||
|
|
||||||
buf.writeVarInt(upgrades.size());
|
buf.writeVarInt(upgrades.size());
|
||||||
for (var entry : upgrades.entrySet()) {
|
for (var entry : upgrades.entrySet()) {
|
||||||
@ -85,7 +82,7 @@ public final class UpgradesLoadedMessage implements NetworkMessage<ClientNetwork
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
var unwrappedSerialiser = (UpgradeSerialiser<T>) serialiser;
|
var unwrappedSerialiser = (UpgradeSerialiser<T>) serialiser;
|
||||||
|
|
||||||
buf.writeResourceLocation(Objects.requireNonNull(registry.getKey(serialiser), "Serialiser is not registered!"));
|
buf.writeResourceLocation(RegistryHelper.getKeyOrThrow(registry, serialiser));
|
||||||
unwrappedSerialiser.toNetwork(buf, entry.getValue().upgrade());
|
unwrappedSerialiser.toNetwork(buf, entry.getValue().upgrade());
|
||||||
|
|
||||||
buf.writeUtf(entry.getValue().modId());
|
buf.writeUtf(entry.getValue().modId());
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.diskdrive;
|
package dan200.computercraft.shared.peripheral.diskdrive;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
import dan200.computercraft.impl.MediaProviders;
|
import dan200.computercraft.impl.MediaProviders;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.common.HorizontalContainerBlock;
|
import dan200.computercraft.shared.common.HorizontalContainerBlock;
|
||||||
@ -26,6 +27,8 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class DiskDriveBlock extends HorizontalContainerBlock {
|
public class DiskDriveBlock extends HorizontalContainerBlock {
|
||||||
|
private static final MapCodec<DiskDriveBlock> CODEC = simpleCodec(DiskDriveBlock::new);
|
||||||
|
|
||||||
public static final EnumProperty<DiskDriveState> STATE = EnumProperty.create("state", DiskDriveState.class);
|
public static final EnumProperty<DiskDriveState> STATE = EnumProperty.create("state", DiskDriveState.class);
|
||||||
|
|
||||||
private static final BlockEntityTicker<DiskDriveBlockEntity> serverTicker = (level, pos, state, drive) -> drive.serverTick();
|
private static final BlockEntityTicker<DiskDriveBlockEntity> serverTicker = (level, pos, state, drive) -> drive.serverTick();
|
||||||
@ -43,6 +46,11 @@ public class DiskDriveBlock extends HorizontalContainerBlock {
|
|||||||
properties.add(FACING, STATE);
|
properties.add(FACING, STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
|
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
|
||||||
|
@ -15,10 +15,8 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* Extract some component (for instance a capability on Forge, or a {@code BlockApiLookup} on Fabric) from a block and
|
* Extract some component (for instance a capability on Forge, or a {@code BlockApiLookup} on Fabric) from a block and
|
||||||
* block entity.
|
* block entity.
|
||||||
*
|
|
||||||
* @param <C> A platform-specific type, used for the invalidation callback.
|
|
||||||
*/
|
*/
|
||||||
public interface ComponentLookup<C extends Runnable> {
|
public interface ComponentLookup {
|
||||||
/**
|
/**
|
||||||
* Extract some component from a block in the world.
|
* Extract some component from a block in the world.
|
||||||
*
|
*
|
||||||
@ -28,9 +26,8 @@ public interface ComponentLookup<C extends Runnable> {
|
|||||||
* @param blockEntity The block entity at that position.
|
* @param blockEntity The block entity at that position.
|
||||||
* @param side The side of the block to extract the component from. Implementations should try to use a
|
* @param side The side of the block to extract the component from. Implementations should try to use a
|
||||||
* sideless lookup first, but may fall back to a sided lookup if needed.
|
* sideless lookup first, but may fall back to a sided lookup if needed.
|
||||||
* @param invalidate An invalidation function to call if this component changes.
|
|
||||||
* @return The found component, or {@code null} if not present.
|
* @return The found component, or {@code null} if not present.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
Object find(ServerLevel level, BlockPos pos, BlockState state, BlockEntity blockEntity, Direction side, C invalidate);
|
Object find(ServerLevel level, BlockPos pos, BlockState state, BlockEntity blockEntity, Direction side);
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,9 @@ import dan200.computercraft.api.lua.MethodResult;
|
|||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -29,7 +30,7 @@ public final class GenericPeripheral implements IDynamicPeripheral {
|
|||||||
|
|
||||||
GenericPeripheral(BlockEntity tile, Direction side, @Nullable String name, Set<String> additionalTypes, List<SaturatedMethod> methods) {
|
GenericPeripheral(BlockEntity tile, Direction side, @Nullable String name, Set<String> additionalTypes, List<SaturatedMethod> methods) {
|
||||||
this.side = side;
|
this.side = side;
|
||||||
var type = RegistryWrappers.BLOCK_ENTITY_TYPES.getKey(tile.getType());
|
var type = RegistryHelper.getKeyOrThrow(BuiltInRegistries.BLOCK_ENTITY_TYPE, tile.getType());
|
||||||
this.tile = tile;
|
this.tile = tile;
|
||||||
this.type = name != null ? name : type.toString();
|
this.type = name != null ? name : type.toString();
|
||||||
this.additionalTypes = additionalTypes;
|
this.additionalTypes = additionalTypes;
|
||||||
|
@ -13,8 +13,6 @@ import net.minecraft.core.BlockPos;
|
|||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -25,39 +23,35 @@ import java.util.Objects;
|
|||||||
* A peripheral provider which finds methods from various {@linkplain GenericSource generic sources}.
|
* A peripheral provider which finds methods from various {@linkplain GenericSource generic sources}.
|
||||||
* <p>
|
* <p>
|
||||||
* Methods are found using the original block entity itself and a registered list of {@link ComponentLookup}s.
|
* Methods are found using the original block entity itself and a registered list of {@link ComponentLookup}s.
|
||||||
*
|
|
||||||
* @param <C> A platform-specific type, used for the invalidation callback.
|
|
||||||
*/
|
*/
|
||||||
public final class GenericPeripheralProvider<C extends Runnable> {
|
public final class GenericPeripheralProvider {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(GenericPeripheralProvider.class);
|
private final List<ComponentLookup> lookups = new ArrayList<>();
|
||||||
|
|
||||||
private final List<ComponentLookup<? super C>> lookups = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a component lookup function.
|
* Register a component lookup function.
|
||||||
*
|
*
|
||||||
* @param lookup The component lookup function.
|
* @param lookup The component lookup function.
|
||||||
*/
|
*/
|
||||||
public synchronized void registerLookup(ComponentLookup<? super C> lookup) {
|
public synchronized void registerLookup(ComponentLookup lookup) {
|
||||||
Objects.requireNonNull(lookup);
|
Objects.requireNonNull(lookup);
|
||||||
if (!lookups.contains(lookup)) lookups.add(lookup);
|
if (!lookups.contains(lookup)) lookups.add(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forEachMethod(MethodSupplier<PeripheralMethod> methods, ServerLevel level, BlockPos pos, Direction side, BlockEntity blockEntity, C invalidate, MethodSupplier.TargetedConsumer<PeripheralMethod> consumer) {
|
public void forEachMethod(MethodSupplier<PeripheralMethod> methods, ServerLevel level, BlockPos pos, Direction side, BlockEntity blockEntity, MethodSupplier.TargetedConsumer<PeripheralMethod> consumer) {
|
||||||
methods.forEachMethod(blockEntity, consumer);
|
methods.forEachMethod(blockEntity, consumer);
|
||||||
|
|
||||||
for (var lookup : lookups) {
|
for (var lookup : lookups) {
|
||||||
var contents = lookup.find(level, pos, blockEntity.getBlockState(), blockEntity, side, invalidate);
|
var contents = lookup.find(level, pos, blockEntity.getBlockState(), blockEntity, side);
|
||||||
if (contents != null) methods.forEachMethod(contents, consumer);
|
if (contents != null) methods.forEachMethod(contents, consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public IPeripheral getPeripheral(ServerLevel level, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity, C invalidate) {
|
public IPeripheral getPeripheral(ServerLevel level, BlockPos pos, Direction side, @Nullable BlockEntity blockEntity) {
|
||||||
if (blockEntity == null) return null;
|
if (blockEntity == null) return null;
|
||||||
|
|
||||||
var builder = new GenericPeripheralBuilder();
|
var builder = new GenericPeripheralBuilder();
|
||||||
forEachMethod(ServerContext.get(level.getServer()).peripheralMethods(), level, pos, side, blockEntity, invalidate, builder::addMethod);
|
forEachMethod(ServerContext.get(level.getServer()).peripheralMethods(), level, pos, side, blockEntity, builder::addMethod);
|
||||||
return builder.toPeripheral(blockEntity, side);
|
return builder.toPeripheral(blockEntity, side);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,17 +75,14 @@ public abstract class AbstractInventoryMethods<T> implements GenericPeripheral {
|
|||||||
* <p>
|
* <p>
|
||||||
* The returned information contains the same information as each item in
|
* The returned information contains the same information as each item in
|
||||||
* {@link #list}, as well as additional details like the display name
|
* {@link #list}, as well as additional details like the display name
|
||||||
* (`displayName`), and item and item durability (`damage`, `maxDamage`, `durability`).
|
* (`displayName`), item groups (`itemGroups`), which are the creative tabs
|
||||||
|
* an item will appear under, and item and item durability (`damage`,
|
||||||
|
* `maxDamage`, `durability`).
|
||||||
* <p>
|
* <p>
|
||||||
* Some items include more information (such as enchantments) - it is
|
* Some items include more information (such as enchantments) - it is
|
||||||
* recommended to print it out using [`textutils.serialize`] or in the Lua
|
* recommended to print it out using [`textutils.serialize`] or in the Lua
|
||||||
* REPL, to explore what is available.
|
* REPL, to explore what is available.
|
||||||
* <p>
|
* <p>
|
||||||
* > [Deprecated fields][!INFO]
|
|
||||||
* > Older versions of CC: Tweaked exposed an {@code itemGroups} field, listing the
|
|
||||||
* > creative tabs an item was available under. This information is no longer available on
|
|
||||||
* > more recent versions of the game, and so this field will always be empty. Do not use this
|
|
||||||
* > field in new code!
|
|
||||||
*
|
*
|
||||||
* @param inventory The current inventory.
|
* @param inventory The current inventory.
|
||||||
* @param slot The slot to get information about.
|
* @param slot The slot to get information about.
|
||||||
|
@ -140,12 +140,12 @@ public class CableBlock extends Block implements SimpleWaterloggedBlock, EntityB
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
|
public ItemStack getCloneItemStack(LevelReader world, BlockPos pos, BlockState state) {
|
||||||
return state.getValue(CABLE) ? new ItemStack(ModRegistry.Items.CABLE.get()) : new ItemStack(ModRegistry.Items.WIRED_MODEM.get());
|
return state.getValue(CABLE) ? new ItemStack(ModRegistry.Items.CABLE.get()) : new ItemStack(ModRegistry.Items.WIRED_MODEM.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForgeOverride
|
@ForgeOverride
|
||||||
public ItemStack getCloneItemStack(BlockState state, @Nullable HitResult hit, BlockGetter world, BlockPos pos, Player player) {
|
public ItemStack getCloneItemStack(BlockState state, @Nullable HitResult hit, LevelReader world, BlockPos pos, Player player) {
|
||||||
var modem = state.getValue(MODEM).getFacing();
|
var modem = state.getValue(MODEM).getFacing();
|
||||||
boolean cable = state.getValue(CABLE);
|
boolean cable = state.getValue(CABLE);
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ public class CableBlockEntity extends BlockEntity {
|
|||||||
private boolean invalidPeripheral;
|
private boolean invalidPeripheral;
|
||||||
private boolean peripheralAccessAllowed;
|
private boolean peripheralAccessAllowed;
|
||||||
private final WiredModemLocalPeripheral peripheral = new WiredModemLocalPeripheral(PlatformHelper.get().createPeripheralAccess(this, x -> queueRefreshPeripheral()));
|
private final WiredModemLocalPeripheral peripheral = new WiredModemLocalPeripheral(PlatformHelper.get().createPeripheralAccess(this, x -> queueRefreshPeripheral()));
|
||||||
private @Nullable Runnable modemChanged;
|
|
||||||
|
|
||||||
private boolean connectionsFormed = false;
|
private boolean connectionsFormed = false;
|
||||||
private boolean connectionsChanged = false;
|
private boolean connectionsChanged = false;
|
||||||
@ -121,7 +120,7 @@ public class CableBlockEntity extends BlockEntity {
|
|||||||
super.setBlockState(state);
|
super.setBlockState(state);
|
||||||
|
|
||||||
// We invalidate both the modem and element if the modem's direction is different.
|
// We invalidate both the modem and element if the modem's direction is different.
|
||||||
if (getMaybeDirection() != direction && modemChanged != null) modemChanged.run();
|
if (getMaybeDirection() != direction) PlatformHelper.get().invalidateComponent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -273,7 +272,7 @@ public class CableBlockEntity extends BlockEntity {
|
|||||||
|
|
||||||
void modemChanged() {
|
void modemChanged() {
|
||||||
// Tell anyone who cares that the connection state has changed
|
// Tell anyone who cares that the connection state has changed
|
||||||
if (modemChanged != null) modemChanged.run();
|
PlatformHelper.get().invalidateComponent(this);
|
||||||
|
|
||||||
if (getLevel().isClientSide) return;
|
if (getLevel().isClientSide) return;
|
||||||
|
|
||||||
@ -326,10 +325,6 @@ public class CableBlockEntity extends BlockEntity {
|
|||||||
return direction == null || getMaybeDirection() == direction ? modem : null;
|
return direction == null || getMaybeDirection() == direction ? modem : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onModemChanged(Runnable callback) {
|
|
||||||
modemChanged = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasCable() {
|
boolean hasCable() {
|
||||||
return getBlockState().getValue(CableBlock.CABLE);
|
return getBlockState().getValue(CableBlock.CABLE);
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.modem.wired;
|
package dan200.computercraft.shared.peripheral.modem.wired;
|
||||||
|
|
||||||
|
import dan200.computercraft.impl.RegistryHelper;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.sounds.SoundSource;
|
import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.item.BlockItem;
|
import net.minecraft.world.item.BlockItem;
|
||||||
@ -50,7 +51,7 @@ public abstract class CableBlockItem extends BlockItem {
|
|||||||
@Override
|
@Override
|
||||||
public String getDescriptionId() {
|
public String getDescriptionId() {
|
||||||
if (translationKey == null) {
|
if (translationKey == null) {
|
||||||
translationKey = Util.makeDescriptionId("block", RegistryWrappers.ITEMS.getKey(this));
|
translationKey = Util.makeDescriptionId("block", RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, this));
|
||||||
}
|
}
|
||||||
return translationKey;
|
return translationKey;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.modem.wireless;
|
package dan200.computercraft.shared.peripheral.modem.wireless;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
import dan200.computercraft.shared.peripheral.modem.ModemShapes;
|
import dan200.computercraft.shared.peripheral.modem.ModemShapes;
|
||||||
import dan200.computercraft.shared.platform.RegistryEntry;
|
import dan200.computercraft.shared.platform.RegistryEntry;
|
||||||
|
import dan200.computercraft.shared.util.BlockCodecs;
|
||||||
import dan200.computercraft.shared.util.WaterloggableHelpers;
|
import dan200.computercraft.shared.util.WaterloggableHelpers;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
@ -31,6 +33,8 @@ import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED;
|
|||||||
import static dan200.computercraft.shared.util.WaterloggableHelpers.getFluidStateForPlacement;
|
import static dan200.computercraft.shared.util.WaterloggableHelpers.getFluidStateForPlacement;
|
||||||
|
|
||||||
public class WirelessModemBlock extends DirectionalBlock implements SimpleWaterloggedBlock, EntityBlock {
|
public class WirelessModemBlock extends DirectionalBlock implements SimpleWaterloggedBlock, EntityBlock {
|
||||||
|
private static final MapCodec<WirelessModemBlock> CODEC = BlockCodecs.blockWithBlockEntityCodec(WirelessModemBlock::new, x -> x.type);
|
||||||
|
|
||||||
public static final BooleanProperty ON = BooleanProperty.create("on");
|
public static final BooleanProperty ON = BooleanProperty.create("on");
|
||||||
|
|
||||||
private final RegistryEntry<? extends BlockEntityType<? extends WirelessModemBlockEntity>> type;
|
private final RegistryEntry<? extends BlockEntityType<? extends WirelessModemBlockEntity>> type;
|
||||||
@ -50,6 +54,11 @@ public class WirelessModemBlock extends DirectionalBlock implements SimpleWaterl
|
|||||||
builder.add(FACING, ON, WATERLOGGED);
|
builder.add(FACING, ON, WATERLOGGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MapCodec<? extends WirelessModemBlock> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public VoxelShape getShape(BlockState blockState, BlockGetter blockView, BlockPos blockPos, CollisionContext context) {
|
public VoxelShape getShape(BlockState blockState, BlockGetter blockView, BlockPos blockPos, CollisionContext context) {
|
||||||
|
@ -7,6 +7,7 @@ package dan200.computercraft.shared.peripheral.modem.wireless;
|
|||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.shared.peripheral.modem.ModemPeripheral;
|
import dan200.computercraft.shared.peripheral.modem.ModemPeripheral;
|
||||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||||
|
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||||
import dan200.computercraft.shared.util.TickScheduler;
|
import dan200.computercraft.shared.util.TickScheduler;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
@ -51,7 +52,6 @@ public class WirelessModemBlockEntity extends BlockEntity {
|
|||||||
private final boolean advanced;
|
private final boolean advanced;
|
||||||
|
|
||||||
private final ModemPeripheral modem;
|
private final ModemPeripheral modem;
|
||||||
private @Nullable Runnable modemChanged;
|
|
||||||
private final TickScheduler.Token tickToken = new TickScheduler.Token(this);
|
private final TickScheduler.Token tickToken = new TickScheduler.Token(this);
|
||||||
|
|
||||||
public WirelessModemBlockEntity(BlockEntityType<? extends WirelessModemBlockEntity> type, BlockPos pos, BlockState state, boolean advanced) {
|
public WirelessModemBlockEntity(BlockEntityType<? extends WirelessModemBlockEntity> type, BlockPos pos, BlockState state, boolean advanced) {
|
||||||
@ -77,7 +77,7 @@ public class WirelessModemBlockEntity extends BlockEntity {
|
|||||||
public void setBlockState(BlockState state) {
|
public void setBlockState(BlockState state) {
|
||||||
var direction = getDirection();
|
var direction = getDirection();
|
||||||
super.setBlockState(state);
|
super.setBlockState(state);
|
||||||
if (getDirection() != direction && modemChanged != null) modemChanged.run();
|
if (getDirection() != direction) PlatformHelper.get().invalidateComponent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockTick() {
|
void blockTick() {
|
||||||
@ -100,8 +100,4 @@ public class WirelessModemBlockEntity extends BlockEntity {
|
|||||||
public IPeripheral getPeripheral(@Nullable Direction direction) {
|
public IPeripheral getPeripheral(@Nullable Direction direction) {
|
||||||
return direction == null || getDirection() == direction ? modem : null;
|
return direction == null || getDirection() == direction ? modem : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onModemChanged(Runnable callback) {
|
|
||||||
modemChanged = callback;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.monitor;
|
package dan200.computercraft.shared.peripheral.monitor;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||||
import dan200.computercraft.shared.platform.RegistryEntry;
|
import dan200.computercraft.shared.platform.RegistryEntry;
|
||||||
|
import dan200.computercraft.shared.util.BlockCodecs;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
@ -33,6 +35,8 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class MonitorBlock extends HorizontalDirectionalBlock implements EntityBlock {
|
public class MonitorBlock extends HorizontalDirectionalBlock implements EntityBlock {
|
||||||
|
private static final MapCodec<MonitorBlock> CODEC = BlockCodecs.blockWithBlockEntityCodec(MonitorBlock::new, x -> x.type);
|
||||||
|
|
||||||
public static final DirectionProperty ORIENTATION = DirectionProperty.create("orientation",
|
public static final DirectionProperty ORIENTATION = DirectionProperty.create("orientation",
|
||||||
Direction.UP, Direction.DOWN, Direction.NORTH);
|
Direction.UP, Direction.DOWN, Direction.NORTH);
|
||||||
|
|
||||||
@ -57,6 +61,11 @@ public class MonitorBlock extends HorizontalDirectionalBlock implements EntityBl
|
|||||||
builder.add(ORIENTATION, FACING, STATE);
|
builder.add(ORIENTATION, FACING, STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MapCodec<? extends MonitorBlock> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
package dan200.computercraft.shared.peripheral.monitor;
|
package dan200.computercraft.shared.peripheral.monitor;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import dan200.computercraft.annotations.ForgeOverride;
|
|
||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
@ -507,7 +506,6 @@ public class MonitorBlockEntity extends BlockEntity {
|
|||||||
computers.remove(computer);
|
computers.remove(computer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForgeOverride
|
|
||||||
public AABB getRenderBoundingBox() {
|
public AABB getRenderBoundingBox() {
|
||||||
// We attempt to cache the bounding box to save having to do property lookups (and allocations!) on every frame.
|
// We attempt to cache the bounding box to save having to do property lookups (and allocations!) on every frame.
|
||||||
// Unfortunately the AABB does depend on quite a lot of state, so we need to add a bunch of extra fields -
|
// Unfortunately the AABB does depend on quite a lot of state, so we need to add a bunch of extra fields -
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.printer;
|
package dan200.computercraft.shared.peripheral.printer;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.common.HorizontalContainerBlock;
|
import dan200.computercraft.shared.common.HorizontalContainerBlock;
|
||||||
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.block.BaseEntityBlock;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
@ -17,6 +19,8 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class PrinterBlock extends HorizontalContainerBlock {
|
public class PrinterBlock extends HorizontalContainerBlock {
|
||||||
|
private static final MapCodec<PrinterBlock> CODEC = simpleCodec(PrinterBlock::new);
|
||||||
|
|
||||||
public static final BooleanProperty TOP = BooleanProperty.create("top");
|
public static final BooleanProperty TOP = BooleanProperty.create("top");
|
||||||
public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
|
public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
|
||||||
|
|
||||||
@ -33,6 +37,11 @@ public class PrinterBlock extends HorizontalContainerBlock {
|
|||||||
properties.add(FACING, TOP, BOTTOM);
|
properties.add(FACING, TOP, BOTTOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.peripheral.speaker;
|
package dan200.computercraft.shared.peripheral.speaker;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.util.BlockEntityHelpers;
|
import dan200.computercraft.shared.util.BlockEntityHelpers;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
@ -22,6 +23,7 @@ import net.minecraft.world.level.block.state.StateDefinition;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class SpeakerBlock extends HorizontalDirectionalBlock implements EntityBlock {
|
public class SpeakerBlock extends HorizontalDirectionalBlock implements EntityBlock {
|
||||||
|
private static final MapCodec<SpeakerBlock> CODEC = simpleCodec(SpeakerBlock::new);
|
||||||
private static final BlockEntityTicker<SpeakerBlockEntity> serverTicker = (level, pos, state, drive) -> drive.serverTick();
|
private static final BlockEntityTicker<SpeakerBlockEntity> serverTicker = (level, pos, state, drive) -> drive.serverTick();
|
||||||
|
|
||||||
public SpeakerBlock(Properties settings) {
|
public SpeakerBlock(Properties settings) {
|
||||||
@ -35,6 +37,11 @@ public class SpeakerBlock extends HorizontalDirectionalBlock implements EntityBl
|
|||||||
properties.add(FACING);
|
properties.add(FACING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MapCodec<? extends SpeakerBlock> codec() {
|
||||||
|
return CODEC;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockState getStateForPlacement(BlockPlaceContext placement) {
|
public BlockState getStateForPlacement(BlockPlaceContext placement) {
|
||||||
|
@ -21,7 +21,7 @@ import net.minecraft.core.Direction;
|
|||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.protocol.Packet;
|
import net.minecraft.network.protocol.Packet;
|
||||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
import net.minecraft.network.protocol.common.ClientCommonPacketListener;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
@ -83,15 +83,6 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
|
|||||||
*/
|
*/
|
||||||
ConfigFile.Builder createConfigBuilder();
|
ConfigFile.Builder createConfigBuilder();
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap a Minecraft registry in our own abstraction layer.
|
|
||||||
*
|
|
||||||
* @param registry The registry to wrap.
|
|
||||||
* @param <T> The type of object stored in this registry.
|
|
||||||
* @return The wrapped registry.
|
|
||||||
*/
|
|
||||||
<T> RegistryWrappers.RegistryWrapper<T> wrap(ResourceKey<Registry<T>> registry);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a registration helper for a specific registry.
|
* Create a registration helper for a specific registry.
|
||||||
*
|
*
|
||||||
@ -101,17 +92,6 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
|
|||||||
*/
|
*/
|
||||||
<T> RegistrationHelper<T> createRegistrationHelper(ResourceKey<Registry<T>> registry);
|
<T> RegistrationHelper<T> createRegistrationHelper(ResourceKey<Registry<T>> registry);
|
||||||
|
|
||||||
/**
|
|
||||||
* A version of {@link #getRegistryObject(ResourceKey, ResourceLocation)} which allows missing entries.
|
|
||||||
*
|
|
||||||
* @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 registered object or {@code null}.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
<T> T tryGetRegistryObject(ResourceKey<Registry<T>> registry, ResourceLocation id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if this resource should be loaded, based on platform-specific loot conditions.
|
* Determine if this resource should be loaded, based on platform-specific loot conditions.
|
||||||
* <p>
|
* <p>
|
||||||
@ -167,14 +147,12 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
|
|||||||
/**
|
/**
|
||||||
* Create a new {@link MessageType}.
|
* Create a new {@link MessageType}.
|
||||||
*
|
*
|
||||||
* @param id The descriminator for this message type.
|
* @param <T> The type of this message.
|
||||||
* @param channel The channel name for this message type.
|
* @param id The id for this message type.
|
||||||
* @param klass The type of this message.
|
* @param reader The function which reads the packet from a buffer. Should be the inverse to {@link NetworkMessage#write(FriendlyByteBuf)}.
|
||||||
* @param reader The function which reads the packet from a buffer. Should be the inverse to {@link NetworkMessage#write(FriendlyByteBuf)}.
|
|
||||||
* @param <T> The type of this message.
|
|
||||||
* @return The new {@link MessageType} instance.
|
* @return The new {@link MessageType} instance.
|
||||||
*/
|
*/
|
||||||
<T extends NetworkMessage<?>> MessageType<T> createMessageType(int id, ResourceLocation channel, Class<T> klass, FriendlyByteBuf.Reader<T> reader);
|
<T extends NetworkMessage<?>> MessageType<T> createMessageType(ResourceLocation id, FriendlyByteBuf.Reader<T> reader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a clientbound {@link NetworkMessage} to a Minecraft {@link Packet}.
|
* Convert a clientbound {@link NetworkMessage} to a Minecraft {@link Packet}.
|
||||||
@ -182,7 +160,15 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
|
|||||||
* @param message The messsge to convert.
|
* @param message The messsge to convert.
|
||||||
* @return The converted message.
|
* @return The converted message.
|
||||||
*/
|
*/
|
||||||
Packet<ClientGamePacketListener> createPacket(NetworkMessage<ClientNetworkContext> message);
|
Packet<ClientCommonPacketListener> createPacket(NetworkMessage<ClientNetworkContext> message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate components on a block enitty.
|
||||||
|
*
|
||||||
|
* @param owner The block entity whose components should be invalidated.
|
||||||
|
*/
|
||||||
|
default void invalidateComponent(BlockEntity owner) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link ComponentAccess} for surrounding peripherals.
|
* Create a {@link ComponentAccess} for surrounding peripherals.
|
||||||
@ -334,7 +320,7 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
|
|||||||
* @return The distance (in blocks) that a player can reach.
|
* @return The distance (in blocks) that a player can reach.
|
||||||
*/
|
*/
|
||||||
default double getReachDistance(Player player) {
|
default double getReachDistance(Player player) {
|
||||||
return player.isCreative() ? 5 : 4.5;
|
return Player.getPickRange(player.isCreative());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,8 +4,13 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.platform;
|
package dan200.computercraft.shared.platform;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.DataResult;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.util.ExtraCodecs;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@ -22,4 +27,22 @@ public interface RegistryEntry<U> extends Supplier<U> {
|
|||||||
* @return This registered item.
|
* @return This registered item.
|
||||||
*/
|
*/
|
||||||
ResourceLocation id();
|
ResourceLocation id();
|
||||||
|
|
||||||
|
static <T> Codec<RegistryEntry<? extends T>> codec(Registry<T> registry) {
|
||||||
|
record HolderEntry<T>(ResourceLocation id, Holder<T> holder) implements RegistryEntry<T> {
|
||||||
|
@Override
|
||||||
|
public T get() {
|
||||||
|
return holder().value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Codec<RegistryEntry<? extends T>> codec = ResourceLocation.CODEC.flatXmap(
|
||||||
|
id -> registry
|
||||||
|
.getHolder(ResourceKey.create(registry.key(), id))
|
||||||
|
.map(x -> DataResult.success(new HolderEntry<>(id, x)))
|
||||||
|
.orElseGet(() -> DataResult.error(() -> "Unknown registry key in " + registry.key() + ": " + id)),
|
||||||
|
holder -> DataResult.success(holder.id())
|
||||||
|
);
|
||||||
|
|
||||||
|
return ExtraCodecs.overrideLifecycle(codec, x -> registry.lifecycle(x.get()), x -> registry.lifecycle(x.get()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.shared.platform;
|
|
||||||
|
|
||||||
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
|
|
||||||
import net.minecraft.core.IdMap;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.core.registries.Registries;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.inventory.MenuType;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
|
||||||
import net.minecraft.world.item.enchantment.Enchantment;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
|
||||||
import net.minecraft.world.level.material.Fluid;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mimics {@link Registry} but using {@link PlatformHelper}'s recipe abstractions.
|
|
||||||
*/
|
|
||||||
public final class RegistryWrappers {
|
|
||||||
public static final RegistryWrapper<Item> ITEMS = PlatformHelper.get().wrap(Registries.ITEM);
|
|
||||||
public static final RegistryWrapper<Block> BLOCKS = PlatformHelper.get().wrap(Registries.BLOCK);
|
|
||||||
public static final RegistryWrapper<BlockEntityType<?>> BLOCK_ENTITY_TYPES = PlatformHelper.get().wrap(Registries.BLOCK_ENTITY_TYPE);
|
|
||||||
public static final RegistryWrapper<Fluid> FLUIDS = PlatformHelper.get().wrap(Registries.FLUID);
|
|
||||||
public static final RegistryWrapper<Enchantment> ENCHANTMENTS = PlatformHelper.get().wrap(Registries.ENCHANTMENT);
|
|
||||||
public static final RegistryWrapper<ArgumentTypeInfo<?, ?>> COMMAND_ARGUMENT_TYPES = PlatformHelper.get().wrap(Registries.COMMAND_ARGUMENT_TYPE);
|
|
||||||
public static final RegistryWrapper<RecipeSerializer<?>> RECIPE_SERIALIZERS = PlatformHelper.get().wrap(Registries.RECIPE_SERIALIZER);
|
|
||||||
public static final RegistryWrapper<MenuType<?>> MENU = PlatformHelper.get().wrap(Registries.MENU);
|
|
||||||
|
|
||||||
public interface RegistryWrapper<T> extends IdMap<T> {
|
|
||||||
ResourceLocation getKey(T object);
|
|
||||||
|
|
||||||
T get(ResourceLocation location);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
T tryGet(ResourceLocation location);
|
|
||||||
|
|
||||||
default Stream<T> stream() {
|
|
||||||
return StreamSupport.stream(spliterator(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private RegistryWrappers() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K> void writeKey(FriendlyByteBuf buf, RegistryWrapper<K> registry, K object) {
|
|
||||||
buf.writeResourceLocation(registry.getKey(object));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K> K readKey(FriendlyByteBuf buf, RegistryWrapper<K> registry) {
|
|
||||||
var id = buf.readResourceLocation();
|
|
||||||
return registry.get(id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.pocket.core;
|
package dan200.computercraft.shared.pocket.core;
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
|
||||||
import dan200.computercraft.api.pocket.IPocketAccess;
|
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||||
@ -19,7 +18,6 @@ import dan200.computercraft.shared.network.server.ServerNetworking;
|
|||||||
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
@ -29,7 +27,10 @@ import net.minecraft.world.entity.player.Player;
|
|||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class PocketServerComputer extends ServerComputer implements IPocketAccess {
|
public class PocketServerComputer extends ServerComputer implements IPocketAccess {
|
||||||
private @Nullable IPocketUpgrade upgrade;
|
private @Nullable IPocketUpgrade upgrade;
|
||||||
@ -104,12 +105,6 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
|
|||||||
setPeripheral(ComputerSide.BACK, peripheral);
|
setPeripheral(ComputerSide.BACK, peripheral);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public Map<ResourceLocation, IPeripheral> getUpgrades() {
|
|
||||||
return upgrade == null ? Map.of() : Collections.singletonMap(upgrade.getUpgradeID(), getPeripheral(ComputerSide.BACK));
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable UpgradeData<IPocketUpgrade> getUpgrade() {
|
public @Nullable UpgradeData<IPocketUpgrade> getUpgrade() {
|
||||||
return upgrade == null ? null : UpgradeData.of(upgrade, getUpgradeNBTData());
|
return upgrade == null ? null : UpgradeData.of(upgrade, getUpgradeNBTData());
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import dan200.computercraft.impl.PocketUpgrades;
|
|||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.inventory.CraftingContainer;
|
import net.minecraft.world.inventory.CraftingContainer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||||
@ -19,8 +18,8 @@ import net.minecraft.world.item.crafting.RecipeSerializer;
|
|||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
public final class PocketComputerUpgradeRecipe extends CustomRecipe {
|
public final class PocketComputerUpgradeRecipe extends CustomRecipe {
|
||||||
public PocketComputerUpgradeRecipe(ResourceLocation identifier, CraftingBookCategory category) {
|
public PocketComputerUpgradeRecipe(CraftingBookCategory category) {
|
||||||
super(identifier, category);
|
super(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user